iOS 持续集成:更完备的 App Store Connect API

引言

时隔两年 App Store Connect API 有了更新,WWDC 2018 推出了 App Store Connect API ,用于自动化一些 App Store Connect 后台操作。这次更新包含了 app 元数据相关的API,补上了原来缺失的重要一环, 使得几乎可以通过 App Store Connect API 完成 App Store Connect 上的所有操作。今后开发、证书配置、用户管理、测试、发布全流程都可以通过 API 完成。


需要注意的是, 配置应用内购买和 Game Center 还是需要通过App Store Connect 网站进行配置。

现有的解决方案

Fastlane 已经是一个完善的自动化工具,它提供了如 produce 等工具用于更新元数据。为啥还要关心 App Store Connect API 呢?

首先 App Store Connect API 是苹果官方提供的,适用于所有环境。Fastlane 基于 ruby 的,限制适用的技术栈。

其次 Fastlane 是通过 Spaceship 来访问 Apple Developer Center 和 App Store Connect 的。目前 Spaceship 是通过解析网页来实现自动处理的,会有以下几个问题:

  1. Apple Developer Center 和 App Store Connect 是两个不同的网站,因此需要两次认证,存两份cookie。
  2. 现在 Apple ID 强制开启了双重认证, 每次登录需要验证码,无法完全自动化。cookie 也只能保持 1 个月。
  3. Apple Developer Center 和 App Store Connect 如果有页面更新,Spaceship 就需要升级来适应变化。

如果都能够用 App Store Connect API 来实现,则这些问题就不存在了。

App Store Connect API 也有一些不完善的地方,例如 其 token 有效期只有 20 分钟,固然增强了安全性,但是如何签名产生这个 token,还需要总结出一个最佳实践。

瑕不掩瑜,业界对 App Store Connect API 还是蛮期待的。Fastlane 在 2.150.0 的分支中已经添加对新的 App Store Connect API 的支持。相关讨论 issue:Fastlane: Support new App Store Connect APIs[1]

App Store Connect API 的新内容

文档

这次新增了 200+ 的 RESTful endpoint, 和原来相比翻了一倍。苹果爸爸还将提供一个 openAPI 规范文件供您下载(OpenAPI Specification[2] 是流行的swagger格式的开放标准第三版)。可以在 swagger UI 中查看它,以获取快速的 API 参考。或者更好的方法是将其输入代码生成器中,以更快,更轻松地引导几乎所有语言的 API 集成。苹果爸爸还声称会添加了一些有关速率限制和文件上传等主题的新说明文章,提供可下载的示例代码,以演示重要的 API 概念,例如创建和签名身份验证令牌,与API响应进行交互以及使用新的资产上传 API。


。详情可以参考:App Store Connect API Resources[3]

应用元数据API (app metadata API)

Session Expanding automation with the App Store Connect API[4] 中 Geoff Coffey 是通过一个例子,贯穿讲解了 相关的 API,包括以下 5 个步骤:创建一个新版本,设置定价以更新应用程序元数据,将构建与该版本相关联,然后将该新版本提交给App Review 。本文就做一个简要的总结,不再一一列举了。

新API遵守原有的 App Store Connect API 的认证方式。可以参考文章 App Store Connect的新特性(WWDC 2018 session 301 & 303)[5], App Store Connect API[6]

基本规则

应用元数据的相关资源以及它们的关系如下图所示。


图中每个节点代表 restful api 中的一个资源,例如 /v1/apps。图中联线代表资源之间的关联,例如:一个 App 可以有多个 App Store Versions。每个资源的数据结构如下

data: {
    "type": 资源名,
    "id": 资源ID,
    "attributes": {
        资源自己的属性
    },
    relationship: {
        "关联资源名": {
            "data" : { "type": 资源名, "id": 资源ID }
        }
    }
}

查询资源

通过 GET 方法 请求资源路径就可以获得对应资源的元数据。

可以通过添加形如 filter[key]=value 的 query string 来过滤返回的结果。例如:

