当前位置:   article > 正文

【HarmonyOS】一文教你如何在H5页面中使用电话、定位及导航_h5拨打电话

h5拨打电话

 【关键字】

HarmonyOS、H5页面、拨打电话、获取系统定位、跳转高德地图导航

【1、写在前面】

上一篇中我们带领大家实现了一个在低码项目中跳转加载H5页面的功能,有兴趣的可以参考以下文章:

华为开发者论坛:【HarmonyOS】一文教你如何在低代码项目中跳转H5页面

今天我们继续在上一篇的基础上继续开发,这次我们要实现的功能是在H5页面中点击按钮实现:①拨打电话、②获取系统定位、③拉起第三方地图应用开启导航功能(本文以高德地图为例),本项目是基于API6的JS工程,项目中使用的是JS FA调用Java PA机制(Java中使用WebView组件加载H5页面),OK,下面一起来实战一下吧。

完整代码见文末。

【2、H5页面】

想要实现上面的效果,我们的核心技术点就是JS跟Java的数据交互,可以参考以下官方文档中的实现:

文档中心

首先准备一个H5页面,页面内容很简单,就是3个按钮,每个按钮绑定一个点击事件,点击事件中是JS调用Java的代码,然后将该文件放在本地entry/src/main/resources/rawfile目录下,这里仅仅是简单写一个H5页面做为测试使用,实际项目开发中此部分内容可以不用看,以实际H5页面地址为准。内容如下:

cke_105314.png

关于加载本地H5页面可以参考文档中的写法,文档地址如下:

文档中心

cke_119739.png

【3、拨打电话】

前面在H5页面中已经定义了JS调用Java端的方法名及参数,这里参考文档中的写法:

文档中心

cke_134200.png

然后在Java侧实现addJsCallback(),在回调方法onCallback中实现具体的拨打电话的业务逻辑:

cke_151115.png

【4、获取定位】

想要获取系统的位置信息,首先需要获取定位权限,关于权限的获取可以参考这篇文章中的实现:

鸿蒙动态权限申请完整规范流程和操作详解-开源基础软件社区-51CTO.COM

我们这里获取的是LOCATION权限,需要在config.json文件的module中添加权限配置,

cke_162052.png

然后需要编写动态获取权限的代码:

cke_175245.png

在获取权限之后,就可以编写获取位置信息的代码了,关于如何获取位置信息可以参考这篇文章:

HarmonyOS使用Java获取位置信息-java获取当前位置

cke_188415.png

location对象中就可以获取到经纬度等位置信息了。然后同样的需要实现onCallback()方法:

cke_201582.png

【5、跳转导航】

这里我们是通过(逆)地理编码转化结合Scheme跳转来实现拉起导航功能的,(逆)地理编码转化的参考文档如下:

文档中心

高德地图导航的Scheme协议要求如下:

导航-Android-开发指南-高德地图手机版 | 高德地图API

跳转的代码就很简单啦:

cke_214791.png

同样的需要实现onCallback()方法:

cke_227980.png

【6、实现效果】

最后来看一下实现的效果吧:

6b090fab1b119aafeff78d716d41fc54_376x815.gif%40900-0-90-f.gif

【7、完整代码】

test.html文件:

  1. <!DOCTYPE html>
  2. <html>
  3. <head>
  4. <meta charset="utf-8">
  5. <title>测试页面</title>
  6. <script>
  7. function callToApp() {
  8. if (window.JsCallbackToCall && window.JsCallbackToCall.call) {
  9. var result = JsCallbackToCall.call("10086");
  10. }
  11. }
  12. function locationToApp() {
  13. if (window.JsCallbackToLocation && window.JsCallbackToLocation.call) {
  14. var result = JsCallbackToLocation.call("");
  15. }
  16. }
  17. function naviToApp() {
  18. if (window.JsCallbackToNavi && window.JsCallbackToNavi.call) {
  19. var result = JsCallbackToNavi.call("南京市玄武湖");
  20. }
  21. }
  22. </script>
  23. </head>
  24. <body>
  25. <div align="center">
  26. <button type="button" id="btn_call" "callToApp()">电话</button>
  27. <button type="button" id="btn_location" "locationToApp()">定位</button>
  28. <button type="button" id="btn_navi" "naviToApp()">导航</button>
  29. </div>
  30. </body>
  31. </html>

相关文本字段strings.json中:

  1. {
  2. "name": "permission_location",
  3. "value": "定位原因"
  4. }

