探秘 App Clips_ios 

正文字数:3378

预计阅读时间:9分钟





◆ ◆  ◆

简介




在​​iOS14​​​中苹果推出了很多新特性,其中就包含​​App Clips​​​。​​App Clips​​​类似微信的小程序,不需要显式的去​​App Store​​​里下载,苹果会在对应的时机进行下载。​​App Clips​​可以在不打开主App的情况下,单独进行使用,交互操作和主App无异,例如登录、列表视图、支付等。

为了保证加载速度,苹果对​​App Clips​​的安装包大小有限制,从产品设计的角度,就要聚焦核心功能,这也是苹果所推荐的。

由于公司打算做​​App Clips​​,所以有了这篇文章,文章中的内容基本上能保证准确性,并且其中很多技术点是和苹果开发者沟通过的。



◆ ◆  ◆

使用流程



通过​​Safari Banner​​​、​​iMessage​​​等如下方式,可以打开​​App Clips​​​。例如点击​Safari Banner​​​调起​​App Clips​​​,调起时会带一个URL过来,系统会根据调用URL来确定卡片显示的数据,随后将数据例如标题、背景图等显示在​​App Clips​​的卡片页。

主标题下方有几行小字,可以选择是否开启通知、定位等权限,这些权限都是临时性或受限制的,可以点击进去将权限关闭,否则默认权限是打开的。点击Open即可进入​​App Clips​​​中,并且将URL传给​​App Clips​​。

探秘 App Clips_ios_02

◆  ◆  ◆

开发



​App Clips​​​从​​iOS14​​​开始支持,所以可以直接用​​SwiftUI​​进行开发,这也是苹果所推荐的开发形式。


◆  ◆  ◆

调起



​App Clips​​​以主工程的一个​​target​​​的形式存在于项目中,与主工程共享代码及资源文件。​​App Clips​​​可以访问蓝牙、NFC等硬件,相当于一个​​smart app​​​。主App和​​App Clips​​​是互斥的,下载主App后​​App Clips​​​就会被删除,所以如果有主App则调起客户端,没有客户端则调起​​App Clips​​。

​App Clips​​​是通过URL的方式调起的,可以直接使用配置的URL,也可以在其后面拼接路径和参数,和我们使用的请求URL类似。从外部调起的时候就会传入一个URL过来,​​App Clips​​进行解析以调起对应的页面。

有一点需要了解的是,在​​WWDC2020​​中,苹果演示的是一个类似于微信小程序二维码那样的异形码。经过和苹果开发者沟通,并不强制要求用异形码,二维码就可以,主要是承载URL即可。


◆ ◆  ◆

二进制下载




对于​​App Clips​​​二进制的下载有两种情况,一种是手机解锁的情况下,系统会在卡片页展示过程中就开启后台下载,点击Open按钮即可打开​​App Clips​​​。如果当时二进制还未现在完,则会出现系统的loading页面,loading完成后即可打开​​App Clips​​。

如果调起​​App Clips​​时手机处于锁屏状态,在卡片页不会开启后台下载,当用户点击Open后才会开始下载并展示loading页面。

下载后的​​App Clips​​​,三十天内未使用则会被删除二进制,下次使用将重新下载。这个卡片页无论是否安装App都会显示,区别在于打开的是主App还是​​App Clips​​​。​​Clip Card​​​只会显示一次,如果​​App Clips​​二进制没有被删除的话,之后就不会再重复显示。

◆ ◆  ◆

Apple Connect配置



每个应用程序只能有一个​​App Clips​​​,但可以有多个配置,可以定义标题、副标题、封面图(有大小限制)、按钮类型(action),标题默认和App名一样。每个​​App Clips​​可以配置多个URL,苹果推荐不同功能模块,对应不同的URL。也可以只配置一个URL,后面通过拼接路径和参数的方式来区分和传值。原则上来说,URL的数量没有限制。

配置​​App Clips​​时可以选择高级设置,在高级设置中可以多套标题和封面图。苹果会根据配置的URL作区分,显示不同的封面图。


探秘 App Clips_ios_03


◆ ◆  ◆

客户端配置



