本文翻译自android官方文档 “Android 6.0 Changes“,文中列出了android 6.0版本的几个关键性的变化,供开发者在适配新版本时参考。
下面是翻译的内容。
伴随着新特性与能力,android 6.0包含一些系统更改与API的更改。本文档重点列出了一些关键性的更改,在app中,你需要理解并且应对这些更改。
你需要意识到,如果你之前发布过针对android的app,这些改变将会影响你的app。
预览版引入了一种新的权限模型,即用户现在可以在运行期间直接管理app的权限。当app开发者线性化安装与自动更新流程的同时,这个模型在权限上赋予用户改进的可视性与控制性。对于已安装的app,用户可以单独地授予或者撤回权限。
当你的app的target为M及更高版本时,确保在运行时检查和请求权限。要确定你的app是否被赋予某个权限,可调用新方法checkSelfPermission()
。要请求一个新权限,可调用requestPermissions()
。即使你的app的target是较低版本,你也应当在新的权限模型下测试你的app。
有关新权限模型的详细信息,可参考开发者预览页面Permissions。有关如何评估对app的影响,可参考Testing Guide。
对于闲置的设备和app,预览版引入了一种新的节能优化。
如果要了解更多有关节能的更改,可参考Power-Saving Optimizations。
预览版已经移除对Apache HTTP Client的支持。如果你的app使用了这个client且target为2.3(API Level 9)或以上版本,可使用HttpURLConnection
代替。这个API更改高效,因为它通过透明的压缩和响应缓存降低了网络数据使用量,并且降低耗电量。如要继续使用Apache HTTP Client,你必须在build.grale
文件中首先声明如下的编译期依赖:
android { useLibrary 'org.apache.http.legacy' }
android正在从OpenSSL迁移到BoringSSL库。如果你在app中使用了NDK,不要链接不是组成NDK API的密码库,如libcrypto.so
和libssl.so
。这些库不是公开的API,并且可能没有事先通知地在不同的版本与设备上发生更改或者间断。除此之外,你还可能将自己暴露于安全缺陷中。作为替代,你可以选择修改你的native代码通过JNI调用Java的密码API,或者静态链接密码库。
为了给用户提供更大程度的数据保护,从这个版本开始,对于使用Wi-Fi和蓝牙API的app,android移除了代码访问设备本地硬件标识符的接口。WifiInfo.getMacAddress()
和BluetoothAdapter.getAddress()
方法现在返回的是一个值为02:00:00:00:00:00
的常量。
如果要通过蓝牙和Wi-Fi扫描访问附近外部设备的硬件标识符,你的app必须拥有ACCESS_FINE_LOCATION
或ACCESS_COARSE_LOCATION
权限:
WifiManager.getScanResults()
BluetoothDevice.ACTION_FOUND
BluetoothLeScanner.startScan()
当运行android 6.0 (API Level 23)的设备发起一个背景Wi-Fi或者蓝牙扫描时,这个操作对于外部设备可见,因为它源自一个随机的MAC地址。
上面的最后一句话不知如何翻译,原文是
the operation is visible to external devices as originating from a randomized MAC address.
这个版本移除了方法Notification.setLatestEventInfo()
。作为替代,使用类Notification.Builder
来构建通知。如要重复更新一个通知,可复用Notification.Builder
实例。调用方法build()
来获得更新的Notification
实例。
命令adb shell dumpsys notification
不再打印你的通知文字。作为替代,使用命令adb shell dumpsys notification --noredact
来打印通知对象的文字。
通过AudioManager直接设置音量或者使指定的数据流静音已经不再支持。方法setStreamSolo()已经弃用,你应该调用方法requestAudioFocus()作为替代。类似地,方法setStreamMute()也已弃用;作为替代,应调用方法adjustStreamVolume(),并且传入指令值ADJUST_MUTE或ADJUST_UNMUTE。
当用户在你的app里选择文本,你现在可以使用一个悬浮工具栏
显示文本选择的操作,如剪切,复制和粘贴。这个用户交互的实现与上下文动作栏相似,详见Enableing the contextual action mode for individual views.
要实现文本选择的悬浮工具栏,在当前app中做以下更改:
startActionMode(Callback)
改为startActionMode(Callback, ActionMode.TYPE_FLOATING)
。ActionMode.Callback
的实现改为继承自ActionMode.Callback2
.如果你使用Android Support Library修订版本22.2,需要了解悬浮工具栏并不能向后兼容,并且appcompat会通过使用默认来控制ActionMode
对象。这阻止了悬浮工具栏的显示。如果要在AppCompatActivity
中启用ActionMode
的支持,调用getDelegate()
,然后在返回的AppCompatDelegate
对象上调用setHandleNativeActionModesEnabled()
,并且设置输入参数为false
。这个调用会返回框架的ActionMode
的控制对象。在运行android 6.0 (API Level 23)的设备上,这将允许框架支持ActionBar
或者悬浮工具栏模式,当设备运行android 5.1 (API Level 22) 或更低版本,则只支持ActionBar
模式。
这个版本移除了全局书签的支持。android.provider.Browser.getAllBookmarks()
和android.provider.Browser.saveBookmark()
方法现在已被移除。同样地,READ_HISTORY_BOOKMARKS
和WRITE_HISTORY_BOOKMARKS
权限也被移除。如果你的app的目标是android 6.0 (API Level 23)或更高版本,不要从全局的provider访问书签或者使用书签的权限。作为替代,你的app需要将书签数据保存到程序内部。
随着预览版的发布,Android Keystore provider
不再支持DSA。ECDSA则依然支持。
当安全锁定屏幕被禁用或者重置(例如,被设备或设备管理器)时,无需加密的非活跃(见备注)Keys将不再被删除。需要加密的非活跃Keys在上述事件发生时则将被删除。
“Keys which do not require encryption at rest”这句里边的”at rest”不知该如何翻译,这里暂且译为”非活跃”。
这个发布版本针对Wi-Fi和网络API引入了下面的行为改变:
WifiConfiguration
对象的状态。对于用户或者其它app创建的WifiConfiguration
对象,你不能修改或者删除。disableAllOthers=true
的设置调用enableNetwork()
,设备会断开其它的网络连接,如蜂窝网络。在这个发行版本里,设备不再会断开其它的网络连接。如果你的app的targetSdkVersion
等于或低于20
,它会固定到所选择的Wi-Fi网络。如果你的app的targetSdkVersion
等于或大于21
,使用多网络API(如openConnection()
, bindSocket()
和新方法bindProcessToNetwork()
)来确保网络流量是通过所选择的网络。如果你的app的
targetSdkVersion
等于或低于20
,它会固定到所选择的Wi-Fi网络。
上面这句话翻译的不太准确,理解的不够。原文是:
If your app’s targetSdkVersion is “20” or lower, it is pinned to the selected Wi-Fi network.
在这个版本中,在Camera服务中访问共享资源的模型已经更改,由原来的”先到,先服务”的访问模型更改为优先服务高优先级的进程的访问模型。服务行为的更改包括:
Camera
API中,这将导致在被驱逐的客户端中onError()
方法被调用。在Camera2
API中,将导致在被驱逐的客户端中onDisconnected()
方法被调用。最后一段翻译的尤其晦涩,见谅;请尽量参考原文
ART运行时现在正确地实现了newInstance()
方法的访问规则。这个更改修复了一个问题,即在以前的版本中Dalvik错误地检查访问规则。如果你的app使用了newInstance()
方法并且你想覆盖访问检查,调用setAccessible()
方法并将输入参数设置为true
。如果你的app使用了v7 appcompat library
或者v7 recyclerview library
,你必须更新你的app来使用这些库最新的版本。另外,确保要更新任何在XML中引用的自定义类以便他们的构造函数可以被访问。
这个版本更新了动态链接器的行为。动态链接器现在可以理解一个库的soname
与它的路径 (公共bug 6670) 的不同,并且现在也实现了通过soname
来搜索。之前使用坏的条目DT_NEEDED
(在编译机器的文件系统上通常为绝对路径) 的app可以工作正常,现在载入时则可能失败。
dlopen(3) RTLD_LOCAL
标记现在已被正确地实现。注意默认为RTLD_LOCAL
,所以没有显式使用RTLD_LOCAL
调用dlopen(3)
会受到影响 (除非你的应用显式地使用了RTLD_GLOBAL
)。随着RTLD_LOCAL
,随后调用dlopen(3)
加载库的符号经不可用 (与被DT_NEEDED
引用的情况截然相反)。
在android之前的版本中,如果你的app请求系统加载一个带有文本重定位的共享库,系统会显示一个警告但是依然允许加载这个库。从这个版本开始,如果你的app的target >= 23,系统将不再加载这个库。为了帮助你监测一个库是否加载失败,你的app应该打印dlopen(3)
的失败日志,包括调用dlerror(3)
返回的问题描述文本。如果要了解更多的有关处理文本重定向的内容,请参考这个指南。
“如果你的app请求系统加载一个带有文本重定位的共享库”这句话可能翻译的不准,原文是”if your app requested the system to load a shared library with text relocations”。
平台现在对APK将进行更加严格的验证。如果一个文件在manifest中声明但是在APK中并不存在,那么该APK则被认为是损坏的。如果移除了任何内容,APK需要重新签名。
现在,通过USB端口的设备连接默认情况下将被设置为充电模式。如要通过USB连接访问设备和它的内容,用户必须显式地对这些交互进行授权。如果你的app支持通过USB端口进行与设备的用户交互,需要考虑到这个交互必须被显式地弃用。
对于Android for Work,这个版本包含了以下的行为更改:
DevicePolicyManager
API行为的更改: