Android7.0版本影响开发的改进分析

本文总结分析了Android7.0版本影响开发的改进。分享给大家供大家参考,具体如下:

低电耗模式

会对闹铃、GPS 和 Wi-Fi 扫描 产生限制.
可参考Optimizing for Doze and App Standby
使用GCM来发送和接受消息

后台优化

Android N 删除了三项隐式广播,隐式广播会在后台频繁启动已注册侦听这些广播的应用。 删除这些广播可以显著提升设备性能和用户体验.

侦听网络变化的主线程广播改为: CONNECTIVITY_CHANGE。
对所有应用都无法 发送和接受 ACTION_NEW_PICTURE 或 ACTION_NEW_VIDEO .

可以使用JobScheduler API ,更多参考后台优化

系统权限更改

为了提高私有文件的安全性,面向 Android 7.0或更高版本的App私有目录被限制访问(0700)。此设置可防止私有文件的元数据泄漏,如它们的大小或是否存在(状态)。此权限策略的更改有多重副作用:

私有文件的文件权限不应再由所有者放宽,为使用MODE_WORLD_READABLE和MODE_WORLD_WRITEABLE而进行的此类尝试将触发SecurityException,会导致App崩溃的。

注:迄今为止,这种限制还不能完全执行。App仍可能使用原生API或File API来修改它们的私有目录权限。但是Google强烈反对放宽私有目录的权限。

传递软件包网域外的 file://URI可能给接收器留下无法访问的路径。因此传递file://URI会触发 FileUriExposedException。分享私有文件内容的推荐方法是使用FileProvider。

DownloadManager不再按文件名分享私人存储的文件。老的App在访问COLUMN_LOCAL_FILENAME时可能出现无法访问的路径。针对Android 7.0或更高版本开发的应用在尝试访问COLUMN_LOCAL_FILENAME时会触发 SecurityException。通过使用DownloadManager.Request.setDestinationInExternalFilesDir())或DownloadManager.Request.setDestinationInExternalPublicDir())将下载位置设置为公共位置的老App仍可以访问COLUMN_LOCAL_FILENAME中的路径,但是Google还是强烈反对使用这种方法。访问由DownloadManager公开的文件的首选方式是使用ContentResolver.openFileDescriptor())。

应用间共享文件

对于针对Android 7.0的应用,Android framework执行的StrictMode API禁止向你的App外公开file://URI。如果一个包含文件URI的Intent发送到你的应用之外,App会发生FileUriExposedException异常。

若要在应用间共享文件,您应发送一项content://URI,并授予URI临时访问权限。进行此授权的最简单方式是使用FileProvider类。如需有关权限和共享文件的更多信息,请参阅共享文件。

解决 Android N 上 安装Apk时报错:android.os.FileUriExposedException:

在AndroidManifest.xml中添加如下代码

<provider
  android:name="android.support.v4.content.FileProvider"
  android:authorities="app的包名.fileProvider"
  android:grantUriPermissions="true"
  android:exported="false">
  <meta-data
    android:name="android.support.FILE_PROVIDER_PATHS"
    android:resource="@xml/file_paths" />
</provider>

注意:

authorities:app的包名.fileProvider
grantUriPermissions:必须是true,表示授予 URI 临时访问权限
exported:必须是false
resource:中的@xml/file_paths是我们接下来要添加的文件

在res目录下新建一个xml文件夹,并且新建一个file_paths的xml文件(如下图)

输入以下内容

<?xml version="1.0" encoding="utf-8"?>
<paths>
  <external-path path="Android/data/app的包名/" name="files_root" />
  <external-path path="." name="external_storage_root" />
</paths>

path:需要临时授权访问的路径(.代表所有路径)
name:就是你给这个访问路径起个名字

最后修改代码:

Intent intent = new Intent(Intent.ACTION_VIEW);
//判断是否是AndroidN以及更高的版本
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
  intent.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
  Uri contentUri = FileProvider.getUriForFile(context, BuildConfig.APPLICATION_ID + ".fileProvider", apkFile);
  intent.setDataAndType(contentUri, "application/vnd.android.package-archive");
} else {
  intent.setDataAndType(Uri.fromFile(apkFile), "application/vnd.android.package-archive");
  intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
}
startActivity(intent);
//以前我们直接 Uri.fromFile(apkFile)构建出一个Uri,现在我们使用FileProvider.getUriForFile(context, BuildConfig.APPLICATION_ID + ".fileProvider", apkFile); //BuildConfig.APPLICATION_ID直接是应用的包名