index.js中跳转H5Ability.java页面代码:

  1. gotoH5Ability() {
  2. featureAbility.startAbility({
  3. want:
  4. {
  5. bundleName: "com.jarchie.h5",
  6. abilityName: "com.jarchie.h5.H5Ability"
  7. },
  8. });
  9. }

config.json中的权限配置:

  1. "reqPermissions": [
  2. {
  3. "name": "ohos.permission.INTERNET"
  4. },
  5. {
  6. "name": "ohos.permission.LOCATION",
  7. "reason": "$string:permission_location",
  8. "usedScene": {
  9. "ability": [
  10. "com.jarchie.h5.H5Ability"
  11. ],
  12. "when": "always"
  13. }
  14. }
  15. ]

H5Ability.java:

  1. import com.jarchie.h5.slice.H5AbilitySlice;
  2. import ohos.aafwk.ability.Ability;
  3. import ohos.aafwk.content.Intent;
  4. import ohos.agp.window.dialog.ToastDialog;
  5. import ohos.bundle.IBundleManager;
  6. import static com.jarchie.h5.slice.LocationAbilitySlice.MY_PERMISSIONS_REQUEST_LOCATION;
  7. public class H5Ability extends Ability {
  8. private H5AbilitySlice h5AbilitySlice;
  9. @Override
  10. public void onStart(Intent intent) {
  11. super.onStart(intent);
  12. super.setMainRoute(H5AbilitySlice.class.getName());
  13. }
  14. @Override
  15. public void onRequestPermissionsFromUserResult(int requestCode, String[] permissions, int[] grantResults) {
  16. super.onRequestPermissionsFromUserResult(requestCode, permissions, grantResults);
  17. switch (requestCode) {
  18. case MY_PERMISSIONS_REQUEST_LOCATION: {
  19. // 匹配requestPermissions的requestCode
  20. if (grantResults.length > 0
  21. && grantResults[0] == IBundleManager.PERMISSION_GRANTED) {
  22. // 权限被授予之后做相应业务逻辑的处理
  23. h5AbilitySlice.requestLocation();
  24. } else {
  25. // 权限被拒绝
  26. new ToastDialog(getContext()).setText("权限被拒绝").show();
  27. }
  28. return;
  29. }
  30. }
  31. }
  32. public H5AbilitySlice getH5AbilitySlice() {
  33. return h5AbilitySlice;
  34. }
  35. public void setH5AbilitySlice(H5AbilitySlice h5AbilitySlice) {
  36. this.h5AbilitySlice = h5AbilitySlice;
  37. }
  38. }

ability_h5.xml:

  1. <?xml version="1.0" encoding="utf-8"?>
  2. <DirectionalLayout
  3. xmlns:ohos="http://schemas.huawei.com/res/ohos"
  4. ohos:height="match_parent"
  5. ohos:width="match_parent"
  6. ohos:alignment="horizontal_center"
  7. ohos:orientation="vertical">
  8. <Text
  9. ohos:id="$+id:back"
  10. ohos:height="50vp"
  11. ohos:width="match_parent"
  12. ohos:start_margin="10vp"
  13. ohos:end_margin="10vp"
  14. ohos:text="返回"
  15. ohos:text_size="18vp"/>
  16. <ohos.agp.components.webengine.WebView
  17. ohos:id="$+id:webview"
  18. ohos:height="match_parent"
  19. ohos:width="match_parent"/>
  20. </DirectionalLayout>

