第一章节:移动应用的性质所带来的挑战。
没有做过移动开发的人常常认为,原生应用的大部分挑战与网络上的挑战相似。
这与事实相差甚远。
移动工程有近十种独特的挑战,这些挑战既不存在于网络,也不存在于后端。其中大部分与移动应用的二进制分布有关;需要在低连接性的设置中工作,并纳入独特的功能,如推送通知、深度链接或应用内购买。
在这一部分中,我们将通过对那些没有在移动领域工作过的人来说是新的挑战,既包括软件工程师,也包括工程经理、产品经理和商业利益相关者。
本部分由Bitrise赞助,它是世界上最高效的移动团队所信赖的移动优先CI/CD解决方案。随着你的应用程序和团队的扩大,构建将变得更难,更耗时的管理 - 这就是我们可以帮助的地方。
Bitrise适用于流程的任何部分,一直到集成测试、设备测试场部署和分发到测试人员。构建支持原生 iOS、Android、Flutter、React Native、Cordova、Ionic 和所有其他流行的移动框架。
免费试用Bitrise今天,并建立更好的应用程序,更快。
1. 状态管理
状态管理是原生移动开发中最令人头痛的根源,与现代Web和后端开发类似。移动应用的不同之处在于,应用的生命周期事件
和转换在Web和后端世界中是不需要担心的。应用程序层面的生命周期转换的例子是,应用程序暂停并进入后台,然后返回前台或被暂停。对于iOS和Android来说,这些状态是相似的,但不完全相同。
移动应用程序中驱动状态变化的事件
在大多数移动应用程序中, 事件驱动状态变化。这些事件以异步方式触发,如应用程序状态变化、网络请求或用户输入。大多数bug和意外崩溃通常是由一个意外的或未经测试的事件组合和应用程序的状态被破坏造成的。状态被破坏是应用程序的一个常见的问题领域,全局或局部状态被多个相互不认识的组件所操纵。遇到这个问题的团队开始尽可能地隔离组件和应用程序的状态,并倾向于迟早开始使用反应式状态管理。
复杂的应用程序中常见的奇特bug的根本原因:非决定性事件使应用程序的部分内容处于无效状态
反应式编程是处理大型和有状态的应用程序的首选方法,以便隔离状态变化。你尽可能地保持状态的不可变性,将模型存储为不可变的对象,发出状态变化。这是Uber使用的的做法,是Airbnb采取的的做法,也是N26构建他们的应用的方式。尽管这种方法在向组件树下传播状态变化时可能很乏味,但同样的乏味也使得在不相关的组件中进行非故意的状态变化变得很困难。
应用程序与所有其他应用程序共享相同的资源,以及操作系统在短时间内杀死应用程序,是为移动开发与为其他平台(如后台和网络)开发之间的两个最大区别。操作系统监控CPU、内存和能源消耗。如果操作系统确定你的应用程序在前台或后台占用了太多的资源,那么它可以在很少的警告下被杀死。应用开发者有责任对应用的状态变化做出反应,保存状态,并将应用恢复到它运行的位置。在iOS上,这意味着处理应用状态和它们之间的转换。在Android上,你需要对活动生命周期中的变化做出反应。
全局应用状态,如权限、蓝牙和连接状态以及其他,带来了一系列有趣的挑战。每当这些全局状态之一发生变化,例如,网络连接下降,那么应用程序的不同部分可能需要做出不同的反应。
有了全局状态,挑战就变成了决定哪个组件拥有对这些状态变化的监听。在光谱的一端,应用程序屏幕或组件可以监听他们关心的全局状态变化;导致大量的代码重复,但组件处理所有的全局状态问题。在另一端,一个组件可以监听某些全局状态变化,并将这些变化转发给应用程序的特定部分。这可能会减少代码的复杂性,但现在全局状态处理程序和它所知道的组件之间存在着紧密的耦合。
像深层链接这样的应用启动点或应用内的内部快捷导航点也增加了状态管理的复杂性。对于深层链接,应用程序的状态可能需要在深层链接被激活后进行设置。我们将在深度链接章节中详细介绍。
2. 错误是很难逆转的。
移动应用程序是以二进制文件的形式发布的。一旦用户更新到一个有客户端错误的版本,他们就会被这个错误困住,直到新的版本发布和用户更新。
这种方法带来了多种挑战。
-
苹果和谷歌对允许向应用程序发送可执行代码都很严格。 苹果不允许执行改变功能的代码在他们的商店指南中,谷歌可以将不相关的可执行代码标记为恶意软件,根据他们的程序政策Ans你不能只是远程更新应用程序。然而,推送修复错误的程序,恢复被破坏的功能,应该在两个商店的政策范围内:例如,在使用功能标志时。同时,苹果确实允许执行JavaScript等非原生代码,这就是为什么像Codepush这样的解决方案越来越受欢迎。Codepush允许React Native或Cordova应用程序在飞行中提供更新。在Uber,我们按照同样的思路建立了一个自制的解决方案,其他几家公司也是如此。
-
在商店上发布一个新的应用版本需要几小时到几天的时间。 对于iOS来说,所有的应用程序都要进行人工审核,需要24-48小时才能完成。历史上,每一次审查都有被拒绝的可能。截至2020年6月,苹果已经改变了指导方针,所以错误修复不再因违反指导方针而被推迟,除非是法律问题。在安卓系统上,人工审查并不总是发生,但当它们发生时,它们可能需要超过七天。
-
在新版本发布到应用商店后,用户需要几天时间才能更新到最新版本。即使是开启了自动更新功能的用户也会出现这种滞后。
-
你不能假设所有的用户都会得到这个更新的版本,永远不会。 一些用户可能已经禁用了自动更新。即使他们更新时,也可能跳过几个版本。
查克-罗西,Facebook的发布工程的一部分,在软件工程日报播客集:上总结了为手机发布的情况。
"这是最可怕的事情,要把一万个差异,有效地包装成一颗子弹,向地平线发射子弹,而那颗子弹一旦离开枪管,就不见了。我无法把它找回来,它在没有摩擦和重力的情况下平直地飞翔,直到宇宙的热死。它已经消失了。我无法修复它。"
这意味着你的应用程序的所有以前的版本需要无限期地支持,理论上,你应该这样做。唯一的例外是,如果你把自家的控制措施落实到位,并建立一个强制更新机制来限制支持过去的版本。Android支持Play核心库中的应用内更新。iOS没有类似的本地支持。我们将在强制升级章节中介绍更多这方面的内容。
修复移动应用程序中的一个错误
假设你有一个拥有数百万用户的应用程序,你可以采取哪些措施来减少旧版本中出现的错误或退步?
- 在各个层面做彻底的测试。自动测试,手动测试,并考虑进行有简易反馈回路的测试。许多公司的常见做法是将测试版应用发布给公司员工和测试版用户,让他们 "烘烤 "一周,收集对任何问题的反馈。
- 有一个功能标记系统,这样你就可以即时恢复错误。不过,功能标记会增加更多的痛点。我们将在 "功能标志地狱 "一章中讨论这些问题。
- 考虑逐步推出,并进行监控以确保事情按预期进行。我们将在分析、监控和警报一章中讨论这个话题。
- 强制升级是一个强大的解决方案,但你需要将其落实到位,一些客户可能因此而流失。我们将在强制升级一章中深入探讨这个问题。
3. 旧的应用程序版本的长尾。
旧版本的应用程序会存在很长一段时间,最长可达数年。如果你是少数几个制定了严格的强制应用升级政策的团队之一,这个时间框架才会缩短。有一个滚动的强制升级窗口的应用程序包括Whatsapp和Messenger。其他几个也经常使用强制升级,如银行应用Monzo或美国运通。
虽然大多数用户会在几天内更新到新的应用程序版本,但也会有一长串的用户落后于几个版本。一些用户故意禁用自动更新,但许多不更新的人因为旧手机或操作系统而被阻挡。同时,旧的应用程序版本不太可能被移动团队定期测试,因为这是一个很大的努力,但回报却很少。
即使是一个非破坏性的后端变化也会破坏旧版本的应用程序--例如改变一个特定的响应内容。你可以采取一些做法来避免这种破坏。
- 建立坚固的网络响应处理和解析,使用专门的工具来解决这些问题。我更喜欢强类型的、在客户端和后端之间生成的合同,如Thrift、GraphQL或其他具有代码生成功能的解决方案,而不是需要手动验证的REST接口,当有人忘记更新移动端的解析逻辑时,这必然会破坏。
- 提前做好计划,应对后端变化的破坏。 与后端团队有一个开放的沟通渠道。要有办法测试旧的应用程序版本。考虑建立新的端点,在强制升级将所有当前应用的用户从旧的端点上移走之前,不要让旧的端点退役。
- 对你的后端端点进行分级,并创建新的版本以适应突破性变化。在进行突破性改变时,你通常会创建一个新的端点,并将现有的端点标记为废弃的。请注意,在使用GraphQL的情况下,这可能不适用,因为GraphQL采取了反对版本控制的强烈立场。
- 在后端废除端点时, 要谨慎行事。监控流量,如果需要的话,要有一个关于如何引导请求的迁移计划。
- 跟踪应用程序版本级别的使用统计。 落后于三个或更多版本的用户比例是多少?一旦你有了这些数据,就可以更容易地决定投入多少精力来确保体验在旧版本上运行良好。
- 将客户端的监控和警报设置到位。 这些警报可能被引导到一个专门的移动值班人员,或者只是普通的值班人员。我们将在分析、监控和警报章节中更深入地探讨这个问题。
- 考虑做升级测试, 至少对于主要的更新。升级测试是很昂贵的,很难自动化,而且可能有几种变化需要尝试。由于这种开销,团队很少这样做。
4. 深度链接
深度链接--提供一个网络或设备链接,打开应用程序的一部分--在移动平台上成为一个令人惊讶的棘手问题。iOS和Android都提供了处理这个问题的API,但没有任何有意见的本地框架或推荐的方法。正如Alberto De Bortoli在iOS深度链接的规模一文中所说。
"深层链接是在移动端要解决的最被低估的问题之一 "。
有几件事使深层链接具有挑战性。
- 向后兼容: 确保现有的深层链接在旧版本的应用程序中保持工作,即使是在重大的导航或逻辑变化之后。
- 当深层链接到具有现有状态的运行中的应用程序时的状态问题。 假设你打开了一个应用程序,并在一个细节页面上。你在邮件应用中点击了一个指向另一个详情页的深度链接。会发生什么?新的详细页面会被添加到导航栈中,保留你当前的状态吗?还是应该重置状态?导致最少的非确定性行为的解决方案是在收到深层链接时完全重置应用程序的状态。然而,可能会有一些你不想破坏的流程,所以要仔细计划。
- iOS和Android的深度链接实现差异。 iOS(通用链接和URL方案)和Android(基于intents)的深度链接实现是不同的。有一些第三方的深度链接供应商提供抽象,以配合单一的接口,如Firebase动态链接或Branch,等等。
- 缺乏前期规划。 一旦应用程序的多个版本发货,深度链接往往是事后才想到的。然而,与网络上不同的是,在网络上添加链接/深层链接是比较直接的,改造深层链接策略可能是一个真正的工程挑战。深层链接与状态管理和导航架构有关。
深层链接的最大挑战是iOS和Android都没有提供一个关于如何设计和测试深层链接的意见方法。随着深层链接数量的增加,保持这些深层链接工作的努力和复杂性也在不断增加。你必须提前做好计划,建立一个合理的、可扩展的深度链接实现。
5. 推送和背景通知
应用程序推送通知是一种经常使用的通知、通信和营销工具。企业喜欢使用推送通知,作为一个开发者,你迟早会被要求支持这种方法。然而,推送通知带来了一系列你需要解决的新挑战。
设置和操作推送通知是很复杂的。 无论是安卓还是iOS,你的应用都需要从服务器获得一个令牌(安卓的FCM,iOS的APNS),然后将这个令牌存储在后端。要让推送通知发挥作用,需要采取很多步骤;请看这个iOS的综合教程和Android的教程。
发送推送通知必须从后端进行。你需要与后端团队合作,确定他们想要发送的通知类型和触发器。你的后台同事必须熟悉移动推送通知的基础设施和能力,以充分利用这一渠道。
将推送通知与电子邮件和文本信息一起使用是营销活动的一个流行策略。理论上,这种用法可能会违反iOS应用指南。然而,大多数苹果的应用程序,以及许多第三方应用程序都是这样使用的。你几乎肯定不会从头开始实施推送通知,而是使用第三方客户参与服务,如Twilio、Airship、Braze、OneSignal或类似服务。
推送通知的挑战很多--在实施它们的基础上。
- 类似于深层链接的一系列挑战,在实施通知应该触发什么行动方面。推送通知是一个光荣的深层链接:一个有行动的消息,链接到应用程序。思考后向兼容性、状态问题和提前计划也都适用于推送通知。
- 用户选择退出推送通知或不选择加入。在iOS和Android上,你有不同的方法和限制来检测何时出现这种情况。作为一个有趣的边缘案例,在iOS上,如果用户选择不接受推送通知,他们仍然可以被发送沉默的背景通知。推送通知对于许多应用程序来说通常是一个 "不错的选择",这正是因为你不能保证每个用户都会选择加入这些通知,或者他们的设备会在线接收这些通知。
- 推送通知的交付是不被保证的。特别是在批量发送时,苹果和谷歌都可能会对推送通知进行节流。围绕这种节流的规则是一个黑箱。然而,设备连接问题,以及操作系统限制最近没有活动的应用程序的通知,也可能导致人们看不到你发送的推送通知。
测试推送通知是一个挑战。当然,你可以手动测试。这更像是一种变通方法,但你可以在模拟器上测试它们,无论是在iOS上,还是在Android上。然而,对于自动化测试,你需要编写端到端的UI测试,这对创建和维护来说是很昂贵的。参见本教程,了解如何在iOS上做到这一点。
背景通知是一种特殊类型的推送信息,对用户来说是不可见的,但会直接进入你的应用程序。这类通知对于同步后端更新到客户端非常有用。这些通知在Android上被称为数据消息,在iOS上被称为后台通知。
关于iOS的使用,请看一个例子。
背景通知的概念对于实时和多设备的场景来说是很方便的。如果你的应用在这个领域,你可能会决定为iOS和Android实现一个跨平台的解决方案,而不是由移动应用轮询服务器,服务器通过后台推送通知向客户端发送数据。在2016年重写Uber的Rider应用时,我们的方法的一个主要转变正是如此;从轮询到推送,用内部推送信息服务。
后台通知可以简化架构和业务逻辑,但会引入消息的可传递性问题、消息顺序问题,而且你需要将这种方法与本地数据缓存结合起来,以满足离线场景的需要。
6. 应用程序崩溃
应用程序崩溃是任何移动应用程序中最引人注目的错误之一,而且往往是具有高度商业影响的错误。用户可能无法完成一个关键流程,他们可能会感到沮丧并停止使用该应用程序(也称为流失),或留下差评。
崩溃并不是一个仅有的移动问题。它们是后台的一个主要焦点领域,在那里监控未捕获的异常或5XX状态代码是常见的做法。在网络上,由于其性质--在沙盒中的单线程执行--崩溃比在移动应用中更少。
崩溃的第一条规则是你需要跟踪它们发生的时间,并有足够的调试信息。 一旦你跟踪崩溃,你要报告有多少百分比的会话最终会崩溃,并尽可能地减少这个数字。在Uber,我们从早期就开始追踪崩溃率,不断努力降低崩溃会话的比率。
在iOS上,每次崩溃都会在设备上产生崩溃报告,你可以用这些日志来映射到你的代码。苹果为开发者提供了从用户那里收集崩溃日志的方法,他们选择通过TestFlight或App Store分享这些信息。这种方法对于较小的应用程序来说足够好用。在Android上,Google Play也让开发者通过Google Play控制台的Android Vitals查看崩溃堆栈痕迹。与苹果一样,只有选择向开发者发送错误报告的用户才会在这个门户中记录这些崩溃的情况。
第三方或定制的崩溃报告解决方案在App Store和Google Play所提供的基础上提供了一些优势。这些优势很多,大多数中型及以上的应用程序会选择第三方,或者建立一个具有以下优势的解决方案。
- 更多的诊断信息。你经常想在你的应用程序中记录关于可能导致崩溃的事件的额外信息。
- 丰富的报告。 第三方解决方案通常提供分组报告和iOS和Android崩溃率的比较。
- 监测和警报功能。 你可以设置在出现新的崩溃类型或某些崩溃激增时获得警报。
- 与其他开发堆栈的整合。 你经常想把新的崩溃与你的票务系统
新的崩溃与你的票据系统连接,或在拉动请求中引用它们。
在Uber,我们在早期就使用了第三方的崩溃报告。然而,后来我们建立了一个内部解决方案。许多第三方崩溃报告解决方案的缺点是,他们只收集崩溃和非致命错误的健康信息,而不收集应用不响应(ANR)的信息
和内存问题。拥有许多应用程序的组织可能也会发现报告不够丰富,可能想建立自己的报告,以比较许多应用程序的健康状态。与内部项目管理和编码工具更好地整合,也可能是定制的一个原因。
崩溃的可重复性和可调试性是其他的痛点,这些痛点比后端或网络团队更影响移动端。特别是在安卓世界里,用户有各种各样的设备,运行各种操作系统版本和各种应用程序版本。如果崩溃可以在模拟器或任何设备上重现,你就没有借口不解决问题了。但如果崩溃只发生在特定的设备上呢?
建立一个优先级框架来定义阈值,超过这个阈值你就会花时间调查和修复崩溃。这个阈值将根据崩溃的性质、客户终身价值和其他业务考虑而有所不同。
你如何确定修复崩溃的优先次序?在应用程序中使用频率较高的部分出现的较小的崩溃是否比使用频率较低的部分出现的较大的崩溃更需要修复?
你需要比较调查和修复的成本与修复的好处,以及工程师花时间在其他方面的机会成本,如建立创收的功能。
应用程序的稳定性是你要最终衡量的指标,以确保它不会倒退。你的应用程序永远不会真正实现无崩溃,但如果你能将崩溃减少到一个稳定的水平,即每一万个会话中只有不到一个受到影响,你就在正确的轨道上。争取根据你的总用户会话计算出一个应用程序稳定性得分,并投入时间来减少崩溃,直到你达到你的目标。
Bugsnag发布了关于应用程序稳定性分数中位数的指标看起来像。
- 由1-10名工程师建立的应用程序的稳定性为99.46%。
- 由11-50名工程师构建的应用程序为99.60%。
- 由51-100名工程师开发的应用程序为99.89%。
- 由100名以上工程师构建的应用程序为99.79%。
如果你的应用程序的稳定性得分是99.99%或以上,你就远远领先于你的竞争对手,并且达到了被认为是世界级的可靠性。
进一步阅读。
- 使用Bugsnag和Splunk的错误监测](go.mobileatscale.com/error-monit…) Zynga
- [移动崩溃报告流程] (go.mobileatscale.com/crah-report…) LinkedIn
- 移动崩溃报告流程 LinkedIn(视频)
- CCSM:可扩展的统计异常检测以更快地解决应用崩溃问题](go.mobileatscale.com/crashes-fac…) 来自Facebook
- 在iOS上实现99.99%无崩溃的路径来自 Turo Engineering
- (go.mobileatscale.com/crashes-str…) Strava Engineering [征服我们的安卓系统崩溃数] (go.mobileatscale.com/crashes-str…)
- 安卓应用中原生崩溃的调试] (go.mobileatscale.com/debugging-c…) ProAndroidDev
- 谷歌地图SDK崩溃,影响数百个应用程序 来自](go.mobileatscale.com/google-maps…
- SDK不应该使应用程序崩溃--从Facebook的故障中吸取教训 来自Bugsnag
- 为什么一个小小的Facebook bug会对一些最受欢迎的iOS应用造成破坏](go.mobileatscale.com/facebook-sd…) from the Verge
- 应用程序稳定性指数 from Bugsnag
7. 离线支持
尽管离线支持正在成为丰富的网络应用的一个特征,但它一直是原生移动应用的一个核心用例。人们希望应用程序能够保持可用性,即使在连接性下降的情况下。他们当然希望在信号下降或减弱时,状态不会丢失。
适当的离线模式支持给应用程序增加了很多复杂性和意想不到的边缘情况,例如。
- 可靠地检测手机何时处于离线状态。 操作系统可以报告用户处于在线状态;然而,情况可能并非如此。当手机连接到使用专属门户的WiFi点时,可能没有数据被传输。对于像这样的边缘案例,应用程序可能需要ping几个 "永远在线 "的域来确定这一点。
- 检测连接速度和延迟并在必要时相应改变应用程序的行为。流媒体应用程序将优化流媒体以匹配可用带宽。其他应用程序可能会对干扰应用程序的不良连接向用户发出警告。预先计划好你要如何处理这些边缘情况。
- 当设备离线时, 存在本地状态,并在连接恢复后同步回来。当用户在多个设备上使用应用程序时,你需要考虑到竞争条件,有些是在线的,有些是离线的。对于修改本地存储数据的应用程序更新,你应该格外小心,将旧数据迁移到新格式。我们将在客户端数据迁移一章中介绍这一挑战。
决定哪些功能应该离线工作,哪些不应该。许多团队错过了这个简单的步骤,它使离线功能的规划更容易,并避免了范围蠕变。我建议从应用程序的关键部分开始,慢慢扩大这个范围。获得真实世界的反馈,即 "主要 "的离线模式能按预期工作。你能在应用程序的其他部分利用你的方法吗?
决定如何处理离线的边缘情况。 你想对极慢的连接做什么,即手机仍然在线,但数据连接过于缓慢?一个强大的解决方案是将其视为离线,并可能通知用户这一事实。超时怎么办?你会重试吗?
移动设备下线了。一个日常场景。你将如何处理这个问题?
重试可能是一个棘手的边缘案例。假设你有一个连接,在一段时间内没有回应 - 一个软超时--你重试另一个请求。如果第一个请求返回,然后第二个请求也返回,你可能会看到竞赛条件或数据问题。
设备和后端数据的同步是另一个常见但令人惊讶的挑战问题。这个问题在多个设备的情况下会成倍增加。你需要选择一个冲突解决协议,这个协议对于多个平行的离线编辑来说足够好用,并且足够强大,可以处理中途的连接性下降。
重试策略伴随着你需要考虑的边缘情况。在重试之前,你怎么能确定网络没有中断?你如何处理用户疯狂地重试并可能产生多个平行请求?应用程序是否会允许在前一个请求未完成的情况下提出相同的请求?在切换到离线模式的情况下,应用程序如何判断网络已经可靠地恢复了?应用程序如何区分是后端服务没有响应
还是网络太慢?资源效率如何;你是否应该研究利用ETags或if-match headers的HTTP条件请求与重试?
在连接不良的情况下,网络请求有时会超时。合理的重试策略或转移到离线模式可能会有帮助。这两种解决方案都有很多需要考虑的权衡因素。
当使用反应式库来处理网络连接时,上述许多情况都可以相对简单地解决,比如RxSwift、苹果的Combine、RxJava或Kotlin Coroutines。
不应重试的请求会带来一系列单独的问题。例如,你可能不想在一个正在进行的支付请求中重试。但如果它回来时是失败的呢?你可能认为重试是安全的。然而,如果请求超时了,但服务器进行了支付呢?那么你就会向用户重复收费。
作为后端端点的消费者,为了安全起见,你应该在API端点上推送所有重试。
通过让这些端点成为idempotent。有了idempotent端点,你必须获得并发送idempotency密钥,并跟踪一个额外的状态。你还得担心边缘情况,比如应用程序崩溃并重新启动,而idempotency密钥没有被持续保存。安全地实现重试,为团队增加了很多额外的工作。你必须与后端团队紧密合作,以映射出需要设计的用例。
与状态管理一样,可维护的离线模式和弱连接支持的关键是简单。使用不可变的状态,直接的同步策略,以及简单的策略来处理慢速连接。使用正确的工具进行大量的测试,如iOS的Network Link Conditioner或Android模拟器的networkSpeed capability。
8. 可访问性
对于流行的应用程序来说,可访问性是一个大问题,有几个原因。
- 如果你有大量的用户,他们中的许多人会有各种无障碍需求,发现如果没有足够的支持,很难或不可能与你的应用程序互动。
- 如果应用程序不能被无障碍使用,应用程序的发布者就会有内在的法律风险;在美国,有几起针对本地移动应用程序的无障碍诉讼已经发生。
无障碍性不仅是一件 "好事",你的应用程序的质量会随着你的无障碍性提高而提高。这个想法来自Victoria Gonda,她收集了优秀的iOS和Android可访问性资源。
在你开始之前,你需要确认你将在实施WCAG 2.1移动定义方面的深度。确保应用程序对于通过VoiceOver(iOS)/TalkBack(Android)的视力正常的人来说是可行的,并确保颜色/关键元素有足够的对比度,这些都是典型的基线期望。根据你的应用类型,你可能需要考虑重听者,或有其他无障碍需求的用户。
无障碍性比确保视力正常的人能够使用该应用程序更深入。允许可访问性偏好与应用程序一起工作,例如支持用户选择的字体大小--通过iOS上的动态类型支持和Android上的使用与尺寸无关的像素作为测量--都是你应该遵循的做法。你还需要考虑到设备的碎片化。例如,在安卓世界里,众所周知,OnePlus手机的字体大小与生态系统的其他设备不同。
从一开始就实施无障碍性,在iOS上是一个令人惊讶的低努力的任务,在Android上是一个明智的任务。这两个平台都对无障碍需求进行了深入思考,并使添加无障碍功能变得相对容易。
加装无障碍功能是这个问题可能会耗费时间的地方。将无障碍性作为设计过程的一部分是一个更好的方法,这就是为什么将无障碍性作为规划/RFC过程的一部分是一个好主意。在页面层面(iOS)考虑VoiceOver框架并从一开始就遵循无障碍性的最佳实践是很好的投资。
测试无障碍性是需要计划的。 有几个层次的无障碍性测试,你可以而且应该增加。
- 自动化可自动化的无障碍性检查部分,例如检查屏幕元素上的无障碍性标签。在iOS上,你也可以让VoiceOver内容显示为文本,并有可能自动进行这些检查。
- 手动测试无障碍功能。作为发布过程的一部分,至少要半定期地这样做。
- 在你的测试项目中招募无障碍用户,直接从他们那里获得反馈。这对大公司来说更可行,但让这些用户与工程团队互动的回报可以是一个重大胜利。
- 在开发过程中**开启无障碍功能,**如果这样做是明智的。这样,你可以检查这些功能的运行情况,并对依赖这些功能的人如何使用它们获得更多的同情。
9. CI/CD和Build Train。
CI/CD对于简单的后台服务和小型Web应用来说是很简单的。然而,即使是简单的移动应用程序,它也不是。这主要是因为应用商店的手动提交步骤。对于iOS应用商店的应用来说,做一个完全自动化的持续部署管道是不可能的,因为有人工审核的门槛。在Android上,你可以自动化这个过程,就像你对企业iOS应用一样。
由于手工的App Store审核过程,你无法在iOS上有一个真正的持续部署过程到App Store。
iOS和Android平台是不同的,每个平台都需要自己的构建系统和单独的管道。 在使用第三方CI时,值得选择一个将iOS和Android移动构建视为一流的,在移动方面有记录的,并能处理你的团队或公司想要的规模的人。有几个供应商你可以探索。
Bitrise是由移动工程师为移动开发的CI/CD。从拉动请求,到应用商店提交和其他,Bitrise自动化,监控和改善你的应用开发工作流程。使用 Bitrise 的团队可以建立更高质量的应用程序,更快地交付,并让开发人员感到满意。
Bitrise 支持原生 Android、iOS、React Native、Flutter 和其他流行的移动框架的构建。需要支持特定的开发步骤,如测试、代码签名,或在构建过程中出现问题时通知?有了数百个集成的开源库,你可能会找到你需要的东西,或者能够快速建立它。
超过100,000名开发人员和成千上万的组织信任Bitrise。免费试用 并建立更好的应用程序,更快。
与使用基于云的CI/CD供应商相比,拥有自己的构建基础设施可以给你更多的控制和更好的体验。几家工程公司的移动工程负责人指出,即使有额外的成本,他们也更乐意在内部拥有构建基础设施。
在一个非常大的规模,你可能会决定在内部构建。在Uber,我们没有任何供应商能够可靠地处理我们所做的构建数量,他们也不能提供我们内部系统所做的集成钩。
你可能会发现自己在使用流行的构建工具来自动完成各种构建步骤,比如上传到应用商店。对于iOS,这可能是Fastlanex,而构建或Android构建运行在Jenkins,它可能是一个Jenkinsfile或类似的东西。
如果你没有专门的人员带宽来支持你的自制CI系统,那就要警惕了。我曾看到初创公司反复设置Jenkins CI,使其运行,但几个月后才发现需要有人继续处理基础设施问题。我强烈建议,要么购买供应商的解决方案--将基础设施部分卸载给供应商--要么让一个专门的人或团队拥有移动的构建基础设施。
对于大公司来说,拥有构建基础设施可能是有意义的。在Uber,我们有一个专门的移动基础设施团队,他们拥有诸如iOS和Android monorepo或保持主规模的绿色。其他拥有大型移动团队和足够资源的公司也运行他们自己的CI,使用专用硬件。同时,像乐天这样的公司已经从内部CI设置转移到Bitrise,并对这种变化感到满意。
构建列车是你有了CI之后的下一步。构建列车是一种跟踪每周或每两周发布的状态的方法。一旦为应用商店的 "候选版本 "进行了发布切割,就需要进行一系列的验证步骤;其中一些是自动的,一些是手动的。这些步骤包括运行所有的自动测试、手动测试、新资源的本地化、性能测试或狗粮或beta测试期。
一旦候选版本得到验证,它就会被上传到应用商店,并等待批准。在批准后,你可能会推出一个阶段性的发布,例如在iOS上的分阶段推出和在Android上的分阶段推出。
你的构建列车会直观地显示上述所有的状态;哪个提交是构建候选的切割,验证过程在哪里,以及分阶段推出的状态是什么。构建列车可能是由负责发布过程的人手动跟踪的,有些公司有复杂的发布步骤和移动信息团队,有时会建立他们自己的解决方案。
典型的推出阶段包括:。
- 应用程序的开发/夜间构建。由CI/CD系统构建的应用程序版本,有时是每晚进行一次。工程师或公司员工通常是唯一能接触到这个版本的人。
- Beta/dogfood版本: 通常在分阶段推广开始前向大多数公司员工和beta测试者发布。一个足够大的测试组可以帮助在全面推广前发现回归和问题。
- 一般的、分阶段的推出在生产中。在安卓系统中,通常是分阶段在生产中推广到一定的人口比例。
Uber应用分阶段推出的步骤(来源)
是否将iOS和安卓的推出结合在一起,或者分开进行,将是发布团队的选择。在Uber,为了简单和一致,我们把这些放在一起。我们有一个每周发布的节奏,更细化的发布时间表将没有意义。
移动应用的发布频率将取决于团队--或公司--决定采用什么。每一次移动发布都会增加测试开销,这可能是很重要的。同时,有许多新变化和功能的大型发布更有可能出现回归,这反过来又会进一步推迟已经很晚的发布。以下是公司倾向于采用的典型的移动发布时间表。
- 每周: 拥有成熟的发布和测试流程的大型移动团队通常采用每周一次的构建切割方法。然后对构建的版本进行测试,并向测试版用户推出。当没有发现退步时,应用程序就会进入商店,通常是在削减后一周。
- 每两周一次: 许多公司选择这种模式,以便与冲刺长度保持一致,并减少每次发布都要测试的开销。
- 不太频繁的或临时性的发布: 小型应用程序可能只在有足够大的变化时才发布。这对大型或复杂的应用程序来说是一种罕见的模式。不太频繁的发布往往与较低的质量有关;更多的功能是一次性发布的,有更多的机会出现退步,这就需要更长的时间来修复。考虑增加你的发布周期以提高你的应用程序的质量。
一项不具代表性的Twitter上的投票表明,268名受访者中约有65%的人每两周或更短的时间发布他们的移动应用。
移动工程团队多长时间发布一次应用程序?一个投票。(来源)
移动构建列车是一种可视化上述所有状态的方式;哪个提交是构建候选切割,验证过程在哪里,以及阶段性推出的状态是什么。发布经理可能会手动跟踪构建列车。拥有复杂的发布步骤和移动信息团队的公司倾向于建立自己的定制解决方案。我们在Uber就是这样做的。
Uber的内部构建列车系统被称为Metro。在每个发布步骤之间,需要完成一系列的手动或自动步骤。(来源)
定义在发布 "准备就绪 "之前需要完成哪些检查。一旦你有了这些正式的东西,你能自动化的检查越多,发布过程就越顺利。
在Uber,每个发布阶段都需要通过以下测试。
- UI测试的执行没有失败。UI测试套件足够大,在CI上运行所有的测试是没有意义的。在发布之前,所有的测试都被执行。
- 由拥有这些测试的团队或拥有该流程的QA团队执行的手动理智测试。如果理智测试失败,或者测试没有被执行,火车就不会前进。
- 所有字符串的定位完成。自动检查将检查应用程序中是否有丢失的翻译。
- 崩溃报告。 在测试过程中没有发现回归。在测试阶段的崩溃将自动触发警报或票据,团队需要调查并解决它,然后才能继续推广。
- 内存使用情况。 根据内存分析,没有出现退步。
- 业务指标:。在推广期间没有出现倒退("E2E漏斗 "指标)。在Uber,我们监测了跨地区的请求、调度和在途信号。如果一个错误会导致这些关键指标的倒退,我们可以检测到这个问题,并采取行动来缓解它。
进一步阅读。
- 移动团队如何使用发布列车来提高速度和效率 来自Bitrise
- Uber公司的在规模上保持绿色主控
- 构建和发布过程 来自Uber
- 创建更快的移动发布周期 来自Lyft
- SoundCloud的发布质量和移动列车
- 大规模的快速发布 来自Facebook
- 来自Skyscanner的应用发布的现在和未来
- 运行自己的CI方法 来自Mobile Native Foundation
10. 第三方库和SDK。
当你的应用程序开始增长并与许多第三方库集成时,构建过程变得复杂。这些库会有新的版本,其中一些是破坏性的变化,需要你的源代码正确更新,并重新测试。
第三方库可能是一个安全责任。例如,Google Play核心库中经常发现新的漏洞,允许本地代码执行(LCE)。用户可能面临数据被盗的风险,或者在使用带有暴露于LCE的库的应用程序时,他们的设备可能会运行未知的代码,特别是在没有更新到解决安全漏洞的新应用程序版本的情况下。
你需要持续监测第三方库的漏洞。一个选择是雇用第三方安全供应商,在发生这种情况时通知你。
稳定性和可靠性是第三方库的另一个问题。 例如,在2020年4月,谷歌地图SDK团队向他们的后台推送代码,导致嵌入它的应用程序崩溃。这影响了数百个应用程序,包括那些将地图作为关键功能的应用程序,导致这些应用程序在故障期间出现损失。2020年5月,Facebook SDK也发生了类似的事情,在2020年7月发生了重复事件。
这意味着不同的公司已经将谷歌地图SDK和Facebook SDK
到他们的应用程序中,然后建立了他们的二进制文件,并在推送到应用程序商店之前进行了适当的测试。从这些公司的角度来看,一切都在控制之中。但是,谷歌和Facebook的这些错误变化被推到了这些SDK的后端,这显然不是在完成整合和构建时可以测试的。而一旦发生崩溃,这些应用程序的开发者就无能为力了。他们的二进制文件是在野外,他们无法控制。
这就是为什么有一个专门针对第三方库的功能标志是很好的做法,这样你就可以封装这些库的加载和所有的执行点,如果开发这些SDK的团队发生了破坏性的变化,你就可以通过你的后端轻松地禁用任何库。
使第三方库的更新可逆是困难的,有时甚至是不可能做到的。主要的库更新可能是有风险的。处理有风险的变化的一个务实的方法是以分阶段的方式推出它们,使用功能标志来进行。然而,通常情况下几乎不可能用两个库的版本来发布应用程序;即使你可以嵌入两个库,你也需要几十个功能标志的接触点来满足API的变化。
不幸的是,这意味着库的更新是任何应用程序中最有风险的变化之一。你需要仔细测试更新后的应用程序的行为,并在应用程序通过构建列车的过程中监测崩溃报告和错误报告。与其他可逆转的变化相比,在主要的库更新后做更多的员工测试和beta测试是很好的做法。
使用第三方库还有许多其他风险, 你要考虑。一些移动团队创建了一个评估标准,他们在接受一个新的第三方依赖关系之前,会对其进行评估。列表中包括以下几个方面。
- 应用程序的大小: 依赖性会给包的大小增加多少?
- 工具升级的风险: 当想要升级到新的XCode或Android Studio版本时,添加这个依赖会不会成为一个障碍?
- 不维护的风险: 该依赖性不被维护的可能性有多大?例如,如果发现了一个安全漏洞,我们是否可以合理地期望所有者在短时间内解决这个问题?
- 第三方的反应能力: 所有者对提出的问题的反应速度如何?他们是否及时地合并了错误修复?
将所有的第三方依赖关系视为风险,跟踪它们,并定期重新评估使用它们的必要性,这是一种健康的做法。
11. 设备和操作系统碎片化。
设备模型和操作系统碎片化是iOS和Android上的一个日常问题。设备碎片化和奇怪的、与硬件有关的bug一直是安卓上熟悉的痛点。操作系统碎片化在iOS上是一个较小的问题,而在Android上不断恶化。
保持新的操作系统发布和伴随的API变化需要移动工程师的关注。 iOS和Android都在不断创新;功能和API不断被添加、改变和废弃。这不仅仅是大的变化,如iOS 13上的SwiftUI或黑暗模式,或iOS 8 (2014)和Android 10 (2019)上的生物识别认证API。有几个较小的API,如Android Oreo上的信用卡自动填写,在一个平台上存在,而在另一个平台上没有对应的API。说实话,在WWDC或Google I/O上了解新的API,然后将它们添加到应用程序中,是最有趣的部分。
确保应用程序在旧的操作系统和设备上保持正常工作, 是一个更大的挑战。你通常需要建立一个内部设备实验室或使用第三方测试服务,以确保应用程序在所有主要机型上正常工作。
2016年窥视Facebook的设备测试实验室:板墙。资料来源:Facebook工程博客。
当涉及到特定设备的边缘案例和崩溃时,安卓系统的怪癖要多得多。例如,三星设备因与三星安卓定制有关的奇怪的崩溃而闻名,更不用说特殊的Galaxy Fold的布局考虑。硬件驱动和GPS传感器可能是一个令人头痛的问题,包括难以理解的堆栈痕迹。
安卓还有一个碎片化问题;不在谷歌的生态系统上运行的安卓分叉。为Fire OS或未来的华为设备构建的应用程序将无法访问谷歌游戏服务。这意味着像Firebase通知的功能将无法使用。崩溃报告、用户错误报告和大规模人工测试是你可以保持对新问题和回归的关注的方法。所有这些都比大多数人预期的要费时和昂贵得多。
决定如何以及何时停止支持旧的操作系统版本是你的移动团队应该投入的一个过程,在早期。支持旧的iOS和Android版本的成本很高,回报可能很低。企业自然会推动支持尽可能多的设备。团队需要量化这种支持所带来的好处。当旧版本的收入或利润低于维护成本时,务实的解决方案是放弃对旧操作系统的支持。
虽然在某些行业可能有支持旧操作系统版本的法律要求,但你支持的版本越少,你就能越快地前进。截至2021年,安卓团队通常会
支持24版本以上(Nougat),但很少回到21版本(Lollipop)之前。在iOS上,由于更快速的操作系统采用,许多企业在新的操作系统发布后不久,就放弃了对超过最后两三个版本的支持。
12. 应用内购买
应用内购买(IAP)在iOS和安卓系统中是独一无二的,因为它们可以带来大量的收入,而且在大型和复杂的应用中测试这些应用也是一种挑战。
IAP是移动平台所特有的,当你销售数字产品时,不实施它是很少的选择。你必须支付高昂的费用,即每年收入不超过100万美元的15%(包括iOS和Android),以及超过这个数字的30%。在分成的基础上,你仍然要在众多的限制和挫折中努力。
你可能遇到的最大的IAP限制是这些。
- 不同的iOS、Android IAP模式和能力,很可能与网络产品的模式不同。例如,Google Play允许暂停订阅以防止自愿流失,但iOS不允许。这是两个平台之间的几个差异之一。
- 实施IAP状态的改变要以一种无弹窗的方式发生。客户会期望IAP的效果能立即发生。然而,这样做可能是一个更大的挑战。你可以
你可以做一个纯粹的客户端实现,这可能是更简单的实现,但这使得
但这使得订阅与App Store账户完全捆绑在一起。这也为不良行为者提供了攻击媒介,如设置设备时钟,或运行你的应用程序的修改版本,"解锁 "IAP功能。你可以等待后端回调,但这可能意味着延迟,并不得不处理更多的边缘案例。这些边缘情况将是你的应用程序和你的IAP功能所特有的。
- 严格的定价。在苹果公司,你只能从预定义的价格层级中选择,而改变订阅的定价变得复杂。如果你的定价与建议的准则不同,你会发现按国家设置价格是很有挑战性的。如果你决定将IAP作为一个纯粹的客户端方法来实现,你也将不得不在二进制中硬编码你的产品。
- 可怜的API文档。iOS的订阅API文档不足。你会发现自己在排除某些方面的故障。安卓的IAP API有更好的文档,你在这方面的麻烦会更少。
- 报告的挑战。回答 "一个特定的用户为我们创造了多少收入 "这个问题变得出乎意料地具有挑战性,如果不是实际上不可能的话。挑战在于计算一个用户的购买毛额的净收益,包括后续交易的收益。一个常见的方法是保存毛价信息,并从各种数据点(如毛价、汇总的每日报告和App Store定价矩阵)对净收益进行估算。
- 会计、对账和税务方面的困扰。iOS和安卓都以不同的方式进行支付,并以不同的方式报告/处理税收。苹果的财政日历本身就很疯狂,包括一个35天的会计月。你的会计团队将试图通过他们的方式来解决事情的运作,而移动团队的人很可能需要帮助他们弄清楚数字是如何加起来的。
- 订阅支持。 在iOS上,你没有工具来取消或退还订阅,即使用户要求你这么做。请参阅Disney+的订阅页面,以了解这导致的那种尴尬的客户信息传递的例子。
- 将IAP用户映射到你的后端系统。 你需要将App Store用户凭证与你存储在系统中的元数据配对。如果你没有这样做,你可能不得不显示错误,使用户感到困惑,并需要客户支持的协助。一个例子是这样的。
- 恢复IAPs流程。当客户购买并设置一个新的手机时,应该发生什么?事情应该是 "正常工作"。为了实现这一点,你可能需要在这个流程中添加额外的业务逻辑。苹果公司对你可能需要采取的步骤有一个很好的概述。关于iOS的说明:恢复收据时,交易ID可能会改变,这是你需要在后台处理的事情。
- IAP端点的可用性 不是100%的。例如,苹果的verifyreceipt端点已经知道返回5xx响应,晦涩的错误信息或不正确的数据。苹果公司很少会通报故障情况,因此许多工程师依靠第三方监测,如Downdetector。
- 非Google Play商店的IAPs,如亚马逊或华为,是一个额外的挑战。你需要咨询各自的开发者文档。你需要平衡在这些平台上构建和支持IAP的成本与这些平台将产生的收入。
- B2B用例和支持批量折扣,或提供增值税收据。虽然苹果公司确实有一个应用程序的批量购买计划,但对于IAP没有类似的东西。对于增值税发票,你需要引导用户在App Store找到这个选项,或者通过Google Play申请。
IAP边缘案例和处理它们应该给你带来大量的工作。这些边缘案例大多不是IAP独有的,在网络上也会有挑战。你仍然需要验证这些情况。
- IAP状态和处理它们,如取消一次性购买、取消订阅或取消后重新购买。
- 订阅的宽限期和试用期。如果人们需要更多的时间,可以延长他们的试用期吗?
- 升级、降级、改变订阅。你的层级越多,需要考虑的边缘情况就越多。
- 折扣和使用这些。你必须在iOS上使用促销优惠或订阅优惠,在Android上使用促销代码。管理、跟踪和清退折扣,每一个新的折扣都会变得更加困难。
- 你的IAP后端端点下降。如果你的IAP解决方案依赖App Store服务器通知或Google Play实时开发者通知来处理服务器之间的事件,你希望有接近100%的可用性来坚持这些事件,即使你的处理能力下降了。如果你的端点不可用,App Store可能会重试,但这种行为在iOS和Android上都没有记录。
- 其他边缘情况,如Android上的退款、信用卡故障、账户保留、宽限期或暂停的订阅。
手动测试应用内购买的工作本身就是一个较小的挑战。苹果和谷歌都提供了测试IAP的方法;苹果提供了Sandbox on iOS和StorekitTest用于单元测试。对于Android,在Google Play上,你可以在Play Store的沙盒中用许可证测试测试者。
请注意,沙盒环境是有限制的。在这种环境下,会有一些你无法复制的真实世界场景。你可能还必须调整你的后端,以允许沙盒测试。
对各种IAP场景的测试是验证应用内购买功能可能变得复杂的地方。
- 一次性购买测试是最直接的方案。不过,你还是要对所有的购买类型进行测试,以确保它们正常工作。
- 验证收据内容是一个经常被忽视的步骤。客户收据上的信息应该是清楚的,以避免不正当的扣款或投诉。
- 订阅升级测试意味着既要测试人们从无订阅到订阅层级的升级,又要确保所有订阅层级按预期工作。
- 订阅升级和降级是你应该测试的事情。降级时,场景可能特别棘手。是否有你需要注意的场景,即用户可能会失去他们输入的一些数据?
- 在应用外改变订阅。 客户可以在应用关闭时或在后台升级或降级订阅。你需要单独处理这些情况,确保应用程序在启动或恢复时对这些变化做出 "反应"。
- 订阅之间的交叉升级是一种比较罕见的情况。然而,如果你有多个不在升级或降级路径上的订阅层级,例如,在月度和年度订阅之间切换,那么你需要测试这些情况。
- 订阅变化和宽限期到位,测试起来特别棘手,因为这些宽限期通常是几天或几周。你确实想确保宽限期被正确处理。
- 记录测试步骤、预期结果、测试账户以及执行测试所需的其他信息。
- 阶段性测试。 你需要检测和解析IAP的webhook请求中的环境字段,以区分沙盒和生产回调。
苹果公司对你可能想测试的测试场景有一个全面的概述,从中可以得到对Android的启发。
自动IAP测试具有挑战性,这是因为可用的工具有限,而且手动测试IAP也很复杂。如果你有一个完善的IAP手动测试过程,自动化应该会更容易一些。你可以用于IAP自动化的工具包括StoreKit Test (iOS)或BrowserStack等工具。
客户支持至关重要确保你的客户服务团队与拥有IAP的工程师有良好的联系,以便你能发现IAP问题并采取行动。如果IAP占了你的应用收入的大部分,这一点尤其正确。
你最终会希望帮助客户支持团队将运行手册落实到位。他们应该如何处理常见的投诉?他们应该如何去安抚那些有合理投诉的客户?如果客户报告了一个新的错误,而团队正在努力修复,该怎么办?这些问题大多存在于工程决策的泡沫之外。不过,我还是建议工程部在进行这些讨论的会议上有一个席位。
至少,工程师应该了解客户的反馈;应用商店的评级,客户的信息,并有能力深入研究围绕IAP功能的常见问题。付费的客户理应期待事情 "正常运行",而作为工程师,我们应该知道何时以及为何出现这种情况。
多平台IAP挑战将是你需要处理的一个反复出现的主题,假设你在iOS、Android和可能的其他平台(如网络)上销售。每个平台将有不同的税收政策。你必须处理客户在一个平台上购买IAP,然后转到另一个平台的问题。
例如,当用户在iOS上购买了IAP,然后又买了一部新的安卓手机,会发生什么情况;他们会再次订阅吗?你会建立一个流程来支持 "转移 "订阅吗?你的后台会不会 "检测 "到同一个人在两个平台上的订阅?你会不会有一个客户支持手册,告诉即将更换手机的人该怎么做?在这种情况下,你的竞争对手是怎么做的;你能做得更好吗?
至少可以说,A/B测试IAPs是具有挑战性的: 苹果和谷歌都没有为这种方法提供本地支持。你将不得不想出自己的解决方案来试验定价点,并很可能发现自己建立并必须维护独立的订阅组。客户在测试后将被 "锁定 "在这些组中,增加了你需要管理的 "IAP债务"。
将客户锁定在同一个订阅组有经济上的好处。如果客户订阅超过一年,苹果的订阅收入分成就会从30%下降到15%。然而,如果用户转移到一个不同的组,这个计时器就会 "重置"。这意味着创建过多这样的群组没有什么经济动力。
实验不同的 "包装",如层级、功能集和定价,变得更加
与网络相比,在IAP中更具挑战性。一个常见的挑战是在你的用户群中的不同群体中测试不同的定价集。如果你想尝试简单的订阅服务以外的东西,你需要提前做好计划。
祖传的订阅定价是你可能面临的另一个问题,特别是当你通过你的应用程序销售SaaS产品时。比方说,你尝试了一个套餐,但对大多数用户来说效果并不好,于是你退出了这个产品。这是一种预期的最佳做法,即你要为购买这个套餐的客户提供祖父级的服务,并在一段时间内支持这个退休的产品。如果你不这样做,你将面临用户流失和用户反感,你的品牌也将受到影响。
实验不同的IAP套餐的一个常见和明智的方法是这样的。
- 提前计划,以便有明确的下一步行动,包括定价实验成功和不成功的时候。你的成功衡量标准是什么?
- 在一个较短的时间内进行实验。
- 提供一个月的、可取消的定价实验订阅。
- 如果定价实验不成功,你需要提高价格,对订阅了这个定价计划的客户要尽可能灵活。
缺乏对任何非基本方案的IAP工具支持可能是最让你头疼的地方。无论是苹果,还是谷歌,都没有建立任何超越简单的一次性产品或订阅产品。当你建立复杂的应用程序,或有许多用户的应用程序时,你可能会发现企业希望有更多的选择,而你自己也在寻找如何解决限制性的IAP功能集。
与采集IAP用户数据的后端团队合作,对于建立一个坚实的产品至关重要。后台团队可能必须与iOS、安卓和可能的网络团队合作,因为每个平台处理付款和订阅的方式不同。
你需要教育后端团队,让他们了解iOS或Android如何处理IAP,以及你需要测试哪些边缘情况。与后端团队合作也是一个很好的机会,可以接触到IAP在其他平台上是如何工作的,以及网络如何处理相同的问题空间。
进一步阅读。
- 在iOS和Android上用沙盒测试应用内购买 来自RevenueCat
- 用沙盒测试应用内购买](go.mobileatscale.com/sandbox-ios) 来自苹果公司
- 收入猫的iOS订阅测试指南
- 测试你的Google Play计费库集成 来自谷歌
- 在Google Play商店沙盒中测试购买 from RevenueCat
- iOS上的应用内购买 来自Ray Wenderlich
- 测试Android上的应用内购买
- iOS应用内购买和测试
- 测试iOS 14中的应用内购买
章节摘要
由Bitrise的Nóra Bézi撰写,作为本书的补充
移动应用程序具有独特的性质,构建它们所面临的挑战也是如此:平台和操作系统碎片化,不断变化的工具集,以及固有的不同生态系统。从前面的章节中我们看到,为移动端开发应用程序会因为要处理状态管理、旧的应用程序版本的长尾、推送通知、深度链接或与第三方库和SDK的集成而变得更加复杂。
移动端的错误是很难恢复的。应用程序崩溃不应掉以轻心--这些可能是移动应用程序中最引人注目的错误,具有严重的、通常是长期的影响。与网页或桌面应用程序相比,用户在移动平台上的宽容度较低--通常会立即放弃那些不符合他们期望的应用程序,转而使用竞争对手的产品。差评会对公司的声誉产生长期的负面影响,而这是很难恢复的。
事实上,移动通信正在迅速发展,这本身就是一个挑战--市场上总是有新的东西。如果你有一个庞大的用户群,满足不同的可访问性需求不仅仅是一件好事,它很快就会成为不可避免的事情。提供离线支持是另一个关键功能,因为人们通常希望即使在连接下降时也能继续使用该应用程序。
虽然iOS和Android上的应用内购买选项有其局限性,但它们在移动商务中是必不可少的--不实施这一功能的团队可能会错过一个巨大的收入机会。这些只是需要考虑的一些额外功能,因为它们进一步增加了应用程序架构的复杂性。
维护移动的CI也可能是个问题:在自我托管的解决方案中,团队需要专门的人员来支持基础设施,所以越来越多的团队决定转向云供应商,将这个责任从团队转移到平台。在CI到位后,他们可以实施构建列车来跟踪他们的发布,可视化手动和自动测试的状态,本地化新资源,优化性能测试和逐步推出。
团队应该以增加他们对发布的信心为目标,他们可以通过优化发布策略、整合功能标志、崩溃报告等技术以及采用更多的移动DevOps实践来做到这一点。在CI/CD自动化方面达到高水平的成熟度,对用户手中的应用程序的性能进行持续的测试和监控,不再是开发者的乌托邦梦想,而是必须的,如果你想建立伟大的移动体验。