一、目标
APP 端实现 跳转其他APP 和 唤起APP,是区别 H5 端很重要的能力, 比如直接唤起本地邮箱发送邮件, 唤起 tiktok APP ,如果没有安装进入 安装下载商店。 同时如果链接是 网页端 还需要支持浏览器打开,下面将对 ios 和 android 分别实现上述功能
二、ios 端
1、处理地址的打开
处理 h5 端发送的打开某APP的消息,传入一个对象分别取scheme url和 该 app store 的地址,判断当前app地址在本机是否安装,未安装使用配置的 appStoreUrl 打开app store 下载页面
// h5 调用 native 打开联系人app
if([message isKindOfClass:[NSString class]] && [message isEqualToString:@"sharedApplication"]) {
NSURL *url = [NSURL URLWithString:messageData[@"url"]];
NSURL *appStoreUrl = [NSURL URLWithString:messageData[@"appStoreUrl"]];
NSLog(@"url appStoreUrl %@ %@", url , appStoreUrl);
// 检查应用是否可打开
if ([[UIApplication sharedApplication] canOpenURL:url]) {
// 应用已安装,打开应用
[[UIApplication sharedApplication] openURL:url options:@{} completionHandler:nil];
} else {
// 应用未安装,不进行任何操作或提示用户
// 可以在这里添加你自己的逻辑
// [self channelMessage:@"showToast" withData: @"Application not installed"];
[[UIApplication sharedApplication] openURL:appStoreUrl options:@{} completionHandler:nil];
}
}
设置webview 允许跳转,也可以这里拦截跳转的请求 进行设置
- (void)webView:(WKWebView *)webView decidePolicyForNavigationAction:(WKNavigationAction *)navigationAction decisionHandler:(void (^)(WKNavigationActionPolicy))decisionHandler{
//如果是跳转一个新页面
if (navigationAction.targetFrame == nil) {
[webView loadRequest:navigationAction.request];
}
decisionHandler(WKNavigationActionPolicyAllow);
};
2、判断是否安装某个app,配置 Queried URL Schemes
apple 手机上判断是否安装了哪个APP,是需要增加查询权限的, 需要查哪个APP就增加哪个
需要跳转哪个APP 就加上哪个APP的 scheme url 前缀
3、h5端跳转使用方式
ios 跳转 facebook 如果没有使用 appStoreUrl 进入下载页
iosBridge.pubSub.publish(messageKey.sendToNative, messageKey.sharedApplication, {
url: 'fb://profile/281216048311568',
appStoreUrl: 'itms-apps://itunes.apple.com/app/id579523206',
});
ios 跳转 邮箱示例
iosBridge.pubSub.publish(messageKey.sendToNative, messageKey.sharedApplication, {
url: `mailto:${email}`,
});
跳转网页
iosBridge.pubSub.publish(messageKey.sendToNative, androidBridgeMessage.sharedApplication, {
schemeUrl: "https://www.baidu.com",
packageName: "",
});
三、android 端实现
1、处理地址打开代码
@JavascriptInterface
fun sharedApplication(urlScheme:String) {
// 将字符串转换为 JSONObject
val jsonObj = JSONObject(urlScheme)
// 从 JSONObject 中获取 schemeUrl 和 packageName
val schemeUrl = jsonObj.getString("schemeUrl")
val packageName = jsonObj.getString("packageName")
// 使用获取的值
// 例如,打印到 Logcat
Log.d("URLScheme", "Scheme URL: $schemeUrl, Package Name: $packageName")
val intent: Intent
val isWebUrl = schemeUrl.startsWith("http://") || schemeUrl.startsWith("https://")
if (isWebUrl) {
// 网页 URL,直接打开
intent = Intent(Intent.ACTION_VIEW)
intent.setData(Uri.parse(schemeUrl))
startActivity(intent)
return;
} else {
// scheme URL,尝试打开应用
intent = Intent(Intent.ACTION_VIEW)
intent.setPackage(packageName)
intent.setData(Uri.parse(schemeUrl))
}
// 尝试获取可以处理 Intent 的 Activity
val pm = packageManager;
val componentName = intent.resolveActivity(pm)
if (componentName != null) {
// 应用已安装,可以打开
startActivity(intent)
} else {
val url = "https://play.google.com/store/apps/details?id=$packageName"
startActivity(Intent(Intent.ACTION_VIEW, Uri.parse(url)))
}
}}
仍然是传入一个对象,当判断是 http 开头,当网页URL 打开, 如果废 http 开头地址,当app 打开, 判断本机有没有 安装该 app 是通过 packageManager 来判断的, 如果未安装 进入 google play进行下载安装
2、判断是否安装了 APP
安卓上判断是否安装某个应用是在 ANdroidManifest.xml 中通过 queries 查询特定包名来实现的,依然是用到哪个app 就声明哪个
<queries>
<!-- 查询特定包名的应用 -->
< package android:name= "com.google.android.youtube" />
< package android:name= "com.ss.android.ugc.trill" />
< package android:name= "com.google.android.youtube" />
< package android:name= "com.twitter.android" />
< package android:name= "com.linkedin.android" />
< package android:name= "com.whatsapp" />
< package android:name= "org.telegram.messenger" />
< package android:name= "com.discord" />
< package android:name= "com.zing.zalo" />
< package android:name= "com.instagram.android" />
< package android:name= "com.kalodata.kalodata_android" />
< package android:name= "com.google.android.gm" />
< package android:name= "com.zhiliaoapp.musically" />
<intent>
<action android:name= "android.intent.action.VIEW" />
<category android:name= "android.intent.category.BROWSABLE" />
< data android:scheme= "http" />
</intent>
</queries>
3、h5 端跳转使用方式
下面是跳转youtobe 示例
androidBridge.pubSub.publish(androidBridgeMessage.sendToNative, androidBridgeMessage.sharedApplication, {
schemeUrl: 'youtube://channel/UCzs4yLr71NYjClyoCClwi0A',
packageName: 'com.google.android.youtube',
});
下面是打开 email 示例
androidBridge.pubSub.publish(androidBridgeMessage.sendToNative, androidBridgeMessage.sharedApplication, {
schemeUrl: `mailto:${email}`,
packageName: "com.google.android.gm",
});
跳转网页
androidBridge.pubSub.publish(androidBridgeMessage.sendToNative, androidBridgeMessage.sharedApplication, {
schemeUrl: "https://www.baidu.com",
packageName: "",
});
四、总结
处理app跳转打开是很常见的Native端需求, 在iOS或者Android上实现该功能大体上思路是一致的,先声明想要查询的app,这样才有能力调用端上查询能力,查询该APP是否在本机安装了,没有安装跳转到特定的商店进行下载,同时也要处理好外部网页的跳转