离线下载
PDF版 ePub版

极客学院团队出品 · 更新于 2017-09-25 14:00:37

关于Android N 开发者预览版的一些随想

译者:李鑫

原文:Random Musings on the N Developer Preview

本文为极客学院Wiki组织翻译,转载请注明出处。

时间:2016.3.21

每当谷歌发布新的开发者预览版时,我都会在 API 差异报告和高级别概述查找一番,看看是否存在一些值得开发者更多关注的东西,重点查找一些开发者可能都会使用的主流特性。我也会特别留意一些关注度可能不是很高的东西,因为有些东西都已经淹没在 Java 文档中了。

这次发布的 N 有点像冰山一角。概要中所展示的内容虽然有趣,但到正式版发布之时,改动可能会非常多。这种情况可能跟转换到 OpenJDK 有点关系,详情请参看我之前的随笔

现在就应着手研究的特性

  • 多窗口功能的支持将在短期内获得很多媒体的关注。多窗口支持是板上钉钉的了。除非 targetSdkVersion 为 N(今天,可能最终是 24)并且你特别声明不想让 activity 被调整尺寸,否则你的应用将一定能被用户调整尺寸。这里还有一些例外情况,尤其是能够通过 screenOrientation 修改原始方位的 activity。但总的来说,不管喜欢与否,activity 将来都可以被调整尺寸。而且,用户也希望能够调整你的 activity 的尺寸。综合各种形式的因素考虑,这一特性大概应尽早地经常进行测试。

  • 安卓准备进入桌面市场的消息已经不是新闻了。多窗口支持明显就是为了桌面方式应用而设计的。尽管现在的媒体可能更为关注分屏模式,但我猜到了五月底,媒体的关注焦点将是“自由形态”(freeform)模式(大型设备制造商将能选择启用“自由形态”模式,从而使用户自由地定义每个 activity 的尺寸)。按照谷歌对该模式的阐述,很可能是针对窗口化桌面应用。但我考虑,除了多窗口支持之外,以下改动确实标志着安卓将开始进入桌面领域:

    • 现在可以对剪切、复制、粘贴以及 Activity 中的 onProvideKeyboardShortcuts() 指定专用的键码,暗示将更为关注硬件的键盘输入功能。

    • 现在有了 PointerIcon,以及 View 中的指针捕获钩子,暗示将更为关注鼠标/触控板的输入功能。

    • 现在出现了 FEATURE_ETHERNET,以及大概会有的对应的 <uses-feature> 选项,暗示将更多关注硬连线的网络连接。
  • Android 6.0 引入了 Doze (瞌睡)模式,这曾让一些开发者感到非常吃惊。那时,该模式被限制用于静止状态的设备中(比如晚上放在了床头几上)。到了 Android N 时代,只要设备不处于充电状态,随时都可以启用 Doze 模式——即使设备处于移动状态。这一模式改变的不是应用的行为,而是应用受此影响的程度,另外一个值得注意的问题是,该模式可能会触发用户支持问题的频率。

  • 多语言环境支持也使得资源协议变得更为复杂。需要你更多地关注对语系的完整翻译,而不能是部分的。如果有些语系丢失了一个字符串,用户设备就可能马上在默认的资源集中(如res/values/strings.xml)用随便一个字符串来代替它。在 N 中,用户可能从次级语言环境中获取字符串。如果在翻译集中出现的漏洞足够多的话,那么用户设备屏幕上显示的语言就会完全不同了。一定要确保翻译的完整性,无论是引入翻译,还是添加面向用户字符串时。

  • 还是跟多语言环境支持有关,如果你的应用设置会覆盖用户设备所用的语言环境,那么在使用 N 时请全面测试。

  • 据数据流量节省功能(Data Saver)文档显示,应用需要“对于后台数据使用上的限制,要恰当地处理”。对此我理解为,数据流量节省功能有点像是应用备用功能,除非用户主动使用应用,否则访问互联网功能受限。这一功能同样也需要全面测试才行。

  • 你可能会忍不住使用 ACTION_IGNORE_BACKGROUND_DATA_RESTRICTIONS_SETTINGS 去引导用户将应用添加到 Data Saver 白名单中,以便可以正常进行后台网络访问。但请记住,谷歌也有类似的电池电量白名单……如果使用那个行为,将使得应用被 Play Store 封杀。目前还没有 Data Saver 白名单的相关文档说明……但是,再说一句,在Android 6.0 发布前,对于进入电池电量节省白名单的请求,谷歌方面也没有明说会封杀应用。

  • 总体来说,网络安全配置可以很有效地保护你的应用。开发者们收到的有关介绍失效 X509TrustManager 实现的邮件中涉及到了一个有用的副作用。其中一些失效的TrustManager 实现已经跟使用自签名证书关联到一起了。现在,你可以使用调试-重写来允许应用使用自签名证书。如果我没理解错的话,这意味着可以在需要时(比如测试服务器)光明正大地使用自签名证书,而不用再冒险在产品发布时支持这种证书。

  • 所有典型的 JUnit 测试用例基类都被弃用,比如 ActivityInstrumentationTestCase2ActivityTestCase。如果你还没有这样做,那么差不多会在明年转变成 JUnit4 测试支持。

  • 目前有了一个新的 FileUriExposedException。如果使用 file: Uri 值就会抛出该异常。现在还不完全清除何种情况下抛出。(2016-03-14 更新:如果使用 file:``Uri 值,则几乎会抛出该异常)。StrictMode.VmPolicy.Builder 中的 penaltyDeathOnFileUriExposure() 据推测可能会触发这个异常。但是,含混的措辞说明,或许 N(以及 Android 的未来版本)会采用默认抛出该异常的机制,就像抛出 NetworkOnMainThreadException 异常那样。为了处理这个问题:

    • 如果从第三方应用中接受了 Uri 值,请做好对 content: Uri 值的支持工作。不要犯傻地认为这些值都来自 MediaStore 或具有能够获取的文件路径。请使用 openInputStream()getType() 以及带有 ContentResolverOpenableColumns 来使用 Uri 标识的内容。

    • 如果将 Uri 值发送到其他应用中(ACTION_VIEWACTION_SEND,等等),请继续continue moving over to content: Uri 值。使用 FileProvider,也许也可以辅以 我的 LegacyCompatCursorWrapper (为了避免犯下前面提到的错误)。最低限度也要将你创建这些 Uri 值的方法隔离到未来可能更容易切换到 content: Uri 值的位置下,以防止在生产环境下抛出 FileUriExposedException 异常。
  • 如果你在 BitmapFactory.Options 上使用 inPreferQualityOverSpeed,那么现在看来,这已经被废弃了。相关文档声明,在 N 中标志会被忽略,因为“输出将一直是高质量的”。根据相关的报道,这种做法有点像是乌比冈湖效应,或者也可以说是一直处于愤怒状态的绿巨人

  • 如果你看过 N 的 API 差异报告,可能会有点恐慌吧?兴许会认为谷歌去除了 Html 类中的 fromHtml()toHtml()。这似乎是 API 差异报告措辞中的一个 Bug。那些方法还在。但确实由接受标志参数的额外方法所补充进来的,可以更好地解释或生成 HTML。不过,这反而说明这一代码经过了彻底检查,效果会非常出色。

  • 根据 API 差异报告的描述,StringBuilder (以及遗留的 StringBuffer)不再实现 Appendable。这似乎是报告中的一个 Bug,因为据 Java 文档显示,它们依然能够实现 Appendable。因为在 Java 8 中它们能够实现 Appendable,所以这些类的安卓版本应该也能继续实现 Appendable