屏幕缩放

Android 7.0支持用户设置显示尺寸,以放大或缩小屏幕上的所有元素,从而提升设备对视力不佳用户的可访问性。用户无法将屏幕缩放至低于最小屏幕宽度sw320dp,该宽度是Nexus 4的宽度,也是常规中等大小手机的宽度。

当设备密度发生更改时,系统会以如下方式通知正在运行的应用:

1. 如果是面向API leve 23或更低版本系统的应用,系统会自动终止其所有后台进程。也就是说如果用户切换后离开你的App,打开“Settings”更改Display size设置,则系统会像处理内存不足的情况一样终止该应用。如果应用具有任何前台进程,则系统会如处理运行时变更中所述将配置变更通知给这些进程,就像对待设备屏幕方向变更一样,具体大家可以再看看这个超链接。

2. 如果是针对Android 7.0的App,则其所有进程(前台和后台)都会收到有关配置变更的通知,如处理运行时变更中所讲的那样。 大多数App并不需要进行任何更改即可支持此功能,不过前提是这些应用遵循Android最佳实践。具体要检查的事项:

① 在屏幕宽度为 sw320dp 的设备上测试你的App,并确保其正常运行。

② 当设备Config发生变更时,更新任何与密度相关的缓存信息,例如缓存位图或从网络加载的资源。当应用从暂停状态恢复运行时,检查Config的变化。
注:如果你要缓存与配置相关的数据,则最好也包括相关元数据,例如该数据对应的屏幕尺寸或像素密度。保存这些元数据便于你在Config变更后决定是否需要刷新缓存数据。

③ 避免用像素单位指定尺寸,因为像素不会随屏幕密度缩放。应改为使用dp等单位。

用户可以在设置-显示-显示大小修改屏幕宽度,也可以在设置-开发人员选项-最小宽度随意设置指定宽度,开发人员特别需要注意适配

NDK平台库

Android N 做了一些命名空间更改,阻止加载非公开API,会出现一些常见错误

如,UnsatisfiedLinkError

典型修复方法:

1. 使用标准 JNI 函数来替代使用 libandroid_runtime.so 中的 getJavaVM 和 getJNIEnv
2. 使用公开 alternative __system_property_get 来替代使用 libcutils.so 中的 property_get 符号
3. 使用应用本地版本来替代使用 libcrypto.so 中的 SSL_ctrl 符号

注解保留

Android 7.0在注解可见性被忽略时修复错误。这种问题将启用本不应被允许的运行时访问注解。 这些注解包括:

VISIBILITY_BUILD:仅应编译时可见。
VISIBILITY_SYSTEM:运行时应可见,但仅限基本系统。 如果你的App依赖这种行为,请在注解中添加一项运行时必须可用的保留政策。你可通过使用@Retention(RetentionPolicy.RUNTIME) 这样做。

其他重要说明

1. 如果一个针对较低API级别开发的App在Android 7.0上运行,那么在用户更改显示尺寸时,系统将终止此App进程。App必须能够正常处理此情景。否则,当用户从最近使用记录中恢复运行App时,App将会出现崩溃现象。您应测试应用以确保不会发生此行为。要进行此测试,您可以通过DDMS手动终止应用,可以造成相同的崩溃现象。在屏幕密度发生更改时,系统不会自动终止针对Android 7.0及更高版本开发的App;不过这些App仍可能对配置变更做出不良响应。

2. Android 7.0上的应用应能够正常处理配置变更,并且在后续启动时不会出现崩溃现象。你可以通过更改字体大小 (Setting > Display > Font size) 并随后从最近使用记录中恢复运行应用,来验证App行为。

3. 由于之前的Android版本中的一项错误,系统没有对主线程上的一个TCP Socket的写入操作严格检查。Android 7.0修复了这个系统错误。之前有这种行为的App将会引发android.os.NetworkOnMainThreadException。一般情况下,不建议在主线程上执行网络操作,因为这些操作通常都有可能导致ANR和卡顿,这个应该是中所周知的,大家一般不会犯。

4. Debug.startMethodTracing()方法族现在默认在你的共享的存储空间上的软件包特定目录中存储输出,而非 SD卡顶级。这意味着应用不再需要请求WRITE_EXTERNAL_STORAGE权限就可以使用这些API。