GET /v1/apps?filter[bundleID]=org.forestexplorer.ForestExplorer
GET /v1/builds?filter[app]=appid&filter[perReleaseVersion.version]=1.1&fileter[version]=3

此时返回结果 data 是一个数组。

可以通过指定资源的 ID,来确定的获得一个资源的数据。例如:

GET /v1/apps/资源ID

此时返回结果 data 是一个对象。

当然也可以获取一个确定资源的关联资源。例如:

GET /v1/appStoreVersions/资源ID/appStoreVersionLocalizations
GET /v1/appStoreVersionLocalizations/资源ID/appPreviewSets

可以通过添加include=关联资源名的 query string 来让返回结果同时包含关联资源, 例如:

GET /v1/apps/资源ID/prices?include=priceTier

修改资源

修改资源通过 http 的 patch 方法。路径需要指定对应的资源 ID。有意思的是,如果想要用一个原子操作,修改资源的同时为资源添加关联资源。而此时由于新添加的资源还没有创建,没有一个正式的资源 ID。可以通过 ${临时资源ID} 的方式由创建者临时指定一个资源 ID, 并在 data 的同级添加一个 included 其中包含临时资源 id。只要临时资源 ID 相同,就会关联并创建。在返回结果中会更正为真正的资源 ID。例如