另外一些优点(对优点的另类解读)

  • 谷歌继续在堆加更多的存储选项,这次使用的是 ACTION_OPEN_EXTERNAL_DIRECTORYandroid.os.storage.StorageVolume。据我所知,这一做法是为了避免 READ_EXTERNAL_STORAGEWRITE_EXTERNAL_STORAGE,并可能会通过请求用户授予长期细粒度的许可,来允许直接访问更多的可移动存储。听上去有点合理。但是,很多开发者依旧还在学习使用 Android 4.4 所引入的存储访问架构( Storage Access Framework),以及在可移动存储上采取同步限制。更为让人困扰的是,预览版中的 “进一步的详细信息”(“For more information”)链接是空的。

2016-03-10 更新: Ian Lake 指出,“scoped directory access” 文档已经不再更新了

  • android.auditing.SecurityLog 似乎非常有意思(可以记录 adb shell 命令等)。

  • AlarmManager 现在具有进程内的警告。set()setExact()setWindow() 都能接受 OnAlarmListener,并能在时机到来时,在其上调用一个回调函数。

  • 现在有了 commitNow() 选项,执行同步的 FragmentTransaction,而commit() 则是异步的。

  • android.webkit 包有了 ServiceWorker相关类

  • WebSettings 有了 setDisabledActionModeMenuItems(),说明可以限制一些标准的剪切/复制/粘贴操作。如果不打算让这些操作干扰所要渲染的 Web 内容,那么这个参数就非常有用了。

  • WebViewClient 上的 shouldOverrideUrlLoading(WebView, String)被废弃,取而代之的是shouldOverrideUrlLoading(WebView, WebResourceRequest)

  • AbsSeekBar 支持刻度线,我猜测是很大程度受益于 SeekBar

  • Chronometer 支持倒数计秒模式,通过 RemoteViews 包含在应用小组件中。

