leiwuhen-67's blog leiwuhen-67's blog
首页
    • 《Vue》笔记
    • 《React》笔记
    • 《NodeJs》笔记
    • 《CSS》笔记
    • 《Redis》笔记
    • 基础入门
    • 《Mock》笔记
    • 《MySQL》笔记
    • 《Git》相关
影音视听
收藏
关于
GitHub (opens new window)

我的公众号

首页
    • 《Vue》笔记
    • 《React》笔记
    • 《NodeJs》笔记
    • 《CSS》笔记
    • 《Redis》笔记
    • 基础入门
    • 《Mock》笔记
    • 《MySQL》笔记
    • 《Git》相关
影音视听
收藏
关于
GitHub (opens new window)
  • React

  • React Native

    • React Native之打包安卓apk优化
    • React Native之安卓apk架构区别解析
    • React Native之打包安卓修改Apk文件名
    • React Native之项目创建以及路由配置
    • React Native之h5唤起APP配置
    • React Native之安卓应用保存图片到相册
  • 《React》笔记
  • React Native
心欲无痕
2025-05-26

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、创建导航工具文件和配置深层链接处理
(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)、配置深层链接处理

// 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

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

到此,打包后,即可在 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

注意:

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)
React Native之项目创建以及路由配置
React Native之安卓应用保存图片到相册

← React Native之项目创建以及路由配置 React Native之安卓应用保存图片到相册→

Theme by Vdoing
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式