PATCH /v1/apps/资源ID/
{
    "data": {
        "type": "apps",
        "id": 资源ID,
        "relationships": {
            "prices": {
                "data" : [{ "type": "appPrices", "id": "${tmpid}" }]
            }
        }
    },
    "included": [{
        "type": "appPrices",
        "id": "${tmpid}",
        "attributes": {
        },
        "relationships": {
            "priceTier": {
                "data": { "type": "priceTiers", "id": "0" }
            }
        }
}

当然也可以直接修改一个资源的关联资源,例如修改一个appStoreVersion 关联的build

PATCH /v1/appStoreVersions/资源ID/relationships/build

创建资源

一个典型的例子是在 AppStore 添加一个新的版本:

POST /v1/appStoreVersions

{
    "data": {
        "type": "appStoreVersions",
        "attributes": {
            "platform": "IOS",
            "versionString": "1.1"
        },
        "relationships": {
            "app": {
                "data": {"type" : "apps", "id" : "资源ID" }
            }
        }
    }
}

创建新资源不用添加"id"属性,创建成功后,ID会自动生成,并在结果中返回

appPreviewsappScreenshots 不仅仅包含元数据,还包含具体的图片、视频文件,这些怎么上传呢?图片、视频文件被统一叫做 asset,代表大数据文件。 在创建 appPreviewsappScreenshots 的元数据成功后,服务端会返回一个属性字段 "uploadOperations" 其中包含了上传 asset 的相关信息。例如 urlmethodoffsetlength,以及请求的headers。使用者还需要通过这些信息上传asset。

需要注意的是, "uploadOperations" 可能返回一个数组,这样可以将大文件分段上传。上传的顺序可以打乱,也可以并发上传,其中一块失败了只需要重传失败的块就行了。


当所有块都上传成功后,还需要更新一下 appPreviews 元数据的状态。标记 uploadedtrue 并且附上 sourceFileChecksum。app store connect 会对上传的asset再做处理。这个处理是异步的。需要通过查询 appPreview 的元数据来确认处理状态。

诊断数据API (Power and Performance Metrics and Diagnostics API)


诊断数据API获取的数据是显示在Xcode中的功能和性能视图(上图)中的数据。有另外一个session: Identify trends with the Power and Performance API[7] 详细讲解其中的具体数据内容。

诊断数据可以通过 app 或者 build 维度获取,具体路径形如:

GET /v1/apps/资源ID/perfPowerMetrics
GET /v1/builds/资源ID/perfPowerMetrics

这里由于返回的数据是苹果定制的格式,因此需要在请求头中添加accept类型如下:

accept: application/vnd.apple.xcode-metrics+json

特别指出,在磁盘写入时,会包含一些堆栈信息,因此还有一个diagnosticSignature的资源节点以及关联的logs资源节点

GET /v1/builds/资源ID/diagnosticSignatures
GET /v1/diagnosticSignatures/资源ID/logs

总结

新的 app metadata API 提供了一种官方支持的自动化发布app的方案。大家可以开动想象力,发挥它的潜力。例如,通过这些 API 一些面向企业的 APP 都可以高效的自动生成定制化版本。再结合苹果正在推广的 Apple Business Manager ,定向为企业发布定制化版本的app。或者未来会涌现出一些简化开发的平台,提供模板和上线服务。只要你有创意和资源,就可以一键在AppStore 上发布一个应用了。


https://mp.weixin.qq.com/s/KnryMnySoOXvf8K7kQVwmA

2021 给 iOS 开发者的一些建议

发布于:14天以前  |  70次阅读  |  详细内容 »

iOS 优化篇 - 启动优化之Clang插桩实现二进制重排

发布于:1月以前  |  101次阅读  |  详细内容 »

抖音品质建设 - iOS启动优化《实战篇》

发布于:1月以前  |  84次阅读  |  详细内容 »

iOS APP 图标版本化

在我们的项目开发过程中,需要频繁打包给测试人员去测试,有时候我们都不知道测试机上安装的版本是否是最新的,这样会造成很多不必要的麻烦和成本。因此我们需要将buildNumber以水印的方式打在APPIcon上,可以很直观的知道当前是哪一个版本。

发布于:1月以前  |  94次阅读  |  详细内容 »

如何实现一个HTTP请求库——axios源码阅读与分析

在前端开发过程中,我们经常会遇到需要发送异步请求的情况。而使用一个功能齐全,接口完善的HTTP请求库,能够在很大程度上减少我们的开发成本,提高我们的开发效率。

发布于:1月以前  |  100次阅读  |  详细内容 »

老司机 iOS 周报 #144 | 2021-01-14

发布于:1月以前  |  119次阅读  |  详细内容 »

快手,快影 iOS App反调试

发布于:1月以前  |  127次阅读  |  详细内容 »

优酷iOS插件化页面架构方法

随着业务不停地迭代,优酷 APP 用于分发视频资源的 UI 控件越写越多,也越来越复杂,并且同时相似相近的代码也非常多。

发布于:3月以前  |  230次阅读  |  详细内容 »

iOS中的内嵌汇编

写一篇在iOS上使用汇编的文章的想法在脑袋里面停留了很久了,但是迟迟没有动手。虽然早前在做启动耗时优化的工作中,也做过通过拦截objc_msgSend并插入汇编指令来统计方法调用耗时的工作,但也只仅此而已。刚好最近的时间项目在做安全加固,需要写更多的汇编来提高安全性(文章内汇编使用指令集为ARM64),也就有了本文

发布于:3月以前  |  239次阅读  |  详细内容 »

77.9K 的 Axios 项目有哪些值得借鉴的地方

Axios 是一个基于 Promise 的 HTTP 客户端,同时支持浏览器和 Node.js 环境。它是一个优秀的 HTTP 客户端,被广泛地应用在大量的 Web 项目中。

发布于:3月以前  |  218次阅读  |  详细内容 »

不会吧,这也行?iOS后台锁屏监听摇一摇

一般情况下,出于省电、权限、合理性等因素考虑,给人的感觉是很多奇怪的需求安卓可以实现,但是iOS就无法实现!今天要介绍的需求也有这种感觉,就是“当 APP 处于后台或锁屏状态时,依旧可以监听到摇一摇,进而触发某些功能,比如:语音播报”。

发布于:4月以前  |  365次阅读  |  详细内容 »

iOS 稳定性:App 被终止的原因

本次 session 主要内容如下: 介绍了后台应用终止的常见原因,并提供了一些优化建议 介绍了 MetricsKit 提供的在代码中获取诊断和性能数据的方法 介绍了 Xcode Metrics Ogranizer 提供的关于线上用户性能数据的可视化报告

发布于:4月以前  |  554次阅读  |  详细内容 »

优酷iOS插件化页面架构方法

随着业务不停地迭代,优酷 APP 用于分发视频资源的 UI 控件越写越多,也越来越复杂,并且同时相似相近的代码也非常多。

发布于:4月以前  |  375次阅读  |  详细内容 »

Vue中Axios的封装和API接口的管理

在vue项目中,和后台交互获取数据这块,我们通常使用的是axios库,它是基于promise的http库,可运行在浏览器端和node.js中。他有很多优秀的特性,例如拦截请求和响应、取消请求、转换json、客户端防御XSRF等。所以我们的尤大大也是果断放弃了对其官方库vue-resource的维护,直接推荐我们使用axios库。如果还对axios不了解的,可以移步axios文档。

发布于:4月以前  |  347次阅读  |  详细内容 »

iOS 持续集成:更完备的 App Store Connect API

时隔两年 App Store Connect API 有了更新,WWDC 2018 推出了 App Store Connect API ,用于自动化一些 App Store Connect 后台操作。这次更新包含了 app 元数据相关的API,补上了原来缺失的重要一环, 使得几乎可以通过 App Store Connect API 完成 App Store Connect 上的所有操作。今后开发、证书配置、用户管理、测试、发布全流程都可以通过 API 完成。

发布于:4月以前  |  438次阅读  |  详细内容 »

iOS 性能优化:优化 App 启动速度

苹果是一家特别注重用户体验的公司,过去几年一直在优化 App 的启动时间,特别是去年的 WWDC 2019 keynote[1] 上提到,在过去一年苹果开发团队对启动时间提升了 200%

发布于:4月以前  |  389次阅读  |  详细内容 »

iOS圆角的离屏渲染,你真的弄明白了吗

发布于:4月以前  |  366次阅读  |  详细内容 »

iOS导航栏整体滑动解决方案(类似淘宝)

发布于:4月以前  |  440次阅读  |  详细内容 »

让你的应用远离越狱:iOS 14 App Attest 防护功能

当越狱在 iOS 设备第一次流行起来时,iOS 开发人员会尝试各种方法来保护自己的应用程序,以让应用免受盗版等不确定因素的困扰。有许多方法可以做到这一点,包括检查 Cydia 是否存在、检测应用程序是否可读取自身沙箱之外的文件、在检测到调试器时让应用程序崩溃等等。

发布于:4月以前  |  406次阅读  |  详细内容 »

探秘 iOS 14 的 WidgetKit

Widget Extension 提供了 small, medium, large 三个尺寸,不同尺寸可以展示不同的数据、不同的界面,开发者也可以锁定自己APP的 Widget 只有某类尺寸,相同的widget也能重复添加。作为添加在主屏幕上的控件,苹果用了 “At a glance” 来形容 widget ,所以 widget extension 是无法交互的,它能做的只有展示一些信息与点击两个作用,点击后就会引导至app,同时为了性能与耗电量的考虑,Widget extension 也不能展示视频和动态图像。

发布于:5月以前  |  445次阅读  |  详细内容 »

最多阅读

快速配置 Sign In with Apple 1年以前  |  3909次阅读
开篇 关于iOS越狱开发 1年以前  |  2622次阅读
使用 GPUImage 实现一个简单相机 1年以前  |  2608次阅读
APP适配iOS11 1年以前  |  2597次阅读
给数组NSMutableArray排序 1年以前  |  2529次阅读
在越狱的iPhone设置上使用lldb调试 1年以前  |  2515次阅读
App Store 审核指南[2017年最新版本] 1年以前  |  2414次阅读
UITableViewCell高亮效果实现 1年以前  |  2364次阅读
所有iPhone设备尺寸汇总 1年以前  |  2333次阅读
使用ssh访问越狱iPhone的两种方式 1年以前  |  2258次阅读
关于Xcode不能打印崩溃日志 1年以前  |  2167次阅读
使用ssh 访问越狱iPhone的两种方式 1年以前  |  2061次阅读
UIDevice的简单使用 1年以前  |  1846次阅读
为对象添加一个释放时触发的block 1年以前  |  1826次阅读
使用最高权限操作iPhone手机 1年以前  |  1791次阅读