未解之谜

Intent 有了 ACTION_PACKAGES_SUSPENDEDACTION_PACKAGES_UNSUSPENDED 这两个行为。目前还不清楚这一上下文中的 suspended 究竟是什么意思。更新 2016-03-14:Andriy Petruk 指出这可能跟 Android for Work 项目有关

Intent 中定义了一个 ACTION_QUICK_VIEW,用来“快速查看 URI 或 URI 列表”。但这样一种查看器的具体含义,以及是否能应用一个查看器等问题仍不可清楚,但我想具体的说明也很快会出现。

还有,什么是 AutomaticZenRule?但我想 Phil Jackson 会赞成它。

目前很清楚的是,isolatedProcess 服务可以运行在单独的权限较少的进程。N 提供了 externalService,它要与 isolatedProcess 配合起来,能允许服务“在应用包的调用过程中运行”。但这里所说的“在应用包的调用过程中运行”到底指的是存储,还是许可,还是其他的什么东西呢?

细思极恐

Android 将来的版本可能会不赞成使用额外的隐式广播,以及未绑定的后台服务。基于这种猜测,应避免或去除用于隐式广播的声明清单接收器中的依赖,同样后台服务也应如此。

这一想法来源于在对 CONNECTIVITY_ACTION 改变(不能再在清单中注册它了)的讨论过程中。

谷歌可能将更多的隐式广播转移到了 registerReceiver()-only bucket does not surprise me. 在某种程度上,我吃惊的是他们没有及时针对这一点进行更多的修改。

让我吃惊的是,未绑定服务可能失去支持了。

如果他们说弃用了 FLAG_START_STICKY,我还可以理解。或者更精确地说,如果他们认为带有服务的进程可能更快地被终止,我也可以理解。

IntentService 和服务的其他命令模式用法全部去除,在我看来是有点过头了。 很显然,他们想让开发者把所有的后台作业都塞进各个分散的类别中,利用专门的服务子类(比如JobScheduler),以此来达成控制电池电量和内存消耗的目的。

我对这一做法的前途深表担心。

What Now?

我猜 2016 年 8 月可能会发布一个版本,上下不超过一个月吧。开发者预览版都比以前提早了几个月,同样,8 月也比一般发布新的主流 Andorid 版本的时间要早几个月了。

另一本书的更新内容中将开始介绍 N 开发者预览版,本月晚些时候将予以公布。

— 2016 年 3 月 9 日 Tweet