概要
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. 動作確認
- H5 画面の「電話」ボタン → ダイヤラー起動。
- 「現在地」ボタン → 権限許可後に Toast で緯度経度表示。
- 「ナビ」ボタン → Amap が目的地を指定して起動。