5. 许多平台API现在开始检查在Binder事务间发送的大负载,系统现在会将TransactionTooLargeExceptions再次作为RuntimeExceptions引发,而不再只是默默记录或不抛出这个错误。一个常见例子是在Activity.onSaveInstanceState())上存储过多数据,导致ActivityThread.StopInfo在你的App面向 Android 7.0时引发RuntimeException。

6. 如果应用向View post Runnable任务,并且View未附加到窗口,系统会用View为Runnable任务排队;在 View附加到窗口之前,Runnable任务不会执行。 此行为会修复以下错误:

① 如果一个App是从并非预期Window UI线程的其他线程发布到View,则Runnable可能会因此运行错误。

② 如果Runnable任务是从并非looper thread的其他线程发布,则应用可能会曝光Runnable任务。

7. 如果Android 7.0上有DELETE_PACKAGES权限的应用尝试删除一个软件包,但另一项应用已经安装了这个软件包,则系统可能要求用户确认。在这种情况下,应用在调用PackageInstaller.uninstall()) 时的返回状态应为STATUS_PENDING_USER_ACTION。

更多关于Android相关内容感兴趣的读者可查看本站专题:《Android开发入门与进阶教程》、《Android调试技巧与常见问题解决方法汇总》、《Android基本组件用法总结》、《Android视图View技巧总结》、《Android布局layout技巧总结》及《Android控件用法总结》

希望本文所述对大家Android程序设计有所帮助。

(0)

