如果你想给视频通话开发一个分享链接,方便你的用户的朋友通过链接直接加入某个视频通话或直播推流,方法一是你的用户向朋友分享聊天室代码,让其朋友把这个代码敲到他们自己的应用上;方法二是让朋友通过用户分享的链接直接进入聊天室,这就需要通用链接。很明显方法二更好,而方法二就需要搭建通用链接。
什么是通用链接?
大部分情况下,应用视图都有等效的网页视图。例如,你可以在手机上的网页浏览器上打开 instagram 个人中心,也可以在 instagram 应用打开这个视图,而通用链接就是把网页浏览器上的内容显示到应用上的“通道”。
在有些情况下,我们不能通过通用链接打开网页,比如,有些复杂的游戏不能在网页浏览器上运行,如果点击专属链接,就会直达模板页面并将模板页面传递给应用,应用会渲染所有内容或加入游戏。
可查看 Apple 文档获取更多关于通用链接的信息:
通用链接也适用于安卓系统,但网站设置和设备略有不同。
前期准备
设置通用链接
通用链接很好设置,主要分两步:
1.设置网站
2.设置应用
我们先从网站端设置开始。
设置网站
这一步应该是通用链接最简单的部分,只需要添加一个名为 apple-app-site-association
的文件,该文件包含了应用程序的正确值:
{
"applinks": {
"apps": [],
"details": [{
"appIDs": ["DEVELOPMENT_TEAM.PRODUCT_BUNDLE_IDENTIFIER"],
"components": [
{
"/": "*"
}
]
}]
}
}
上述示例会在网站的每个页面分别设置一个通用链接按钮,下文会教大家如何在自己的域名下设置特定的 URL。
只需要用你的应用的关联值替换 DEVELOPMENT_TEAM 和 PRODUCT_BUNDLE_IDENTIFIER 。要找到这些相关值,可以找到项目的根文件夹的终端,在终端中运行几个命令,例如:
grep -r -m 1 "DEVELOPMENT_TEAM" .; grep -r -m 1 "PRODUCT_BUNDLE_IDENTIFIER" .
你的终端与下列代码类似:
=> grep -r -m 1 "DEVELOPMENT_TEAM" .; grep -r -m 1 "PRODUCT_BUNDLE_IDENTIFIER" .
./AppName.xcodeproj/project.pbxproj: DEVELOPMENT_TEAM = 278494H572;
./AppName.xcodeproj/project.pbxproj: PRODUCT_BUNDLE_IDENTIFIER = io.agora.AppName;
本示例中,我们需要的值分别是 278494H572
和 io.agora.AppName
。
为确保网站设置正确,可点击查看 branch.io’s validator。常见问题之一是找不到 content-type
标头,如果你也遇到这个问题,需要创建或添加以下代码到 .htaccess
,与 apple-app-site-association
文件的位置相同:
<Files "apple-app-site-association">
ForceType 'application/json'
</Files>
按照上述设置,网站的所有页面都可以链接到指定的应用。如果你只想把网站的特定部分链接到应用,可以修改组件数组对象或再添加一个组件数组。例如,我们用下面的代码替代当前的组件数组:
"components": [
{ "/": "/wwdc/news" },
{ "/": "/videos/wwdc/2015/*" }
]
那么所有的 WWDC 新闻文章和 2015 年之后的视频就可以被导入应用。
点击 Apple 文档 查看更多示例。
我们打算在应用中添加下列组件:
{
"/": "/join*",
"?": { "channel": "?*" }
}
我们用 example.com 作为域名地址,以下是完整 URL 的示例:
https://www.example.com/join?channel=dkvn3lw2
想查看更多用 apple-app-site-association
文件设置通用链接的信息,可以点击 这里 查看 WWDC 2019 的相关资源。
完整文件如下:
{
"applinks": {
"details": [
{
"appIDs": ["DEVELOPMENT_TEAM.PRODUCT_BUNDLE_IDENTIFIER"],
"components": [
{
"/": "/join/*",
"?": {
"channel": "?*"
}
}
]
}
]
}
}
以上就是所有设置,接下来是对应用的设置。
设置应用
安装工具包
在 Xcode 中设置一个新的 SwiftUI 应用,通过以下 URL 把 Swift 安装包添加到你的项目中:
https://github.com/AgoraIO-Community/iOS-UIKit.git
截止 2022 年 3 月 16 日,UIKit 的稳定版本为 1.7.1。
如果不知道怎么添加 Swift 安装包,可查看 Apple 文档中的具体步骤:
设置视图
因为本文的主要内容是通用链接,所以这一部分我们就简单介绍一下。首先,添加一个用于创建和加入频道的按钮:
Button {
// click action here
} label: {
Text("Create Channel")
.padding().background(.green).cornerRadius(30)
}
这个按钮可以创建频道名称并显示 AgoraViewer。AgoraViewer 是 View 的子类,由 UIKit 提供,可通过下列代码块实现:
import SwiftUI
import AgoraRtcKit
import AgoraUIKit_iOS
struct ContentView: View {
@State var channelName: String?
@State var isShowingVideo: Bool = false
var videoCallView: some View {
VStack {
HStack { /* Other buttons will be placed here */ }
ContentView.agview
}
}
static var agview: AgoraViewer = {
AgoraViewer(
connectionData: AgoraConnectionData(
appId: <#Agora App Id#>, rtcToken: <#Agora Token#>
), style: .floating
)
}()
var body: some View {
NavigationView {
ZStack {
NavigationLink(
destination: self.videoCallView
.navigationBarHidden(true)
.onAppear(perform: { /* appear action */ })
.onDisappear(perform: { /* disappear action */ }),
isActive: $isShowingVideo
) { EmptyView() }
HStack {
Button {
self.channelName = "test"
self.isShowingVideo = true
} label: {
Text("Create Channel")
.padding().background(.green).cornerRadius(30)
}
}
}
}
}
}
如上,频道被设置为静态字符串 "test"
,特性 isShowingVideo 被设置为 true。 在 GitHub 的最终产品里,“test”字符串会被替换为随机字符串生成器。
isShowingVideo 是一个布尔值,可以决定是否由 NavigationView 展示视频通话视图(videoCallView
)。接下来,我们需要用 onAppear 和 onDisappear 方法加入或离开频道,并在摄像头视图上方添加一些按钮。
.onAppear(perform: {
guard let channelName = self.channelName else {
self.isShowingVideo = false
return
}
ContentView.agview.join(
channel: channelName, with: nil, as: .broadcaster
)
})
.onDisappear(perform: {
ContentView.agview.viewer.leaveChannel()
})
视频视图出现时,如果 channelName 是 nil,我们就再次关闭视频视图,因为如果没有频道名称,就说明之前的阶段出现了错误。然后,我们从 Agora UIKit 中调用 builtin 函数,以主播角色加入频道。
加入方法中的第二个参数用于令牌,我在应用测试中没有使用令牌,但如果用声网搭建生产级应用需要用令牌。
想了解更多用声网 SDK 使用令牌的信息,可查看以下内容:
UI 设置的最后一步是在上述 videoCallView
中设置其他按钮。
var videoCallView: some View {
VStack {
HStack {
Button {
self.isShowingVideo = false
} label: {
Text("Exit")
.padding().background(.gray).cornerRadius(3)
}
Spacer()
Button {
guard let channelName = channelName,
let urlShare = URL(
string: "https://example.com/join?channel=\(channelName)"
) else { return }
let activityVC = UIActivityViewController(
activityItems: [urlShare],
applicationActivities: nil
)
let scenes = UIApplication.shared.connectedScenes
guard let windowScene = scenes.first as? UIWindowScene,
let window = windowScene.windows.first else { return }
window.rootViewController?.present(activityVC, animated: true, completion: nil)
} label: {
Text("Share")
.padding().background(.gray).cornerRadius(3)
}
}
ContentView.agview
}
}
上述代码段中已添加了两个按钮,这两个按钮被放置在 HStack
中,相邻放置,中间放了 Spacer()
。
用户可以点击第一个按钮退出当前视图、离开通话并返回主屏幕。点击第二个按钮可以创建一个用频道作为参数的 URL (用 example.com 作为域名),生成的 URL 会打开默认的共享屏幕,并通过 iMessage、AirDrop 和 email 等发送默认共享屏幕。
共享屏幕如下:
解释通用链接
想让应用解释通用链接,必须让应用知道它能够与哪个域名沟通。这是一个非常简单的项目,可以直接用 Xcode 完成。
在 Xcode 中找到你的应用,选中 Signing & Capabilities,像下面这样添加关联域功能:
完成之后,在新功能中设置域名:
上述条目是 applinks:example.com
和 applinks:www.example.com
。用托管 apple-app-site-association
的域名替代“example.com”。
最后,了解什么时候通过通用链接打开应用,并获取打开应用的完整 URL。
SwiftUI 提供了一个非常容易实现的方法来捕获打开应用程序的通用链接—— onOpenURL 方法。这个方法可以附加到任何 View 上,它唯一的参数是 URL 对象。我们可以把以下内容添加到 NavigationView 上:
NavigationView {
// Navigation View content here
}.onOpenURL { url in
print(url.absoluteString)
}
通过通用链接打开应用时,以上代码段会执行并打印完整的 URL 字符串。
我们只需从中获得 URL 的最后一部分——频道参数。
我们把 URL 的部分内容提取到字典中,从下列 Stack Overflow 回答中获取 queryDictionary
特性并调用该特性:
使用 queryDictionary
获得频道名称,再次触发并打开视频传送:
if let channel = url.queryDictionary?["channel"] {
self.channelName = channel
self.isShowingVideo = true
}
应用搭建完成!现在,通过终端 join?channel=test
进入你的域名地址,可以启动你的应用,直接到设置频道名称这一步。
测试
可以在 GitHub 上查看完整项目:
运行应用时,确保在 Signing and Capabilities 中更新域名(默认设置为 example.com)。改变 Bundle 和 Team ID 后,立即在终端运行下列命令,获得新的值:
grep -r -m 1 "DEVELOPMENT_TEAM" .; grep -r -m 1 "PRODUCT_BUNDLE_IDENTIFIER" .
其他资源
想了解更多使用声网 SDK 搭建应用的信息,请查看声网Agora Video Call Quickstart Guide 和 声网 API Reference。
原文作者:Max Cobb
原文链接:Universal Links and SwiftUI Video Calls