大多数浏览器和
Developer App 均支持流媒体播放。
-
为受限网络 创建本地推送连接
利用本地推送连接,从你的 app 服务器给处于无网络连接的网络中的设备传送通知。了解如何为在受限的网络环境中运行的 app 创建通知,帮助用户在受限的网络环境中也能拥有跟有网络连接的环境中先攻的可靠性和使用体验。我们一起来探索这个技术的技术细节,这样在你需要用到这项技术时,就可以在自己的 app 中实施了。
资源
-
下载
(你好 WWDC 2020)
大家好 欢迎来到 WWDC
你好 我叫 Paresh Sawant 我要讲的是 iOS 14 里的 新本地推送连接 API 推送通知非常好 能够将相关内容及时传给 你的 app 用户 然而 推送通知的传送依赖 Apple Push Notification Service 这个服务只有在设备 连接到互联网时才是可用的 有些人给我们发来反馈 说能够从他们的 app 服务器接收信息 是其 app 功能性的一个极其重要的部分 即便在没有互联网连接的情况下 也必须要继续工作 为了让大家的 app 能够满足这个要求 我们在 iOS 14 里添加了一个新 API 让大家能够创建自己的 基于 Wi-Fi 网络运作的 推送通知服务 首先 我会扼要说明一下 Apple 推送通知 然后我会讲一下如何使用新 API 建立 定制推送通知服务 之后 我会使用示例 app 来演示一下 这个新功能 然后我会详细介绍 使用这个新 API 的细节 那我们开始吧 你们当中肯定有许多人很熟悉推送通知 许多 app 使用推送通知 来发送新闻提醒、体育更新 即时通讯、接收 VoIP 网络语音电话 和许多其他信息 我们来回顾下其工作原理 你的服务商服务器给 Apple Push Notification Service 也就是人们所知的 APNs 发送一条推送通知请求 APNs 把相关通知载荷传送给 每个目标设备 一收到通知后 系统会把该载荷传送给设备上适当的 app 根据通知类型 你的 app 要么使用 PushKit 要么使用 UserNotifications 框架 来接收此载荷 APNs 是推送通知功能的核心 连接有 APNs 连接或因特网的网络 使用 app 时 对于 app 来说 推送通知才是正确选择 它是最佳选择 因为它实现了设备与 APNs 之间的连接 把通知传送给设备上的所有 app 推送通知为你的 app 提供 你所渴望的用户体验 最重要的是 它非常节能 所以 开发者应当更喜欢使用 PushKit 或者是 UserNotifications 框架 来处理他们服务器发来的通知 但是 如果你的 app 所使用的网络环境是 APNs 所无法连接的 那这个 app 是无法接收这些通知的 举例来说 有些像是游轮、航班、野营地或医院 这类可能限制或没有 APNs 连接的地方 app 的推送通知功能在以上情况下 可能会受损 在为用户提供即时信息方面 推送通知发挥着非常重要的作用 它还让用户能够采取适当行动作为回应 所以在推送通知对用户尤为重要的情况下 即便是在受限的网络环境中 保持它的正常运转也是非常重要的 本地推送连接就是用来解决这个问题的 我们在 iOS 14 里添加了 本地推送连接 API 这是 API NetworkExtension 家族的 新成员 我们来看看它的工作原理 在这个新 API 的协助下 你可以建立一个 app 扩展 它能在一个本地 Wi-Fi 网络上 直接与你的服务商服务器通信 因为没有 APNs 你需要界定你自己的 在服务商服务器和 app 扩展之间的 协议来传送通知 你的 app 必须指定 你希望为你的 app 用户启动 本地推送连接的 Wi-Fi 网络 在设备加入指定的 Wi-Fi 网络时 系统会启动 app 扩展 app 扩展负责和服务商服务器 保持网络连接并接收通知 只要设备与指定的 Wi-Fi 网络处于 关联状态 app 扩展就能继续在后台运行 当设备与指定的 Wi-Fi 网络断开连接时 系统就会停止 app 扩展 现在 既然我们知道了这个 新本地推送连接 API 也回顾了正常的推送通知 我想讲一下 为 app 选择正确的 API 的 一般性指导方针 针对一般的推送通知请求 大家应当首选 PushKit 或 UserNotifications 框架 本地推送连接 API 是面向 一小部分非常特殊的案例的 这些案例主要由网络环境的限制 和这些环境中用户的要求决定 在通知非常重要 而网络环境受限的情况下 本地推送连接可以是最恰当的解决方案 要使用本地推送连接 API 实现特殊案例 你需要请求新授权 现在我们通过互相对比 来看看这两种机制的情况 新本地推送连接是在你的服务商服务器 和 app 扩展之间建立直接通讯 办法是在你指定的网络上使用你的协议 这完全由你来控制 现在我们来了解下 app 扩展 是如何处理不同类型的通知的 一收到面向用户的通知 你的 app 扩展使用本地通知来 引起用户的注意 app 扩展代码会使用 UserNotifications 框架 来创建和安排本地通知 它可以显示提醒、发出响声 或显现出你 app 的图标 比如说 一收到一条短信的通知 就像这里显示的那样 屏幕顶端会滚动出 一条横幅消息来提醒用户 app 扩展应该一直使用用户本地通知 来进行面向用户的通知
现在我们来看看 app 扩展是如何 处理 VoIP 网络语音电话通知的 这类通知传达的信息 是告诉你的 app 用户 VoIP 网络语音电话有来电
一收到 VoIP 通知 app 扩展会使用 NEAppPushProvider 类别 来向系统报告来电 系统对此做出回应 如果容器 app 没有在运行 系统会唤醒它 并把来电信息传递给它 就像这里展示的这样 容器 app 会使用 CallKit 框架 来显示来电用户界面 稍后我会详细讲述如何处理 app 里的 VoIP 通知 现在我们通过演示 app 看看这个 是怎么工作的 游轮的互联网要么连接受限 要么根本没网 或者有时游轮提供付费数据服务 这个演示版本里的游轮公司 开发了一个名为 SimplePush 的 app 该 app 在使用新的本地推送连接 API 来提供短信和 VoIP 网络语音电话服务 他们希望船上的朋友和家人们 使用该 app 来保持联系 Jane 和 John 是该 app 的用户 在演示版本里 当他们的设备没有联网时 他们使用 SimplePush app 来彼此沟通
这是 Jane 的设备 这是 John 的设备 我们来看一下 Jane 的设备上 SimplePush app 里的设置
设置包括服务商服务器的主机名 实现本地推送连接的 Wi-Fi 网络的 SSID 已经启动
就像大家在这里看到的那样 Jane 的设备连接到了游轮的 Wi-Fi
这些是 Jane 的联系人 我将用 Jane 的设备给 John 发一条短信 John 的设备上会显示该短信的通知 我们就从联系人中选择 John 轻点”信息“按钮 (新信息) 我输入 ”你好 John“…
然后轻点“发送”按钮 然后这条短信的通知出现在了 John 的设备上 John 轻点这条通知 在 SimplePush app 里打开这条短信
现在 Jane 语音呼叫 John…
然后 John 的设备上会显示来电用户界面 John 接通来电…
大家可以在这里看到通话正在进行
现在 John 挂断电话
这是 SimplePush app 在 iOS 14 里 使用新本地推送连接 API 的 一个简单演示 新本地推送连接 API 包括两个类别 NEAppPushManager 和 NEAppPushProvider 使用 NEAppPushManager 类别的是 容器 app app 扩展代码执行 NEAppPushProvider 类别的子类别
你的 app 扩展和容器 app 都需要由 NEAppPushProvider 授权 来使用该 API 容器 app 使用 NEAppPushManager 类别的一个实例 来创建一个配置 这个配置主要由 应该运行本地推送连接的 Wi-Fi 网络组成 你可以使用此类别载入、保存和删除 一个配置 如果你在执行 VoIP app NEAppPushManager 也会被用来 设置一个委托 来处理 VoIP 来电 你的 app 扩展执行 NEAppPushProvider 类别的一个子类别 这个类别决定了你在你的子类别里 必须覆盖的 生命周期管理方法 当 app 扩展被开启和停止时 系统会调用这些方法 当设备加入指定 Wi-Fi 网络时 app 扩展就被启动了 当设备和指定 Wi-Fi 网络断开连接 系统会停止 app 扩展 app 扩展开启时 会和其服务商服务器建立网络连接 并在停止时断开连接 一收到 VoIP 通知 app 扩展使用该类别向系统报告此来电 系统对此做出回应 唤醒容器 app 并把来电信息传递给它 现在我们来看看 app 如何使用 NEAppPushManager 类别 来创建配置 你需要导入 NetworkExtension 模块 来使用本地推送连接 API
为你的 app 推送服务商创建配置 非常简单
你需要创建 NEAppPushManager 类别的 一个实例 并用它来设置属性 matchSSIDs 明确指定了你希望开启 本地推送连接的 Wi-Fi 网络的 SSID 的一个区域
providerBundleIdentifier 是 app 扩展的包标示符 此设置让系统在需要时运行恰当的 app 扩展
providerConfiguration 是为 app 扩展 指定配置数据的 代码字典
最后 你需要设置 isEnabled 为”真“ 来使用该配置启动本地推送连接
在你把所有设置配置好后 调用 saveToPreferences 办法 来处理该配置 如果该配置成功保存 并启动了 系统会使用该配置启动本地推送连接 app 扩展执行 NEAppPushProvider 类别的子类别 并覆盖所需方法
系统调用 startwithcompletionHandler 来启动 app 扩展 在这个方法中 app 扩展和其服务器 建立一个网络连接 当停止使用 app 扩展时 系统调用 stopwithreason 在这个方法中 app 扩展断开 与服务器的连接 收到 VoIP 通知时 app 扩展调用 reportIncomingCall 来向系统报告这个 VoIP 来电 系统对此做出回应 如果容器 app 没有在运行 系统会唤醒它 并把来电信息传递给它 正如上一页幻灯片所展示的那样 app 扩展负责 向系统报告 VoIP 来电 系统做出回应 启动该 app 容器 app 必须执行 app 委托对象 遵循 UIApplicationDelegate 协议 以确保知道 app 进程何时启动的 app 启动时 你必须调用 loadAllFromPreferences 来载入所有已保存的配置 并为每个 NEAppPushManager 实例 设置 NEAppPushDelegate 对象 就像这里展示的那样
系统把用户信息代码字典传递给容器 app 办法就是 为 app 主队列上适当的 NEAppPushManager 实例 调用 didReceiveIncomingCallWithUser Info 委托方法 一收到用户信息 app 必须使用适当的 CallKit API 把来电报告给 CallKit 并让它显示来电用户界面 请大家查看 CallKit API 说明文档 来获取报告来电的细节 还请大家查阅 SimplePush 示例 app 来获取更多细节 请注意 为了接收来电信息 你的容器 app 必须在 Xcode 项目功能面板里 启动 VoIP 后台模式 就像这里展示的那样 现在大家了解了关于 iOS 14 里引入的 新本地推送连接 API 的 详细内容 我们来讲一下要在你的 app 使用推送 接下来该采取的几个步骤
对于 app 里绝大部分一般性的 推送通知要求 你该首选 PushKit 或 UserNotifications 框架
只有在 APNs 连接不可用 并且通知对你的用户非常必要的 网络条件下 你才应该使用本地推送连接
如果你认定本地推送连接对于你的 app 用户是最佳解决方法 记住 你必须请求 NEAppPushProvider 授权 来使用本地推送连接 API 欢迎大家的观看
-
-
10:07 - Create Configuration
import NetworkExtension let manager = NEAppPushManager() manager.matchSSIDs = [ "Cruise Ship Wi-Fi", "Cruise Ship Staff Wi-Fi" ] manager.providerBundleIdentifier = "com.myexample.SimplePush.Provider" manager.providerConfiguration = [ "host": "cruiseship.example.com" ] manager.isEnabled = true manager.saveToPreferences { (error) in if let error = error { // Handle error return } // Report success }
-
11:11 - App Extension life cycle management and reporting VoIP call
// Manage App Extension life cycle and report VoIP call class SimplePushProvider: NEAppPushProvider { override func start(completionHandler: @escaping (Error?) -> Void) { // Connect to your provider server completionHandler(nil) } override func stop(with reason: NEProviderStopReason, completionHandler: @escaping () -> Void) { // Disconnect your provider server completionHandler() } func handleIncomingVoIPCall(callInfo: [AnyHashable : Any]) { reportIncomingCall(userInfo: callInfo) } }
-
11:57 - Handling incoming VoIP call in the containing app
class AppDelegate: UIResponder, UIApplicationDelegate, NEAppPushDelegate { func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool { NEAppPushManager.loadAllFromPreferences { (managers, error) in // Handle non-nil error for manager in managers { manager.delegate = self } } return true } func appPushManager(_ manager: NEAppPushManager, didReceiveIncomingCallWithUserInfo userInfo: [AnyHashable: Any] = [:]) { // Report incoming call to CallKit and let it display call UI } }
-
-
正在查找特定内容?在上方输入一个主题,就能直接跳转到相应的精彩内容。
提交你查询的内容时出现错误。请检查互联网连接,然后再试一次。