在主工程中新建一个​​target​​​并选择为​​App Clips​​​,并且关联到我们的主工程Fruta即可。因为​​App Clips​​​是从​​iOS14​​​推出的,而​​SwiftUI​​​是从​​iOS13​​​推出的,所以我们可以选择使用​​SwiftUI​​​进行开发,这也是苹果推荐的开发方案,当然也可以选择​​UIKit​​的方式。


探秘 App Clips_客户端_04


创建​​App Clips​​​后,系统会生成对应的​​iOSClip.entitlements​​​文件,需要在里面设置​​App Group​​​、​​Parent Identifier​​​、​​Associated Domains​​​,以关联主App。我们填写应用程序标示符时,苹果推荐以​​{App Bundle id}+Clip​​的格式命名,这种命名也更清晰一些。

◆ ◆  ◆

客户端代码


客户端进行开发时,无论采用​​UIKit​​​还是​​SwiftUI​​​,都是通过​​NSUserActivity​​​对​​App Clips​​​传入的URL做解析处理,并根据URL处理不同的业务逻辑,这块和 ​​Unversal Link​​​的处理有点类似。对于URL的处理,使用​​UIKit​​​和​​SwiftUI​​​的处理方式不同,如果是​​UIKit​​则采用下面的方法处理URL传参。

​UIKit​​​通过​​UIScene​​的代理方法接收回调,例如下面的方式。

func scene(_ scene: UIScene, continue userActivity: NSUserActivity) {
guard userActivity.activityType == NSUserActivityTypeBrowsingWeb else { return }
guard let url = userActivity.webpageURL else { return }


presentExperience(for: url)
}


func presentExperience(for url: URL) {
// Route user to the appropriate place in your App Clip.
}

​SwiftUI​​​的处理方式需要注册一个​​NSUserActivityTypeBrowsingWeb​​​类型的​​userActivity​​​,并在回调方法中解析​​webpageURL​​即可。因为如果安装主App后,这个操作就要交由主App来处理,所以主App也需要有相同的处理代码。

struct FrutaAppClip: App {
var body: some Scene {
WindowGroup {
NavigationView {
SmoothieMenu()
}
.onContinueUserActivity(NSUserActivityTypeBrowsingWeb, perform: handleUserActivity)
}
}
func handleUserActivity(_ userActivity: NSUserActivity) {
guard
let incomingURL = userActivity.webpageURL,
let components = NSURLComponents(url: incomingURL, resolvingAgainstBaseURL: true),
let queryItems = components.queryItems
else {
return
}
}
}


◆ ◆  ◆

服务端开发


在打开​​App Clips​​​之前,苹果会验证配置信息,验证方式是苹果请求公司服务器,公司服务器返回给苹果一个​​JSON​​​格式的配置文件,​​App Clips​​​的​​JSON​​​和​​Universal Link​​​的格式差不多。苹果要求设置的请求地址必须是​​https​​​协议,并且不能进行重定向。这里的​​appIDs​​​指的是​​App Clips​​​配置的​​bundle id​​。

下面是​​App Clips​​​服务端配置​​JSON​​​的示例,做过​​Universal Link​​​开发的同学,对下面的​​JSON​​应该比较熟悉。

{
"applinks": {
"details": [
{
"appIDs": [ "", "2" ],
"components": [
{
"#": "no_universal_links",
"exclude": true,
"comment": "Matches any URL whose fragment equals no_universal_links and instructs the system not to open it as a universal link"
},
]
}
]
},
"webcredentials": {
"apps": [ "" ]
}
}



◆ ◆  ◆

数据共享




需要了解的是,​​App Clips​​​和主App是互斥的,当主App安装后,就会删除​​App Clips​​​。二者的数据共享主要是沙盒的数据迁移,所以在安装主App后就需要从​​App Clips​​读取数据。

​App Clips​​​和主App同步数据时,将二者的​​group id​​​设置成相同的即可,例如之前的​​iWatch Extension​​​也有类似功能。这个​​App Group​​​是需要在苹果后台创建的,如果没有创建则需要进入开发者中心的​​Groups​​​选项,创建的对应的​​group id​​。