H5AbilitySlice.java:

  1. import com.jarchie.h5.H5Ability;
  2. import com.jarchie.h5.ResourceTable;
  3. import ohos.aafwk.ability.AbilitySlice;
  4. import ohos.aafwk.content.Intent;
  5. import ohos.aafwk.content.Operation;
  6. import ohos.agp.components.Text;
  7. import ohos.agp.components.webengine.*;
  8. import ohos.agp.utils.TextTool;
  9. import ohos.agp.window.dialog.ToastDialog;
  10. import ohos.bundle.IBundleManager;
  11. import ohos.global.resource.Resource;
  12. import ohos.hiviewdfx.HiLog;
  13. import ohos.hiviewdfx.HiLogLabel;
  14. import ohos.location.*;
  15. import ohos.utils.net.Uri;
  16. import java.io.File;
  17. import java.io.FileInputStream;
  18. import java.io.IOException;
  19. import java.io.InputStream;
  20. import java.net.URLConnection;
  21. import java.util.List;
  22. public class H5AbilitySlice extends AbilitySlice {
  23. private static final HiLogLabel TAG = new HiLogLabel(HiLog.DEBUG, 0x0, H5AbilitySlice.class.getName());
  24. private Text backText;
  25. private WebView webView;
  26. // 定位
  27. public static final int MY_PERMISSIONS_REQUEST_LOCATION = 0;
  28. private Locator locator;
  29. private RequestParam requestParam;
  30. private MyLocatorCallback locatorCallback;
  31. @Override
  32. public void onStart(Intent intent) {
  33. super.onStart(intent);
  34. super.setUIContent(ResourceTable.Layout_ability_h5);
  35. H5Ability h5Ability = (H5Ability) getAbility();
  36. h5Ability.setH5AbilitySlice(this);
  37. initBackText();
  38. initWebView();
  39. callPhone();
  40. location();
  41. navi();
  42. }
  43. private void navi(){
  44. final String jsName = "JsCallbackToNavi";
  45. webView.addJsCallback(jsName, new JsCallback() {
  46. @Override
  47. public String onCallback(String msg) {
  48. gotoGaode(msg);
  49. return "jsResult";
  50. }
  51. });
  52. }
  53. // 获取定位
  54. private void location(){
  55. final String jsName = "JsCallbackToLocation";
  56. webView.addJsCallback(jsName, new JsCallback() {
  57. @Override
  58. public String onCallback(String msg) {
  59. requestPermission();
  60. return "jsResult";
  61. }
  62. });
  63. }
  64. // 拨打电话
  65. private void callPhone(){
  66. final String jsName = "JsCallbackToCall";
  67. webView.addJsCallback(jsName, new JsCallback() {
  68. @Override
  69. public String onCallback(String msg) {
  70. // 增加自定义处理
  71. Intent intent = new Intent();
  72. intent.setAction("ohos.intent.action.dial");
  73. intent.setUri(Uri.parse("tel:"+msg));
  74. startAbility(intent,0);
  75. return "jsResult";
  76. }
  77. });
  78. }
  79. private void gotoGaode(String destination){
  80. try {
  81. // (逆)地理编码转换
  82. GeoConvert geoConvert = new GeoConvert();
  83. List<GeoAddress> geoList = geoConvert.getAddressFromLocationName(destination, 1);
  84. GeoAddress geoAddress = geoList.get(0);
  85. if (geoAddress == null)
  86. return;
  87. Intent intent1 = new Intent();
  88. Operation operation = new Intent.OperationBuilder()
  89. .withAction("android.intent.action.VIEW")
  90. .withUri(Uri.parse("androidamap://navi?sourceApplication=amap&lat="+geoAddress.getLatitude()+"&lon="+geoAddress.getLongitude()+"&dev=1&style=2"))
  91. .withFlags(Intent.FLAG_NOT_OHOS_COMPONENT)
  92. .build();
  93. intent1.setOperation(operation);
  94. startAbility(intent1);
  95. }catch (Exception e){
  96. e.printStackTrace();
  97. }
  98. }
  99. private void requestPermission() {
  100. if (verifySelfPermission("ohos.permission.LOCATION") != IBundleManager.PERMISSION_GRANTED) {
  101. // 应用未被授予权限
  102. if (canRequestPermission("ohos.permission.LOCATION")) {
  103. // 是否可以申请弹框授权(首次申请或者用户未选择禁止且不再提示)
  104. requestPermissionsFromUser(new String[]{"ohos.permission.LOCATION"}, MY_PERMISSIONS_REQUEST_LOCATION);
  105. } else {
  106. // 显示应用需要权限的理由,提示用户进入设置授权
  107. new ToastDialog(getContext()).setText("请进入系统设置进行授权").show();
  108. }
  109. } else {
  110. // 权限已被授予
  111. requestLocation();
  112. }
  113. }
  114. public void requestLocation() {
  115. locator = new Locator(this);
  116. requestParam = new RequestParam(RequestParam.SCENE_NAVIGATION);
  117. locatorCallback = new MyLocatorCallback();
  118. locator.requestOnce(requestParam, locatorCallback); // 请求一次
  119. // locator.startLocating(requestParam, locatorCallback); // 多次请求 直接启动服务
  120. }
  121. public class MyLocatorCallback implements LocatorCallback {
  122. @Override
  123. public void onLocationReport(Location location) {
  124. if (location != null) {
  125. getUITaskDispatcher().asyncDispatch(() -> {
  126. // (逆)地理编码转换
  127. GeoConvert geoConvert = new GeoConvert();
  128. try {
  129. List<GeoAddress> list = geoConvert.getAddressFromLocation(location.getLatitude(), location.getLongitude(), 1);
  130. GeoAddress geoAddress = list.get(0);
  131. if (geoAddress == null)
  132. return;
  133. new ToastDialog(getContext())
  134. .setText("当前位置:经度:" + location.getLongitude() + "\n纬度:" + location.getLatitude()
  135. + "\n国家:" + geoAddress.getCountryName())
  136. .show();
  137. // "位置:" + geoAddress.getPlaceName()
  138. } catch (IOException e) {
  139. e.printStackTrace();
  140. }
  141. });
  142. }
  143. }
  144. @Override
  145. public void onStatusChanged(int type) {
  146. }
  147. @Override
  148. public void onErrorReport(int type) {
  149. }
  150. }
  151. // 初始化WebView
  152. private void initWebView() {
  153. webView = (WebView) findComponentById(ResourceTable.Id_webview);
  154. webView.getWebConfig().setJavaScriptPermit(true); // 如果网页需要使用JavaScript,增加此行
  155. webView.getWebConfig().setWebStoragePermit(true);
  156. webView.setWebAgent(new WebAgent() {
  157. @Override
  158. public ResourceResponse processResourceRequest(WebView webview, ResourceRequest request) {
  159. final String authority = "com.jarchie.h5";
  160. final String rawFile = "/rawfile/";
  161. final String local = "/local/";
  162. Uri requestUri = request.getRequestUrl();
  163. if (authority.equals(requestUri.getDecodedAuthority())) {
  164. String path = requestUri.getDecodedPath();
  165. if (TextTool.isNullOrEmpty(path)) {
  166. return super.processResourceRequest(webview, request);
  167. }
  168. if (path.startsWith(rawFile)) {
  169. // 根据自定义规则访问资源文件
  170. String rawFilePath = "entry/resources/rawfile/" + path.replace(rawFile, "");
  171. String mimeType = URLConnection.guessContentTypeFromName(rawFilePath);
  172. try {
  173. Resource resource = getResourceManager().getRawFileEntry(rawFilePath).openRawFile();
  174. ResourceResponse response = new ResourceResponse(mimeType, resource, null);
  175. return response;
  176. } catch (IOException e) {
  177. HiLog.info(TAG, "open raw file failed");
  178. }
  179. }
  180. if (path.startsWith(local)) {
  181. // 根据自定义规则访问本地文件
  182. String localFile = getContext().getFilesDir() + path.replace(local, "/");
  183. HiLog.info(TAG, "open local file " + localFile);
  184. File file = new File(localFile);
  185. if (!file.exists()) {
  186. HiLog.info(TAG, "file not exists");
  187. return super.processResourceRequest(webview, request);
  188. }
  189. String mimeType = URLConnection.guessContentTypeFromName(localFile);
  190. try {
  191. InputStream inputStream = new FileInputStream(file);
  192. ResourceResponse response = new ResourceResponse(mimeType, inputStream, null);
  193. return response;
  194. } catch (IOException e) {
  195. HiLog.info(TAG, "open local file failed");
  196. }
  197. }
  198. }
  199. return super.processResourceRequest(webview, request);
  200. }
  201. });
  202. webView.load("https://com.jarchie.h5/rawfile/test.html");
  203. }
  204. // 初始化返回文本
  205. private void initBackText() {
  206. backText = (Text) findComponentById(ResourceTable.Id_back);
  207. backText.setClickedListener(component -> onBackPressed());
  208. }
  209. @Override
  210. public void onActive() {
  211. HiLog.info(TAG, "onActive:");
  212. super.onActive();
  213. }
  214. @Override
  215. public void onForeground(Intent intent) {
  216. HiLog.info(TAG, "onForeground:");
  217. super.onForeground(intent);
  218. }
  219. @Override
  220. protected void onStop() {
  221. HiLog.info(TAG, "onStop:");
  222. super.onStop();
  223. locator.stopLocating(locatorCallback);
  224. }
  225. }
声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/笔触狂放9/article/detail/587983
推荐阅读
相关标签
  

闽ICP备14008679号