相关推荐

  • Android7.0开发实现Launcher3去掉应用抽屉的方法详解

    本文实例讲述了Android7.0开发实现Launcher3去掉应用抽屉的方法.分享给大家供大家参考,具体如下: 年初做过一个项目,有一个需求就是需要将桌面变为单层不需要二级菜单.最近几次有小伙伴有这个问我这个解决办法.现在我将分享给大家. 先上效果图:   功能分解 1. 去除Allapp键,调整HotSeat布局 2. 将所有应用摆在launcher第一层 3. 去掉长按时删除选项 解决方案 一.设置总开关 按照6.0 Launcher3 的模式,添加一个开关,控制是否去掉抽屉. Launc

  • Android圆形头像拍照后“无法加载此图片”的问题解决方法(适配Android7.0)

    Feature: 点击选择拍照或者打开相册,选取图片进行裁剪最后设置为圆形头像. Problem: 拍好照片,点击裁剪,弹Toast"无法加载此图片". Solution: 在裁剪的class里加两行代码 intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION); intent.addFlags(Intent.FLAG_GRANT_WRITE_URI_PERMISSION); 主要代码如下: public static final S

  • Android7.0上某些PopuWindow出现显示位置不正确问题的解决方法

    本文实例讲述了Android7.0上某些PopuWindow出现显示位置不正确问题的解决方法.分享给大家供大家参考,具体如下: 情景描述: 在andorid7.0及以上系统,点击某个view,本来期待有一个Popuwindow在该view下面弹出(调用PopuWindow.showAsDropDown(view)方法)但结果PopuWindow却弹出在view上方,顶在系统状态栏下面. 原因分析: 在android7.0上,如果不主动约束PopuWindow的大小,比如,设置布局大小为 MATC

  • 适配android7.0获取文件的Uri的方法

    前言# Android 7.0已经发布很久了,虽然市场份额还不是很高,但是流行起来都是早晚的事,所以适配Android 7.0刻不容缓. Android 7.0 对系统进行了很多的优化:例如文件访问权限,省电,网络,后台等等,其中最突出的就是应用外的Uri访问. 什么时候会用到Uri的应用外访问呢?举一个简单的例子,下载apk更新,这个时候会调用系统功能来安装这个apk,这就是应用外访问文件,需要传入文件的Uri. 但是这样可能会显得不太安全,万一是什么非常重要的文件就糟糕了,所以Android

  • Android7.0 MessageQueue详解

    Android中的消息处理机制大量依赖于Handler.每个Handler都有对应的Looper,用于不断地从对应的MessageQueue中取出消息处理. 一直以来,觉得MessageQueue应该是Java层的抽象,然而事实上MessageQueue的主要部分在Native层中. 自己对MessageQueue在Native层的工作不太熟悉,借此机会分析一下. 一.MessageQueue的创建 当需要使用Looper时,我们会调用Looper的prepare函数: public stati

  • Android7.0 工具类:DiffUtil详解

    一 概述 DiffUtil是support-v7:24.2.0中的新工具类,它用来比较两个数据集,寻找出旧数据集->新数据集的最小变化量. 说到数据集,相信大家知道它是和谁相关的了,就是我的最爱,RecyclerView. 就我使用的这几天来看,它最大的用处就是在RecyclerView刷新时,不再无脑mAdapter.notifyDataSetChanged(). 以前无脑mAdapter.notifyDataSetChanged()有两个缺点: 1.不会触发RecyclerView的动画(删

  • 解决Android7.0更新后无法安装的问题

    最近在我们的应用中加入更新功能,按照往常一样加入代码 if (!apkfile.exists()) { Toast.makeText(mContext, "下载的安装包不存在", Toast.LENGTH_SHORT).show(); return; } Intent install = new Intent(Intent.ACTION_VIEW); install.setDataAndType(Uri.fromFile(apkfile), "application/vnd.

  • Android7.0版本影响开发的改进分析

    本文总结分析了Android7.0版本影响开发的改进.分享给大家供大家参考,具体如下: 低电耗模式 会对闹铃.GPS 和 Wi-Fi 扫描 产生限制. 可参考Optimizing for Doze and App Standby 使用GCM来发送和接受消息 后台优化 Android N 删除了三项隐式广播,隐式广播会在后台频繁启动已注册侦听这些广播的应用. 删除这些广播可以显著提升设备性能和用户体验. 侦听网络变化的主线程广播改为: CONNECTIVITY_CHANGE. 对所有应用都无法 发

  • webpack 4.0.0-beta.0版本新特性介绍

    近年来前端技术如雨后春笋般蓬勃发展,我们也在这个潮流下不断地学习.成长.前端技术的不断发展,给我们提供了许多的便利.例如:JSX的出现为我们提供了一个清晰.直观的方式来描述组件树,LESS/SASS的出现提高了我们书写css的能力,AMD/CommonJS/ES6 的出现为我们模块化开发提供了便利.然而,我们需要使用其它工具将这些工具转化成原生语言以运行在浏览器上.为了能够更好的将这些不同的资源整合到一起,我们就需要一个打包工具,webpack就是这个需求下的产物. webpack 可以看做是模

  • Seraph 4.0版本以后的新的脚本示例

    4.0中,最重要的几大改如下:- 允许数组相互直接赋值,并允许数组成为函数的参数.- 允许在函数中调用后面声明的函数,即函数声明的先后与调用关系无关.使间接递归成为可能.- 允许在定义了函数之后的脚本位置定义全局变量.这样USE子脚本中也可以声明全局变量了,使其功能可以更灵活. 以下分别对这几大改进举例说明允许数组相互直接赋值,并允许数组成为函数的参数. 例1,数组相互直接赋值function maindim arr1[10]arr1[1]=5#将数组arr1整体COPY至arr2arr2=ar

  • vue-cli V3.0版本的使用详解

    vue-cli 3.0版本 目前官网上还不是3.0版本,所以需要在github上面学习使用:github网站:https://github.com/vuejs/vue-cli/tree/dev/docs 1.项目搭建 (1).在上面的GitHub网页中,拉到底部可以看到: 然后在全局中执行命令:sudo npm install -g @vue/cli即可. 最后, vue -V //可以查看到当前的vue是3.0版本了 (2).查看vue 相关指令 vue --help 查看到的常用指令: -V

  • 基于NodeJS+MongoDB+AngularJS+Bootstrap开发书店案例分析

    这章的目的是为了把前面所学习的内容整合一下,这个示例完成一个简单图书管理模块,因为中间需要使用到Bootstrap这里先介绍Bootstrap. 示例名称:天狗书店 功能:完成前后端分离的图书管理功能,总结前端学习过的内容. 技术:NodeJS.Express.Monk.MongoDB.AngularJS.BootStrap.跨域 效果: 一.Bootstrap Bootstrap是一个UI框架,它支持响应式布局,在PC端与移动端都表现不错. Bootstrap是Twitter推出的一款简洁.直

  • 浅谈ThinkPHP5.0版本和ThinkPHP3.2版本的区别

    5.0版本和之前版本的差异较大,本篇对熟悉3.2版本的用户给出了一些5.0的主要区别. URL和路由 5.0的URL访问不再支持普通URL模式,路由也不支持正则路由定义,而是全部改为规则路由配合变量规则(正则定义)的方式: 主要改进如下: 增加路由变量规则: 增加组合变量支持: 增加资源路由: 增加路由分组: 增加闭包定义支持: 增加MISS路由定义: 支持URL路由规则反解析: 请求对象和响应对象 5.0新增了请求对象Request和响应对象Response,Request统一处理请求和获取请

随机推荐