React Native之h5唤起APP配置
在项目中,经常会遇到需要 h5 落地页唤起 APP 的需求,这里通过 scheme 协议的方式来实现。
既然是通过 scheme 的方式实现,那么项目中就必须先配置这个。
1、在项目根目录找到 android 文件夹,在 app/src/main/AndroidManifest.xml 中增加如下配置
<intent-filter>
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<data android:scheme="videoapp" />
</intent-filter>
1
2
3
4
5
6
2
3
4
5
6
2、创建导航工具文件和配置深层链接处理
(1)、创建导航工具文件
// src/utils/navigation.js
import { createNavigationContainerRef } from '@react-navigation/native';
export const navigationRef = createNavigationContainerRef();
export function deepLinkNavigate(route, params) {
if (navigationRef.isReady()) {
navigationRef.navigate(route, params);
}
}
1
2
3
4
5
6
7
8
9
10
11
2
3
4
5
6
7
8
9
10
11
(2)、配置深层链接处理
// src/utils/deepLinkHandler.js
import { Linking } from 'react-native';
import { deepLinkNavigate } from './navigation';
// 处理URL解析
function parseDeepLink(url) {
if ( !url ) {
return null;
}
// 示例解析 videoapp://profile/123?name=John
const route = url.replace(/.*?:\/\//g, ''); // 移除scheme
const [pathSegment, id] = route.split('/').filter(Boolean);
const params = Object.fromEntries(new URLSearchParams(url.split('?')[1]));
return {
route: pathSegment,
params: { id, ...params },
};
}
// 统一处理链接
export function handleDeepLink(url) {
const parsed = parseDeepLink(url);
if ( !parsed ) {
return;
}
switch (parsed.route) {
case 'profile':
deepLinkNavigate('Profile', parsed.params);
break;
case 'search':
deepLinkNavigate('Search', parsed.params);
break;
case 'category':
deepLinkNavigate( 'Category', parsed.params );
break;
default:
deepLinkNavigate('Home');
}
}
// 初始化监听
export function initDeepLinkListeners() {
const linkingSubscription = Linking.addEventListener('url', ({ url }) => {
handleDeepLink(url);
});
return linkingSubscription.remove;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
3、在 NavigationContainer 所在的组件中增加如下配置:
import { useEffect } from 'react';
import { Linking } from 'react-native';
import { NavigationContainer } from '@react-navigation/native';
import { navigationRef } from '../utils/navigation';
import { initDeepLinkListeners, handleDeepLink } from '../utils/deepLinkHandler';
function AppNavigator () {
const linking = {
prefixes: [ 'videoapp://' ],
config: {
screens: {
Home: 'home',
Category: 'category',
Search: 'search',
Profile: 'profile',
},
},
};
useEffect(() => {
const cleanup = initDeepLinkListeners();
// 处理应用启动时的初始URL
Linking.getInitialURL()
.then( url => {
if (url) {
handleDeepLink(url);
}
})
.catch(console.error);
return cleanup;
}, []);
return (
<NavigationContainer ref={navigationRef} linking={ linking }>
<Stack.Navigator screenOptions={ {
headerTitleAlign: 'center',
}}>
<Stack.Screen
name="Main"
component={MainTabNavigator}
options={{ headerShown: false }}
/>
...
</Stack.Navigator>
</NavigationContainer>
);
}
export default AppNavigator;
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
到此,打包后,即可在 h5 页面通过 scheme 协议唤起该 APP。
例如:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<button class="btn">按钮</button>
<script>
function openApp() {
const iframe = document.createElement('iframe');
iframe.style.display = 'none';
iframe.src = 'videoapp://search';
document.body.appendChild(iframe);
setTimeout(() => {
document.body.removeChild(iframe);
}, 500);
}
var btn = document.querySelector('.btn')
btn.onclick = function () {
openApp()
}
</script>
</body>
</html>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
注意:
1、推荐始终使用全小写 Scheme(如 videoapp://),避免驼峰式命名
2、确保 AndroidManifest.xml、React Navigation 的 prefixes、H5 链接三者的 Scheme 完全一致(包括大小写)
3、如果要使用驼峰式命名,则必须在 AndroidManifest.xml 和 React Navigation 的 prefixes 声明大小写
AndroidManifest.xml 中:
<data android:scheme="videoApp" /> <data android:scheme="videoapp" />
React Navigation 的 prefixes:
prefixes: ['videoapp://', 'videoApp://']
编辑 (opens new window)