React Native 下面Android 下的Deep link 配置
RN下面Android平台下的DeepLink 的配置与使用
deeplink vs weblink vs applink 参考这幅图
简单来说就是 deeplink 的scheme 可以是任意值, weblink 只能是http/https, 这两种方式都需要用户选择是否使用app打开链接。
applink 的schema 与weblink 一样,唯一的差别就是,不需要用户选择,直接打开app.
Note:目前applink 的方式配置还没有成功。
遇到的坑
- 不要将定制化的sheme 与http(s) 配置到同一个Intent里面,以下面为例,如果你配置了,那么结果将会是mypayment://add 不起作用, mypayment://localhost/add 会起作用。实际上有效的link 组合将会是 scheme 与host 的全排列。但是,如果你的link 配置不正确,跳转还是不会正常工作。
- 对于host, port 非 applink 的模式,其实这两个值随便配,哪怕是假的都可以,就是用来占坑用的。
- 对于applink, 一直没有成功,安装文档都配置好了,就是不工作,还是走的deeplink, weblink 的模式。证书,autoVerify 等等都配置了,就是不工作。
- 还有一个问题,如果让用户选择某个App 来打开链接,如果用户选择永远用浏览器打开,那么以后都会用浏览器打开。调试的时候可以在 Android 手机上面的Settings-> Apps&Notifications->Advanced->default apps 里面清除。被坑了好久。
- 实际上applink 已经成功了只是验证的方式有问题,验证applink 只能使用
adb shell am start -W -a android.intent.action.VIEW -d "https://localhost/setting" com.payment
, 不可以使用 uri-scheme来验证。
AndroidManifest.xml的配置
路径: android/app/src/main/AndroidManifest.xml
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.payment">
<uses-permission android:name="android.permission.INTERNET" />
<application
android:name=".MainApplication"
android:label="@string/app_name"
android:icon="@mipmap/ic_launcher"
android:roundIcon="@mipmap/ic_launcher_round"
android:allowBackup="false"
android:theme="@style/AppTheme">
<activity
android:name=".MainActivity"
android:label="@string/app_name"
android:configChanges="keyboard|keyboardHidden|orientation|screenLayout|screenSize|smallestScreenSize|uiMode"
android:launchMode="singleTask"
android:windowSoftInputMode="adjustResize"
android:exported="true">
<!-- autoVerify 需要网页配置文件配合来达到浏览器打开app效果 -->
<!-- 使用这个命令来验证 adb shell am start -W -a android.intent.action.VIEW -d "https://localhost/setting" com.payment -->
<intent-filter android:autoVerify="true">
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<!-- 如果想使用applink 只能使用一直https -->
<!-- https://localhost/.well-known/assetlinks.json 这个站点得有下面这个json 文件. -->
<data android:scheme="https" android:host="localhost"/>
</intent-filter>
<!-- 可以使用这个命令 npx uri-scheme open "mypayment://setting" \\-\\-android` -->
<!-- 这个命令也行 adb shell am start -W -a android.intent.action.VIEW -d "mypayment://setting" com.payment -->
<intent-filter android:label="custom scheme name">
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<data android:scheme="mypayment"/>
</intent-filter>
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
<!-- 下面这个配置项是用于配置路由,注意schema 那个data, -->
<!-- 10.0.2.2 对应的是windows 机器,在android emulator中,我们的开发机器就是这个ip,相当于localhost -->
<!-- 配置了三个路由 myPayment://10.0.2.2:8245/xxx -->
<!-- https://10.0.2.2:8246/xxx -->
<!-- http://10.0.2.2:8245/xxx -->
<!-- !!!!!!!!!!!!!!!坚决不推荐使用这种方式,这种方式最多只能拿到weblink,!!!!!!!!!! -->
<intent-filter>
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<!-- 不要采用注释掉的配置方法,否则一条也不会命中,实际上有效的link会是sheme 与host 的全排列 -->
<!-- <data android:scheme="myPayment"/>
<data android:scheme="https" android:host="10.0.2.2:8246"/>
<data android:scheme="http" android:host="10.0.2.2:8245"/> -->
<!-- 下面的配置是正确的 由于这个host 只是占位,不是applink, 所以不需要port, 对于实际的常见,我们一个intent-filter 只配置一个sheme,不要配多个 -->
<data android:scheme="myPayment"/>
<data android:scheme="https" />
<data android:scheme="http" />
<data android:host="localhost"/>
</intent-filter>
</activity>
</application>
</manifest>
由于开启了android:autoVerify="true",需要一个站点来提供app的签名认证,完整链接,
具体步骤如下:
keytool -list -v -keystore .\android\app\debug.keystore
产生app的签名,注意其中的SHA256这个hash。.\android\app\debug.keystore
,这个路径是相对于项目目录而言的。这个里面有个坑,需要密码。密码是android,- copy 其中的 SHA256签名,放入assetlinks.json 文件中,内容如下;如果copy下面文件,记得删除注释。
[{
"relation": ["delegate_permission/common.handle_all_urls"],
"target": {
"namespace": "android_app",
"package_name": "com.payment", // 这个是你app的名字,android/app/build.gradle 中的defaultConfig, applicationId
"sha256_cert_fingerprints":
["FA:C6:17:45:DC:09:03:78:6F:B9:ED:E6:2A:96:2B:39:9F:73:48:F0:BB:6F:89:9B:83:32:66:75:91:03:3B:9C"] // 这个第一步中的SHA256
}
}]
- 建立一个web 站点 域名为https://localhost , 在https://localhost/.well-know/assetlinks.json 放置第二步的配置项。
定义linking 来响应接受上面配置的路由参数,完整链接
代码示例
const config = {
screens: {
approval_setting: 'setting',// key screen 名字,value: 我们需要的路由,例如: http://10.0.2.2:8245/setting 将对应approval_setting screen
my_approvals: 'myapprovals',
submit_invoice: 'invoice',
}
};
const linking = {
prefixes: ['myPayment://', 'https://localhost'],
config,
};
function App(){
return (
<NavigationContainer linking={linking}>
xxx
</NavigationContainer>
)
}
测试link
小插曲,我一开始直接在浏览器中输入url: https://localhost/setting
,发现不起作用,实际上需要开发者工具,推荐 uri-scheme
这个npm 包,
直接运行npx uri-scheme open "https://localhost/setting" --android
就可以打开这个app.
验证deeplink 是否工作可以使用
npx uri-scheme open "https://localhost/setting" --android
adb shell am start -W -a android.intent.action.VIEW -d "https://localhost/setting" com.payment
推荐用这个来验证,也只有这个可以验证applink
link 的格式是 scheme://hostname/xxx