HarmonyOS WebView から H5 画面で電話・位置情報・ナビゲーションを呼び出す実装手順

概要

HarmonyOS(API 6)の JS FA プロジェクトで WebView 経由の H5 画面から、端末の電話アプリ・位置情報取得・外部地図アプリ(今回は Amap)を起動するまでをまとめます。JS と Java PA の橋渡し(addJsCallback)を軸に、各機能を最小構成で実装します。

1. H5 画面の準備

entry/src/main/resources/rawfile/demo.html に以下を配置します。3 つのボタンが、それぞれ異なる JavaScript インターフェースを呼び出します。

<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8">
  <title>デモ</title>
</head>
<body>
  <button onclick="callNative('tel')">電話</button>
  <button onclick="callNative('loc')">現在地</button>
  <button onclick="callNative('nav')">ナビ</button>

  <script>
    function callNative(type) {
      switch (type) {
        case 'tel':
          window.NativeDialer && NativeDialer.invoke('10086');
          break;
        case 'loc':
          window.NativeLocator && NativeLocator.invoke('');
          break;
        case 'nav':
          window.NativeNavigator && NativeNavigator.invoke('東京タワー');
          break;
      }
    }
  </script>
</body>
</html>

2. 電話アプリを起動する

H5AbilitySlice.java にて WebView にコールバックを登録し、Intent.ACTION_DIAL でダイヤラーへ遷移します。

webView.addJsCallback("NativeDialer", new JsCallback() {
    @Override
    public String onCallback(String number) {
        Intent intent = new Intent();
        intent.setAction("ohos.intent.action.dial");
        intent.setUri(Uri.parse("tel:" + number));
        startAbility(intent);
        return "dial sent";
    }
});

3. 位置情報を取得する

3.1 権限設定

config.json の module セクションに以下を追加。

"reqPermissions": [
  { "name": "ohos.permission.LOCATION",
    "reason": "$string:location_reason",
    "usedScene": { "ability": ["com.example.demo.H5Ability"], "when": "always" }
  }
]

3.2 動的権限リクエスト

private static final int REQ_LOC = 100;

private void requestLocIfNeeded() {
    if (verifySelfPermission("ohos.permission.LOCATION") != IBundleManager.PERMISSION_GRANTED) {
        requestPermissionsFromUser(new String[]{"ohos.permission.LOCATION"}, REQ_LOC);
    } else {
        fetchOnce();
    }
}

3.3 現在地取得

private void fetchOnce() {
    Locator locator = new Locator(this);
    RequestParam param = new RequestParam(RequestParam.SCENE_NAVIGATION);
    locator.requestOnce(param, new LocatorCallback() {
        @Override
        public void onLocationReport(Location loc) {
            new ToastDialog(getContext())
                .setText("緯度=" + loc.getLatitude() + ", 経度=" + loc.getLongitude())
                .show();
        }
        // 他のコールバック省略
    });
}

H5 側への登録:

webView.addJsCallback("NativeLocator", msg -> {
    requestLocIfNeeded();
    return "loc requested";
});

4. 外部地図アプリでナビゲーション

GeoConvert で目的地を緯度経度に変換し、Amap の Scheme URL で起動します。

webView.addJsCallback("NativeNavigator", destName -> {
    try {
        GeoConvert convert = new GeoConvert();
        List<GeoAddress> list = convert.getAddressFromLocationName(destName, 1);
        if (list.isEmpty()) return "no result";
        GeoAddress addr = list.get(0);

        Intent intent = new Intent();
        Operation op = new Intent.OperationBuilder()
            .withAction("android.intent.action.VIEW")
            .withUri(Uri.parse("androidamap://navi?sourceApplication=demo&lat="
                               + addr.getLatitude() + "&lon=" + addr.getLongitude()
                               + "&dev=1&style=2"))
            .withFlags(Intent.FLAG_NOT_OHOS_COMPONENT)
            .build();
        intent.setOperation(op);
        startAbility(intent);
    } catch (Exception e) {
        e.printStackTrace();
    }
    return "navi started";
});

5. WebView の初期化

WebView web = (WebView) findComponentById(ResourceTable.Id_webview);
web.getWebConfig().setJavaScriptPermit(true);
web.setWebAgent(new WebAgent() {
    @Override
    public ResourceResponse processResourceRequest(WebView w, ResourceRequest r) {
        // rawfile 配下の demo.html を返却
        Uri uri = r.getRequestUrl();
        if ("com.example.demo".equals(uri.getDecodedAuthority())
                && uri.getDecodedPath().startsWith("/rawfile/")) {
            String path = "entry/resources/rawfile/demo.html";
            try (Resource res = getResourceManager().getRawFileEntry(path).openRawFile()) {
                return new ResourceResponse("text/html", res, null);
            } catch (IOException ignore) {}
        }
        return super.processResourceRequest(w, r);
    }
});
web.load("https://com.example.demo/rawfile/demo.html");

6. 動作確認

  1. H5 画面の「電話」ボタン → ダイヤラー起動。
  2. 「現在地」ボタン → 権限許可後に Toast で緯度経度表示。
  3. 「ナビ」ボタン → Amap が目的地を指定して起動。

タグ: HarmonyOS webview JSBridge location Intent

8月19日 01:33 投稿