探秘 App Clips_swift_05


不同​​target​​​或应用间访问沙盒很简单,可以通过​​NSUserDefaults​​​并传入对应的​​group​​​的方式创建​​userDefaults​​​对象,可以对​​key​​​、​​value​​进行操作。

NSUserDefaults *userDefaults = [[NSUserDefaults alloc] initWithSuiteName:@"group.company.appGroupName"];

还可以通过​​containerURLForSecurityApplicationGroupIdentifier​​方法获取到沙盒路径,随后对文件进行操作。

NSURL *containerURL = [[NSFileManager defaultManager] containerURLForSecurityApplicationGroupIdentifier:APP_GROUP_ID];
NSURL *directoryPath = [containerURL URLByAppendingPathComponent:GroupShareRelativeDirectory];



授权




​App Clips​​​的设计初衷就是简单并聚焦核心功能,所以对于一些应用功能权限也和普通App有区别。例如在使用定位功能时,​​App Clips​​不需要用户的完整授权,可以请求“部分授权”,用户可以在卡片页选择是否关闭,就是卡片页下方蓝色按钮。

通知也是一样的,不需要向用户申请授权,可以请求“部分授权”,选项也是默认打开的,在卡片页可以关闭。​​App Clips​​的通知在通知中心显示时,和普通通知看起来是一样的,但“部分授权”有效期八小时,正常弹窗授权有效期一周,我们也可以选择请求用户授权普通通知。


探秘 App Clips_客户端_06


​App Clips​​​中设置“部分授权”,在​​App Clips​​​的​​info.plist​​​配置中,通过​​NSAppClipRequestEphemeralUserNotification​​​字段设置开启通知,如果设置此字段后默认为开启,但用户可以点击​options​​​关闭通知。定位也是一样的,字段为​​NSAppClipRequestLocationConfirmation​​。

探秘 App Clips_ios_07


代码差异



在开发​​App Clips​​​过程中,由于二者大多数使用的都是同一份代码,有些代码可能与主程序有差异,并不能运行到主程序或​​App Clips​​​上。可以通过在​​Active Compilation Conditions​​​设置对应的环境变量,来区分不同的​​target​​。


探秘 App Clips_swift_08


判断代码如下。

#if !APPCLIP
// Code you don't want to use in your app clip.
#else
// Code your app clip may access.
#endif


◆ ◆  ◆

应用推荐



可以在​​App Clips​​​的下方显示一个叠层,来推荐用户下载我们的App,通过​​SKOverlay​​来进行配置。

func displayOverlay() {
guard let scene = view.window?.windowScene else { return }


let config = SKOverlay.AppClipConfiguration(position: .bottom)
let overlay = SKOverlay(configuration: config)
overlay.present(in: scene)
}


◆ ◆  ◆

本地测试




进行本地测试时,可以将在​​Apple Connect​​​中配置的要测试的URL,配置在​​App Clips​​​的环境变量中,并以​​_XCAppClipURL​​进行命名来测试,记得将其勾选。

这里的域名需要和​​Associated Domains​​一致。


探秘 App Clips_swift_09


◆ ◆  ◆

注意点


  1. 下面这些库在​​App Clips​​​不支持,编译时并不会报错,但调用时会出现调用无效等问题。​​CallKit​​​、​​CareKit​​​、​​CloudKit​​​、​​HealthKit​​​、​​HomeKit​​​、​​ResearchKit​​​、​​SensorKit​​​、​​Speech​​。
  2. 为了保护用户隐私,在​​App Clips​​​中下面的​​API​​禁止使用。通讯录、Files、相册、iTunes。
  3. ​App Clips​​无法进行后台活动,目前看主要是后台网络请求。


◆ ◆  ◆

审核



​App Clips​​​是作为应用程序的一部分参与审核的,所以需要随客户端版本上线。虽然​​App Clips​​​和主App在一个​​project​​中,但并不占用主App的包体积。

但是对于​​App Clips​​​的审核标准,经过和苹果开发者团队的沟通,截止目前还未有审核标准发出,估计要等​​iOS14​​出来应该就会有审核标准出来。


THE END