目录

[TOC]
个人认为热更新虽然是好 但是 像ios直接拒绝使用热更新 也不无道理 本人一直使用传统的版本升级方式 请求接口 返回下载链接 然后下载文件 用Intent吊起安装 android7.0之前是没有问题的 也没有遇到三星note系列的问题(测试机是三星note4 5.0的机器好像。。。) 后来使用note系列的更新版本都有问题 这里分享给大家 避免大家踩坑

  • 使用系统自带的Api(DownloadManager)
  • 请求服务器接口然后配置一些相关的参数(网上百度有很多关于这个Api的介绍)
  • 设置File路径(这里坑坑的 基本上主要的问题都在这)
  • 判断版本>=7.0必须自定义FileProvider(网上解释好像说7.0为了什么什么安全 具体没有了解)
  • <7.0正常使用Intent安装即可(这里的坑就是三星note系列 其他的比如vivo,魅族,华为,非三星note系 列,小米。。没有遇到此类问题)

代码块

/*** 2017/3/9* 版本更新下载类*/public class DownloadController {private DownloadManager mDownManager;private Context mCtx;private String substr;private static DownloadController instance;String path_apk = "";private List<Long> mIdList = new ArrayList<Long>();private DownloadController(Context context) {this.mCtx = context;mDownManager = (DownloadManager) mCtx.getSystemService(Context.DOWNLOAD_SERVICE);}public static DownloadController getInstance(Context context) {if (instance == null) {instance = new DownloadController(context);}return instance;}public long startLauncherDownLoader(String url, long downId) {if (TextUtils.isEmpty(url)) {return -1;}if (mIdList.contains(downId)) {Toast.makeText(mCtx, "正在下载...", Toast.LENGTH_SHORT).show();return downId;}Toast.makeText(mCtx, "开始下载", Toast.LENGTH_SHORT).show();DownloadManager.Request request = new DownloadManager.Request(Uri.parse(url));request.setNotificationVisibility(DownloadManager.Request.VISIBILITY_VISIBLE);request.setVisibleInDownloadsUi(true);String appNmae = mCtx.getResources().getString(R.string.app_name);request.setTitle(appNmae);request.setDescription(appNmae + "正在下载...");request.setAllowedOverRoaming(true);// 设置文件存放目录substr = url.substring(url.lastIndexOf("/") + 1);File file = getDownloadFile();path_apk = file.getPath() + "/" + substr;Log.i("apkpatch", substr + "================" + path_apk);if (file != null) {request.setDestinationUri(Uri.fromFile(new File(file.getPath() + "/" + substr)));} else {request.setDestinationInExternalFilesDir(mCtx, "downloadqzxq",substr);}long id = mDownManager.enqueue(request);mIdList.add(id);return id;}/*** 安装apk** @param id*/public void installApk(Context context, Long id) {try {Intent install = new Intent(Intent.ACTION_VIEW);Uri downloadFileUri = mDownManager.getUriForDownloadedFile(id);install.setDataAndType(downloadFileUri, "application/vnd.android.package-archive");install.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);context.startActivity(install);} catch (Exception e) {}}/*** 安装apk** @paramid*/public void installApkByFile(File file,Context mContext) {try {Intent install = new Intent(Intent.ACTION_VIEW);//7.0系统的安装if (Build.VERSION.SDK_INT>=24){Uri apkUri = FileProvider.getUriForFile(mContext, "com.qizi.yqxq.fileprovider", file);install.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);install.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);install.setDataAndType(apkUri, "application/vnd.android.package-archive");}//<24的安装else {Uri downloadFileUri = Uri.fromFile(file);install.setDataAndType(downloadFileUri, "application/vnd.android.package-archive");install.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);}mCtx.startActivity(install);} catch (Exception e) {e.printStackTrace();}}public File isExistFile(String url) {substr = url.substring(url.lastIndexOf("/") + 1);File file = getDownloadFile();if (file != null && !TextUtils.isEmpty(url)) {File apkFile = new File(file.getPath() + "/" + url.substring(url.lastIndexOf("/") + 1));if (apkFile.exists()) {return apkFile;} }return null;}public void installAPK(Context mContext) {installApkByFile(new File(path_apk),mContext);}public File getDownloadFile() {File files = new File(Environment.getExternalStorageDirectory() + "/" + "downloadqzxq");File[] ffs = files.listFiles();File file2 = null;if (ffs != null) {for (int i = 0; i < ffs.length; i++) {if (ffs[i].getName().equals(substr)) {file2 = new File(substr);}}}if (file2 != null) {if (!file2.exists()) {file2 = files;}} else {file2 = files;}return file2;}
}

以上是我自己的一个下载安装类 咱们先看一下startLauncherDownLoader这个方法 代码中具体的设置 自己可以百度看一下配置 网上有很多介绍 我只选择重要的去解释

   File file = getDownloadFile();

这个方法就是我先去检测我的下载目录是否有我需要更新的apk包,很多人会问 为什么要去检测,这里给大家解释一下 如果正常的安装当弹出安装窗口的时候 用户点击安装就行了 但是如果用户点击取消呢 下一次进来的时候 我们还是提示用户更新 当用户点击更新按钮的时候 我们难道还要让用户去下载吗 这个是肯定不行的 如果之前用户点击取消 第二次再进app的时候点击更新按钮 我们只要吊起本地我们之前下载好的apk安装就行了 因为用户第一次已经下载了 只不过是取消了安装。。。这个解释够清楚了吧接下来看一行代码

File files = new File(Environment.getExternalStorageDirectory() + "/" + "downloadqzxq");

我们看这个 downloadqzxq 这个目录是我手动设置的一个名字(之前用的Environment.DIRECTORY_DOWNLOADS 内存自带的Downloads文件夹) 这个地方就有坑了 三星note系列的手机直接提示我没有权限 可是我明明在minefist里面加内存的读取权限 也申请运行时权限了 结果是不行 换其他的手机都可以 只要三星note系列就不行 有兴趣的可以自己试一下 。。。。(这是一个坑)

7.0的适配

  • 自定义fileProvider
  • 安装的时候去判断版本
 <!--适配版本升级>=7.0的情况--><providerandroid:name="android.support.v4.content.FileProvider"android:authorities="包名.fileprovider"android:grantUriPermissions="true"android:exported="false"><!--元数据--><meta-dataandroid:name="android.support.FILE_PROVIDER_PATHS"android:resource="@xml/file_paths" /></provider>

这里的最好写包名 容易区分 (以上代码在minefest里面配置)
exported:要求必须为false,为true则会报安全异常。grantUriPermissions:true,表示授予 URI 临时访问权限
file_paths如下

<resources><paths><external-pathname="mydemo"path="downloadqzxq" /></paths>
</resources>

这段代码指定共享的目录(在res下面新建一个xml文件夹并且新建文件就行 这里的downloadqzxq 必须必须必须跟咱们之前设置的文件夹名字一样 否则会找不到对应的文件 进而抛出异常)
- 代表的根目录: Context.getFilesDir()
- 代表的根目录: Environment.getExternalStorageDirectory()
- 代表的根目录: getCacheDir()

  public void installApkByFile(File file,Context mContext) {try {Intent install = new Intent(Intent.ACTION_VIEW);//7.0系统的安装if (Build.VERSION.SDK_INT>=24){Uri apkUri = FileProvider.getUriForFile(mContext, "com.qizi.yqxq.fileprovider", file);install.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);install.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);install.setDataAndType(apkUri, "application/vnd.android.package-archive");}//<24的安装else {Uri downloadFileUri = Uri.fromFile(file);install.setDataAndType(downloadFileUri, "application/vnd.android.package-archive");install.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);}mCtx.startActivity(install);} catch (Exception e) {e.printStackTrace();}}

这里的名字com.qizi.yqxq.fileprovider 必须有我们之前配置的名字一样
这里我们去判断版本更新就行了 下面的代码是我自己的广播

public class DownloadCompleteReceiver extends BroadcastReceiver {DownloadController downloadController;@Overridepublic void onReceive(Context context, Intent intent) {if (intent.getAction().equals(DownloadManager.ACTION_DOWNLOAD_COMPLETE)) {downloadController = DownloadController.getInstance(context);downloadController.installAPK(context);}}
}
//这是我在main里面自己的方法 弹窗去提示版本升级 主要是点击里面的代码  拿到下载的链接 然后调用封装好的下载类去下载   public void showUpdatDialog(final Boolean isForce, String version, final String url, String desc) {updateDialog = new VersionUpdateDialog(mContext);if (!MainActivity.this.isFinishing()) {flaotDialog.dismiss();updateDialog.show(version, desc, isForce, new View.OnClickListener() {@Overridepublic void onClick(View v) {downloadController = DownloadController.getInstance(mContext);File apkFile = downloadController.isExistFile(url);if (apkFile != null) {downloadController.installApkByFile(apkFile, mContext);} else {downloadController.startLauncherDownLoader(url, -1);}updateDialog.dismiss();if (isForce) {finish();
//                        exitMainApp();}}}, new View.OnClickListener() {@Overridepublic void onClick(View v) {updateDialog.dismiss();if (isForce) {exitMainApp();}}});}}

总结

  1. 7.0适配必须自定义FileProvider
  2. 三星note系列手机适配 不要使用系统自带的目录 为了统一我们就自定义一个目录
  3. 大家多多踩坑才能有收获啊 !!!!!!!!!!!!!! 大家有问题 可以留言一起交流

Android 版本更新(非热更新) 适配7.0更新 以及三星 note系列读取内存相关目录无权限问题相关推荐

  1. android大屏适配_大屏开创者三星Note系列,也要被更大屏的折叠屏手机取代了

    临近年关,各个手机厂商们的旗舰产品也都发布的差不多了,发布会数量也在逐渐减少,紧随而来的就是一年一度的手机曝光大赛了,关于明年旗舰产品的信息也开始逐渐浮出水面. 其中一条关于三星旗舰的曝光信息则比较特 ...

  2. android 版本更新和下载安装适配7.0 8.0 9.0

    在android 7.0之前版本更新其实相当简单,只需要使用系统下载器就能够完成下载之后安装,但是在7.0之后android升级安全机制,下载安装受到一些限制.工具类拿去用 public class ...

  3. 历代三星Note系列主要参数对比,更新于2021年6月

    历代三星Note系列主要参数对比 三星的Note已大屏和spen著称,历代都是妥妥的安卓机皇. 一.按年份排序 序 型号 年份 处理器 运存 存储 屏幕 摄像头 电池 特性 1 三星 Note1 20 ...

  4. android搜狗互联网链接,完美适配Android5.0搜狗手机浏览器上线

    被网友誉为"移动阅读神器"的搜狗手机浏览器Android版近日获得更新.全新V3.7版本不仅完美适配Android5.0系统,还对小说阅读功能进行再次改进,令网友在阅读.更新小说时 ...

  5. 三星android7.7,三星Note系列更新Android 7.0指南

    Android 7.0已经正式发布了,对于三星旗舰手机Note系列的用户而言,及时更新到最新版的安卓系统,一直是一个心头痛,每次安卓更新,Note系列总是慢人半步. 值得一提的是,三星每年的产品和升级 ...

  6. 华为鸿蒙os2.0更新,鸿蒙OS2.0更新了吗?更新方法、更新包大小、使用体验等都来了...

    在6月2日的华为鸿蒙操作系统及华为全场景新品发布会上,万众瞩目已久的Harmony OS 2.0系统正式发布,在实际操作当中,官方也兑现了此前的预热,在发布会后,不少华为手机用户就已经可以更新到Har ...

  7. 华为鸿蒙os2.0更新,鸿蒙OS2.0更新了吗? 更新方法、更新包大小、使用体验等都来了...

    在6月2日的华为鸿蒙操作系统及华为全场景新品发布会上,万众瞩目已久的Harmony OS 2.0系统正式发布,在实际操作当中,官方也兑现了此前的预热,在发布会后,不少华为手机用户就已经可以更新到Har ...

  8. xz2p更新android 9,索尼 XZ2 迎来安卓 9.0 更新,但少了全面屏手势

    上周末,在 iOS 12 正式版亮相不到一个月的时间里,苹果方面就已经宣布在过去四年里发布的 iOS 设备中,运行 iOS 12 的设备占比达到 53%.但在对比之下,Android P 已经发布了近 ...

  9. 三星+android+7.0+自动纠正单词,升级党必看!三星S/Note系列更新Android 7.0指南

    上周,雷科技(微信ID:leitech)曾为大家提供了一份Android 7.0升级预测名单.现在为了增加针对性,这次笔者就以三星最热门的两大旗舰S和Note系列为例,给大家提供一个全方面的更新指南. ...

最新文章

  1. php文本域输出_PHP转换文本框内容为HTML格式的方法
  2. Java8 stream filter map
  3. android怎么关应用程序,如何关闭Android应用程序?
  4. Sonya and Informatics
  5. 6.dubbo常用的xml配置有哪些_【面试篇】必须掌握的Spring 常用注解
  6. Unity 协程深入解析与原理
  7. python pyquery倒数第二个节点之前的节点_Python中PyQuery库的使用总结
  8. 安卓recovery流程分析【第一篇】
  9. Linux下编译android源码的步骤
  10. .net反编译工具reflector5.0 的介绍及使用
  11. HDU_1874_畅通工程续_最短路问题
  12. 【概率统计】(在更)
  13. java程序设计-飞机大战
  14. 整人的python代码_vbe最新整人代码
  15. matlab 声卡输出,请问高手关于matlab控制声卡输出的问题
  16. Internet Explorer 无法打开搜索页
  17. List of music used by Apple Inc.
  18. 智牛股_第6章_Mybatis Generator代码生成器
  19. SkeyeVSS综合安防视频云服务无插件WEB直播方案中实现抓取快照功能
  20. 趣味解析,斗鱼直播大数据的玩法儿

热门文章

  1. 服务器如何在网上设置共享文件,服务器Linux系统设置共享文件夹方法!
  2. android 11 机型,安卓11支持哪些机型
  3. docker搭建hadoop完全分布式
  4. 笔记本电脑计算机里面怎么管理,Win7笔记本电脑如何分盘?
  5. MySQL数据库学总结很干很有用
  6. ajax的traditional属性作用
  7. HttpURLConnection,getResponseCode,网络超时 相关总结。
  8. 智工教育:公务员行测常识内容考查
  9. ESG成全球风潮,联想造了一个可持续的“进托邦”
  10. 鸿蒙系统小米手机,鸿蒙系统小米手机能用吗?鸿蒙系统支持第三方手机!