权限更改
自从Android 6.0加了动态获取一些权限以后Android N 做了一些权限更改,这些更改可能会影响您的应用。
系统权限更改
为了提高私有文件的安全性,面向 Android N 或更高版本的应用私有目录被限制访问 (0700)。 此设置可防止私有文件的元数据泄漏,如它们的大小或存在。 此权限更改有多重副作用:
私有文件的文件权限不应再由所有者放宽,为使用MODE_WORLD_READABLE和/或MODE_WORLD_WRITEABLE而进行的此类尝试将触发SecurityException。
注:迄今为止,这种限制尚不能完全执行。 应用仍可能使用原生 API 或FileAPI 来修改它们的私有目录权限。 但是,我们强烈反对放宽私有目录的权限。
传递软件包网域外的file://URI 可能给接收器留下无法访问的路径。 因此,尝试传递file://URI 会触发FileUriExposedException。 分享私有文件内容的推荐方法是使用FileProvider。
DownloadManager不再按文件名分享私人存储的文件。 旧版应用在访问COLUMN_LOCAL_FILENAME时可能出现无法访问的路径。 面向 Android N 或更高版本的应用在尝试访问COLUMN_LOCAL_FILENAME时会触发SecurityException。 通过使用DownloadManager.Request.setDestinationInExternalFilesDir()或DownloadManager.Request.setDestinationInExternalPublicDir()将下载位置设置为公共位置的旧版应用仍可以访问COLUMN_LOCAL_FILENAME中的路径,但是我们强烈反对使用这种方法。 访问由DownloadManager公开的文件的首选方式是使用ContentResolver.openFileDescriptor()。
应用间共享文件
对于面向 Android N 的应用,Android 框架执行的StrictModeAPI 政策禁止向您的应用外公开file://URI。 如果一项包含文件 URI 的 Intent 离开您的应用,应用失败,并出现FileUriExposedException异常。
若要在应用间共享文件,您应发送一项content://URI,并授予 URI 临时访问权限。 进行此授权的最简单方式是使用FileProvider类。 如需有关权限和共享文件的更多信息,请参阅共享文件。
无障碍改进
为提高平台对于视力不佳或视力受损用户的可用性,Android N 做出了一些更改。这些更改一般并不要求更改您的应用代码,不过您应仔细检查并使用您的应用测试这些功能,以评估它们对用户体验的潜在影响。
屏幕缩放
Android N 支持用户设置显示尺寸,以放大或缩小屏幕上的所有元素,从而提升设备对视力不佳用户的可访问性。用户无法将屏幕缩放至低于最小屏幕宽度sw320dp,该宽度是 Nexus 4 的宽度,也是常规中等大小手机的宽度。
当设备密度发生更改时,系统会以如下方式通知正在运行的应用:
如果是面向 API 级别 23 或更低版本系统的应用,系统会自动终止其所有后台进程。 这意味着如果用户切换离开此类应用,转而打开“Settings”屏幕并更改Display size设置,则系统会像处理内存不足的情况一样终止该应用。如果应用具有任何前台进程,则系统会如处理运行时变更中所述将配置变更通知给这些进程,就像对待设备屏幕方向变更一样。
如果是面向 Android N 的应用,则其所有进程(前台和后台)都会收到有关配置变更的通知,如处理运行时变更中所述。
大多数应用并不需要进行任何更改即可支持此功能,不过前提是这些应用遵循 Android 最佳实践。具体要检查的事项:
在屏幕宽度为sw320dp的设备上测试您的应用,并确保其充分运行。
当设备配置发生变更时,更新任何与密度相关的缓存信息,例如缓存位图或从网络加载的资源。当应用从暂停状态恢复运行时,检查配置变更。
注:如果您要缓存与配置相关的数据,则最好也包括相关元数据,例如该数据对应的屏幕尺寸或像素密度。 保存这些元数据便于您在配置变更后决定是否需要刷新缓存数据。
避免用像素单位指定尺寸,因为像素不会随屏幕密度缩放。应改为使用与密度无关像素(dp) 单位指定尺寸。
设置向导中的视觉设置
Android N 在“Welcome”屏幕中加入了“Vision Settings”,用户可以在新设备上设置以下无障碍功能设置:Magnification gesture、Font size、Display size和TalkBack。 此项变更增强了与不同屏幕设置相关的错误的可见性。 要评估此功能的影响,您应在启用这些设置的状态下测试应用。 您可以在Settings > Accessibility中找到这些设置。
NDK 应用链接至平台库
Android N 做了一些命名空间更改,以阻止加载非公开 API。 如果您使用 NDK,则只能使用 Android 平台提供的公开 API。 在下一个官方发布的 Android 版本上使用非公开 API 会导致应用崩溃。
为提醒您使用了非公开 API,在 Android N 设备上运行的应用会在有应用调用非公开 API 时在日志消息输出中生成一个错误。 此错误还会作为消息显示在设备屏幕上,以帮助增强您对此情况的认识。 您应检查应用代码以删除使用非公开平台 API,并使用预览版设备或模拟器全面测试应用。
如果您的应用依赖平台库,则请参见 NDK 文档,了解使用公开 API 等效项替换普通私有 API 的典型修复。 您还可以链接至平台库,而无需实现此应用,如果应用使用的库是平台的一部分(例如libpng),但不属于 NDK,则更可如此。 此情况下,请确保您的 APK 包含您打算链接到的所有 .so 文件。
注意:有些第三方库可能会链接至非公开 API。 如果您的应用使用这些库,那么当您的应用在下一个官方发布的 Android 版本上运行时可能会出现崩溃现象。
应用不应依赖或使用不属于 NDK 的原生库,因为这些库可能会发生更改或从一个 Android 版本迁移至另一版本。 例如,从 OpenSSL 切换至 BoringSSL 即属于此类更改。 此外,不同的设备可能提供不同级别的兼容性,因为不属于 NDK 中的平台库没有兼容性要求。 如果您必须在较旧设备上访问非 NDK 库,则请依据 Android API 级别进行加载。
为帮助您诊断此类问题,下面列举了一些在您试图使用 Android N 开发应用时可能遇到的Java和 NDK 错误:
Java 错误示例:
java.lang.UnsatisfiedLinkError: dlopen failed: library "/system/lib/libcutils.so"
is not accessible for the namespace "classloader-namespace"
NDK 错误示例:
dlopen failed: cannot locate symbol "__system_property_get" referenced by ...
以下是遇到这类错误的应用的一些典型修复:
可以使用标准 JNI 函数来替代使用 libandroid_runtime.so 中的 getJavaVM 和 getJNIEnv:
AndroidRuntime::getJavaVM -> GetJavaVM from
AndroidRuntime::getJNIEnv -> JavaVM::GetEnv or
JavaVM::AttachCurrentThread from .
可以使用公开alternative __system_property_get来替代使用libcutils.so中的property_get符号。如需这样做,请使用__system_property_get及以下 include 函数:
#include <sys/system_properties.h>
应使用应用本地版本来替代使用libcrypto.so中的SSL_ctrl符号。例如,您应在.so文件中静态链接libcyrpto.a,或者在应用中包含您自己的来自 BoringSSL 或 OpenSSL 的动态libcrypto.so。
待续。。。