使用 React Native UIKit 为声网视频通话创建会议 URL

加入视频通话最快捷的方法是通过点击专属链接(unique link)。下面这个教程会教大家如何使用 React Native 框架下的通用链接打开用 React Native UIKit 搭建的视频通话或直播推流 app。

想了解更多关于 React Native UIKit 的信息,可查看 GitHub。点击 这里 获得本文项目的完整版。


前期准备

  • Node.js LTS
  • Expo CLI (npm i -g expo-cli )
  • 了解 React Native 和 Expo 的基础知识

为了方便大家快速了解基础样板,我用 expo-cli 创建了一个 tabs (TypeScript) 模板项目。大家可以跟着我逐步操作,首先,执行 expo-cli init ,看到选择模板的提示时,选择 tabs 选项。所有使用 react-navigation 库的 app 都可以采取以上步骤。

要在 Expo 项目中使用 UIKit,需要安装 expo-dev-client 包(expo install expo-dev-client )和声网Agora Native UIKit 包(npm i agora-rn-uikit react-native-agora )。


用 Expo 使用链接

有两种链接到 app 的方式:深度链接和通用链接。深度链接类似这个链接:exp://com.uikit/screen-one?data=hello 。深度链接不使用 http/https 协议,它使用的 scheme。Expo app 的 scheme 被设置为 exp ,大家可以根据自己的 app 作出相应改变,这里我们使用 uikit://

通用链接是 app 支持的常见 web URL。例如,https://myapp.com/screen-one?data=hello 这样的 URL 可以在网站中打开,也可以直接在支持该链接的 app 中打开。我们接下来会讨论如何使用深度链接和通用链接。如果对本文的理念有任何疑惑,可以查看 Expo docs 资源库。

更新 app.json 文件夹,为通用链接定义支持,使用 example.com 作为主机名:

"scheme": "uikit",
...
"ios": {
	"supportsTablet": true
	"supportsTablet": true,
	"bundleIdentifier": "com.ekaansh.uikitlink",
	"infoPlist": {
		"LSApplicationQueriesSchemes": ["uikit"],
		"NSCameraUsageDescription": "camera perm",
		"NSMicrophoneUsageDescription": "mic perm"
	},
	"associatedDomains": ["applinks:example.com"]
},
...
"android": {
	...
	"package": "com.ekaansh.uikitlink",
	"intentFilters": [
	{
		"action": "VIEW",
		"data":{
			"scheme": "https",
			"host": "*.example.com"
		},
		"category": [
			"BROWSABLE",
			"DEFAULT"
		]
	}
	]
},

保存更改,执行 expo prebuild 。这样可以改变本地项目文件(如 AndoidManifest.xmlinfo.plist ),添加域名配置。


设置域名

IOS 系统的 AASA 配置

要在 IOS 系统上使用通用链接,必须首先从 web 服务器提供一个 Apple App Site Association (AASA)文件,以验证域名是否属于本人。该文件必须由 /.well-known/apple-app-site-association 提供(不能延展)。在 CDN 上添加合适的标头,确保这个文件以 Content-Type=application/pkcs7-mime 为标头。

示例 AASA 文件如下:

{
  "applinks": {
    "apps": [],
    "details": [{
      "appID": "<APPLE_TEAM_ID.APP_BUNDLE_ID>",
      "paths": ["*"]
    }]
  }
}

可以用下面示例中的 vercel.json 文件给 vercel 设置标头:

{
  "headers": [{
    "source": "/apple-app-site-association"
    "headers" : [{
      "key" : "Content-Type",
      "value" : "application/pkcs7-mime"
    }]
  }]
}

如果你想获得更多 AASA 的 format,可查看 Apple 文档。


在安卓系统中验证域名(可选)

点击通用链接时,默认会出现选择 app 的对话框。如果不想弹出选择 app 的对话框,并且让链接总是打开特定 app,必须在 /.well-known/assetlinks.json 上发布一个 JSON 文件,说明安卓 app ID 和 app 应打开的链接,更多信息请查看安卓文档 。


设置链接

更新 navigation/LinkingConfiguration.tsx 文件中的 prefix 来支持通用链接:

prefixes: [‘https://example.com', Linking.createURL(‘/’)]

这样,app 路由可以同时处理通用链接和深度链接。

现在,修改第二屏幕(./screens/TabTwoScreen.tsx)以打开 UIKit,把该频道保存为状态变量。我们会在 URL 中添加一个监听器,从查询中提取频道并更新状态。

import { StyleSheet } from 'react-native';
import AgoraUIKit from 'agora-rn-uikit';
import * as Linking from 'expo-linking';
import { Text, View } from '../components/Themed';
import { useEffect, useState } from 'react';

export default function TabTwoScreen() {
	const [channel, setChannel] = useState('')

	Linking.addEventListener('url', (u) => {
		let query = Linking.parse(u.url).queryParams
		if(query.channel) {
			setChannel(query.channel)
		}
	})
...

然后,创建 useEffect 钩子,当通过通用链接打开 app 时,用useEffect 钩子从查询中获取频道。接下里,使用 getInitialUrlparse 方法提取频道,更新状态:

...
	useEffect(() => {
		const fn = async () => {
			let link
			link = await Linking.getInitialURL();
			if (link) {
				let query = Linking.parse(link).queryParams
				if(query.channel) {
					console.log('joining channel', query.channel)
					setChannel(query.channel)
				}
			}
		}
	fn()
	}, [])
...

最后,渲染 UIKit。记得一定要把你的 App ID 添加到 rtcProps

...
	return (
		<View style={styles.container}>
			{channel ?
				<AgoraUIKit
					styleProps={{ UIKitContainer: { flex: 1, height: '100%', width: '100%', backgroundColor: '#ff00ff' } }}
					rtcProps={{ appId: '<YourAgoraAppID>', channel: channel }}
					callbacks={{EndCall: () => {setChannel('')}}}
				/> :
				<Text> Didn't get Channel </Text>
			}
		</View>
	);
}
const styles = StyleSheet.create({
	container: {flex: 1,alignItems: 'center',justifyContent: 'center'},
});

可以使用 expo 的 Linking ,调用深度链接 uikit://two?channel=test ,从而在 app 内打开 UIKit 屏幕。我添加了一个 <Text> 组件以导航到 ./screens/TabOneScreen.tsx 中的 UIKit:

const  createLink = () => {
	const  ts = new  Date().getTime()
	let  link = Linking.createURL(`/?channel=${ts}`)
	return  link
}

生成链接

调用 JavaScript 中的 Date 对象来使用当前时间戳,这是生成专属链接的速成法。可以用下面这个简易函数创建一个聊天室:

const  createLink = () => {
	const  ts = new  Date().getTime()
	let  link = Linking.createURL(`/?channel=${ts}`)
	return  link
}

总结

使用 React Native 和 Expo 设置安卓和 iOS 系统都兼容的通用链接可不容易,本教程教给大家的是一个相对较容易的方法~

如果想了解更多信息,可以参考 ExpoReact Navigation 文档。

如果你在学习这篇教程或使用声网 React Native UIKit 时遇到任何问题,欢迎随时在GitHub 仓库提出功能需求或报告 bug。


原文作者:Ekaansh Arora
原文链接:https://www.agora.io/en/blog/use-meeting-urls-for-an-agora-video-call-with-the-react-native-uikit/
推荐阅读
相关专栏
SDK 教程
167 文章
本专栏仅用于分享音视频相关的技术文章,与其他开发者和声网 研发团队交流、分享行业前沿技术、资讯。发帖前,请参考「社区发帖指南」,方便您更好的展示所发表的文章和内容。