适配Android7.0版本更新功能
来源:互联网 发布:网络销售的工作好不好 编辑:程序博客网 时间:2024/06/03 15:32
适配Android7.0版本更新功能
测试手机:华为 Android 7.0
问题1 升级安装失败,程序崩溃:
前面有一篇文章讲过了使用DownloadManager在应用内实现版本更新 详见 Android学习之—-利用DownLoadManager实现版本升级,之前Android 7.0也还没有普及所以一直没有更新代码,没注意到Android7.0的一些版本变化,导致了在Android 7.0 上面使用之前的代码更新安装程序出错,具体错误为:
Caused by: java.lang.SecurityException: COLUMN_LOCAL_FILENAME is deprecated; use ContentResolver.openFileDescriptor() instead at android.app.DownloadManager$CursorTranslator.getString(DownloadManager.java:1503)
会抛出这样一个异常终止程序运行。那么导致整个问题的主要原因就是Android 7.0在文件管理方面更加严格,不随便对外开发文件访问权限,想要访问文件可以使用FileProvider的方式来访问,在7.0系统中,Android禁止通过file://这样的方式来访问,需要使用content://这样的方式来对文件进行访问。 所以在我之前代码中的读取文件更新就会出现这个问题,不过现在我们来对这个问题进行修复。
问题2
安装出现安装包解析异常(图片引用其他文章)
我也网上到处翻查资料 大概有这样几种情况,
1 v1,v2签名的原因,2 apk的签名不一致3 安装文件路径问题
也可以参考 android升级安装包–包解析错误 这篇文章,但是我只遇到过以上的2,3问题,其中2的问题好解决,保证签名一致即可,第3个问题,就又可以牵扯到7.0的安装路径问题上。只要能够找到正确的文件路径,那么就可以正确的安装。
解决办法:
既然知道了问题原因,那么我们就查找对应的解决办法。
第一步骤:了解FileProvider的使用 可以参考官网例子: https://developer.android.google.cn/reference/android/support/v4/content/FileProvider.html
<providerandroid:name="android.support.v4.content.FileProvider"android:authorities="com.mydomain.fileprovider"android:exported="false"android:grantUriPermissions="true"><meta-data android:name="android.support.FILE_PROVIDER_PATHS" android:resource="@xml/file_paths" /></provider>
第二步骤:在manifest中 application中 添加provider标签,修改provider中 android:authorities为你自己的名称 建议使用包名+fileprovider
在res文件夹下面新建一个xml目录,新建一个file_paths文件,上面meta-data中使用到的。
<paths xmlns:android="http://schemas.android.com/apk/res/android"> <external-path name="download" path=""/></paths>
上面的代码paths中不止external-path这一种标签属性,还有其他的,这里不作详细讲解,步骤一里面给出的官网地址里面解释的比我清楚,不过声明这个地址表示 在这个对应的路径下的文件都是可以被共享访问的。
第三步骤:编写代码适配 android7.0,这里我只给出下载部分和安装部分的代码,因为对比之前 Android学习之—-利用DownLoadManager实现版本升级这篇文章除了加上第一步骤和第二步骤以外,其他的就修改了以下给出的代码,
下载部分修改实现细节
1 添加下载类型 -----> request.setMimeType("application/vnd.android.package-archive");2 创建需要保存的File ---> downloadFile = new File(context.getExternalFilesDir(Environment.DIRECTORY_DOWNLOADS), "demo.apk");3 修改------> request.setDestinationInExternalFilesDir() 为request.setDestinationUri()4 调用 request.setDestinationUri(Uri.fromFile(downloadFile));
更新安装部分实现细节修改
1 兼容7.0 ---判断系统版本2 使用FileProvider获取文件uri
具体代码
下载部分
public void gotoUpdate(Context context, String url) { DownloadManager downloadManager = (DownloadManager) context.getSystemService(context.DOWNLOAD_SERVICE); DownloadManager.Request request = new DownloadManager.Request(Uri.parse(url)); request.setMimeType("application/vnd.android.package-archive"); //修改 downloadFile = new File(context.getExternalFilesDir(Environment.DIRECTORY_DOWNLOADS), "demo.apk"); //修改 request.setDestinationUri(Uri.fromFile(downloadFile)); //修改 request.setNotificationVisibility(DownloadManager.Request.VISIBILITY_VISIBLE_NOTIFY_COMPLETED); request.setTitle("下载新版本"); request.setVisibleInDownloadsUi(true); long downloadId = downloadManager.enqueue(request); DownCompleteReceiver downCompleteReceiver = new DownCompleteReceiver(downloadId); context.registerReceiver(downCompleteReceiver, new IntentFilter(DownloadManager.ACTION_DOWNLOAD_COMPLETE)); }
兼容安装部分
if (Build.VERSION.SDK_INT > Build.VERSION_CODES.M) { Uri uri = FileProvider.getUriForFile(context, BuildConfig.APPLICATION_ID + ".fileprovider", downloadFile); //修改 downloadFile 来源于上面下载文件时保存下来的 // BuildConfig.APPLICATION_ID + ".fileprovider" 是在manifest中 Provider里的authorities属性定义的值 Intent installIntent = new Intent(Intent.ACTION_VIEW); installIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); installIntent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION); //临时授权 installIntent.addFlags(Intent.FLAG_GRANT_WRITE_URI_PERMISSION); intent.setDataAndType(uri, "application/vnd.android.package-archive"); context.startActivity(intent); } else { // 获取下载好的 apk 路径 String uriString = c.getString(c.getColumnIndex(DownloadManager.COLUMN_LOCAL_FILENAME)); // 提示用户安装 installAPP(Uri.parse("file://" + uriString), context); }
总的步骤就是
1 manifest文件中添加Provider声明,声明好自己的authorities值,2 在res/xml 目录中新增 file_paths.xml文件,声明需要共享的文件路径3 使用DownloadManager下载文件的时候使用setDestinationUri的方式,保存事先创建的file对象,4 通过版本判断兼容Android7.0以上以及以下的版本 5 通过fileProvider获取到之前file对象的uri6 添加flag 临时授权uri权限
VersionUpdate.java 可以直接拷贝一下代码测试 只需要使用VersionUpdate.newInstance().gotoUpdate()方法即可
public class VersionUpdate {private static VersionUpdate versionUpdate = new VersionUpdate();File downloadFile;public static VersionUpdate newInstance() { return versionUpdate;}private VersionUpdate() {}public void gotoUpdate(Context context, String url) { DownloadManager downloadManager = (DownloadManager) context.getSystemService(context.DOWNLOAD_SERVICE); DownloadManager.Request request = new DownloadManager.Request(Uri.parse(url)); request.setMimeType("application/vnd.android.package-archive"); downloadFile = new File(context.getExternalFilesDir(Environment.DIRECTORY_DOWNLOADS), "demo.apk"); request.setDestinationUri(Uri.fromFile(downloadFile)); request.setNotificationVisibility(DownloadManager.Request.VISIBILITY_VISIBLE_NOTIFY_COMPLETED); request.setTitle("下载新版本"); request.setVisibleInDownloadsUi(true); long downloadId = downloadManager.enqueue(request); DownCompleteReceiver downCompleteReceiver = new DownCompleteReceiver(downloadId); context.registerReceiver(downCompleteReceiver, new IntentFilter(DownloadManager.ACTION_DOWNLOAD_COMPLETE));}public void createDialogUpdate(final Context context, final String url) { AlertDialog.Builder alert = new AlertDialog.Builder(context); alert.setTitle("更新提示") .setMessage("发现新版本,是否立即更新?") .setCancelable(false).setNeutralButton("取消", new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { dialog.dismiss(); } }).setPositiveButton("立即更新", new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { gotoUpdate(context, url); dialog.dismiss(); } }); alert.create().show();}public class DownCompleteReceiver extends BroadcastReceiver { long enqueueId; public DownCompleteReceiver(long enqueueId) { this.enqueueId = enqueueId; } @Override public void onReceive(Context context, Intent intent) { DownloadManager dm = (DownloadManager) context.getSystemService(context.DOWNLOAD_SERVICE); long id = intent.getExtras().getLong(DownloadManager.EXTRA_DOWNLOAD_ID, -1); if (enqueueId != id) { return; } DownloadManager.Query query = new DownloadManager.Query(); query.setFilterById(enqueueId); Cursor c = dm.query(query); if (c != null && c.moveToFirst()) { int columnIndex = c.getColumnIndex(DownloadManager.COLUMN_STATUS); // 下载失败也会返回这个广播,所以要判断下是否真的下载成功 if (DownloadManager.STATUS_SUCCESSFUL == c.getInt(columnIndex)) { if (Build.VERSION.SDK_INT > Build.VERSION_CODES.M) { Uri uri = FileProvider.getUriForFile(context, BuildConfig.APPLICATION_ID + ".fileprovider", downloadFile); Intent installIntent = new Intent(Intent.ACTION_VIEW); installIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); installIntent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION); installIntent.addFlags(Intent.FLAG_GRANT_WRITE_URI_PERMISSION); intent.setDataAndType(uri, "application/vnd.android.package-archive"); context.startActivity(intent); } else { // 获取下载好的 apk 路径 String uriString = c.getString(c.getColumnIndex(DownloadManager.COLUMN_LOCAL_FILENAME)); // 提示用户安装 installAPP(Uri.parse("file://" + uriString), context); } } c.close(); } } private void installAPP(Uri data, Context context) { Intent promptInstall = new Intent(Intent.ACTION_VIEW) .setDataAndType(data, "application/vnd.android.package-archive"); // FLAG_ACTIVITY_NEW_TASK 可以保证安装成功时可以正常打开 app promptInstall.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); context.startActivity(promptInstall); }}
}
2017/9/19 22:16:41 好记性不如烂笔头。
- 适配Android7.0版本更新功能
- android apk版本更新,兼容android7.0
- android7.0 系统更新日志
- Android7.0 更新APK报错适配
- Android7.0分屏功能
- ios 版本更新功能
- android版本更新功能
- android 版本更新功能
- android版本更新功能
- Android版本更新功能
- Android7.0更新一览,快来吃Nougat
- Android7.0 快速开启分屏功能
- Android7.0实现头像更换功能
- Android7.0实现头像更换功能
- Android7.0相机拍照功能导致FileUriExposedException
- Android7.0 nougat适配
- android7.0适配
- Android7.0适配
- vue-cli 动画效果
- 你担心spring容器中scope为prototype的bean太大内存溢出吗?
- c++11新特性
- Ubuntu 安装 Redis -编译方式安装
- 数据结构实验之链表九:双向链表
- 适配Android7.0版本更新功能
- 1007. 素数对猜想 (20)
- java多线程之Lock介绍
- n阶方阵对角线之和
- bzoj 4976: 宝石镶嵌
- PHP-Laravel部署Apache X-debug进行调试
- nginx 504超时 主要是uwsgi 连接数不够用
- 滑板鞋
- windows nginx php 环境搭建