之前写过一篇 Android 实现应用更新(适配Anndroid N),本篇主要讲解Android O(Android 8.0)上应用更新的适配问题,应用更新的完整实现请结合上一篇文章一起,文末也会给出完整代码链接。

最近测试反馈在Android 8.0的手机上,提示应用更新,更新时会出现下载失败,并且通知栏也没有显示下载的进度的情况,即使下载成功也不会弹出应用安装界面。

实测发现确实是有这样的问题。当targetSdkVersion小于26时,没有问题,当targetSDK等于26时,就会出现上述问题。
上述问题实际上是三个问题:
(1)APK文件下载失败
(2)通知栏不显示
(3)下载成功没有跳出应用安装界面

于是马上想到了应该是Android O(Android 8.0)的新特性导致的。

-APK文件下载失败

通过查看日志信息,是因为在本地SD卡创建下载文件失败。
而创建下载文件失败,日志信息竟然是没有权限,怎么可能,明明点击更新时,动态申请了“读写”权限,这里“读写”权限打双引号,是因为代码中申请的其实是READ_EXTERNAL_STORAGE读存储权限,这在Android O(Android 8.0)之前是没有任何问题的,因为读写是一组权限,同属存储权限,只要申请了同组权限中的一个,同组中的其他在清单文件中列出了的权限也就被授予了。但是Android O(Android 8.0)运行时权限有了变动,就是系统只会授予应用明确请求的权限,
然而一旦用户为应用授予某个权限,则所有后续对该权限组中权限的请求都将被自动批准,但是还是需要去申请,这点和Android O(Android 8.0)之前不同。

由于这里创建下载文件,实际上是往存储中写文件,需要写存储权限WRITE_EXTERNAL_STORAGE,于是将代码点击更新时申请READ_EXTERNAL_STORAGE改为申请WRITE_EXTERNAL_STORAGE。运行测试,APK文件是可以下载成功了。第一个问题得到解决。

-通知栏不显示问题

在Android O(Android 8.0)之前的手机上,更新下载APK文件时,通知栏会显示下载进度的通知,然而Android O(Android 8.0)的手机上,targetSDK等于26时,下载文件并没有通知栏显示。查看官网Android O行为变更,发现通知的创建与显示发生了变化,创建通知之前还需要创建一个NotificationChannel。按照官网的示例对通知的显示做了兼容性处理:(完整代码,文末会给出链接)

 private void notifyUser(int progress) {        if (Build.VERSION.SDK_INT >= 26) {            if (mNotificationChannel == null) {                //创建 通知通道  channelid和channelname是必须的(自己命名就好)                mNotificationChannel = new NotificationChannel("1",                        "Channel1",NotificationManager.IMPORTANCE_HIGH);                mNotificationChannel.enableLights(true);//是否在桌面icon右上角展示小红点                mNotificationChannel.setLightColor(Color.GREEN);//小红点颜色                mNotificationChannel.setShowBadge(true); //是否在久按桌面图标时显示此渠道的通知                mNotificationManager.createNotificationChannel(mNotificationChannel);            }            int notificationId = 0x1234;            Notification.Builder builder = new Notification.Builder(getApplicationContext(), "1");            builder.setOnlyAlertOnce(true);            builder.setSmallIcon(R.mipmap.ic_launcher)                    .setContentText("正在下载新版本,请稍后...")                    .setAutoCancel(true);            if (progress > 0 && progress <= 100) {                builder.setProgress(100, progress, false);            } else {                builder.setProgress(0, 0, false);            }            builder.setContentIntent(progress >= 100 ? this.getContentIntent() :                    PendingIntent.getActivity(this, 0, new Intent(), PendingIntent.FLAG_UPDATE_CURRENT));            Notification notification = builder.build();            mNotificationManager.notify(notificationId, notification);        } else {            NotificationCompat.Builder builder = new NotificationCompat.Builder(this,null);            builder.setSmallIcon(R.mipmap.ic_launcher)                    .setLargeIcon(BitmapFactory.decodeResource(getResources(), R.mipmap.ic_launcher))                    .setContentTitle(getString(R.string.app_name));            if (progress > 0 && progress <= 100) {                builder.setProgress(100, progress, false);            } else {                builder.setProgress(0, 0, false);            }            builder.setAutoCancel(true);            builder.setWhen(System.currentTimeMillis());            builder.setContentIntent(progress >= 100 ? this.getContentIntent() :                    PendingIntent.getActivity(this, 0, new Intent(), PendingIntent.FLAG_UPDATE_CURRENT));            mNotification = builder.build();            mNotificationManager.notify(0, mNotification);        }    }

这里要特别声明一点的是 builder.setOnlyAlertOnce(true);这句代码,
因为在测试的时候发现,通知更新进度的时候,手机会一直有提示音,加上这句代码后就不会一直有提示音了。

然后测试发现下载APK文件时,通知栏就会正常显示通知显示APK下载进度了。
第二个问题也得到了解决。

-APK文件下载成功没有正常跳到应用安装界面

Android O (Android 8.0) 中,Google 移除掉了容易被滥用的“允许未知来源”应用的开关,在安装 Play Store 之外的第三方来源的 Android 应用的时候,竟然没有了“允许未知来源”的检查框,如果你还是想要安装某个被自己所信任的开发者的 app,则需要在每一次都手动授予“安装未知应用”的许可。

首先在AndroidManifest.xml 清单文件中添加安装未知来源应用的权限

    <uses-permission android:name="android.permission.REQUEST_INSTALL_PACKAGES"/>

然后在用户点击更新时判断是否开启了该应用的“允许安装未知来源”的权限,没有的话,就引导用户去开启该应用的“允许安装未知来源”的权限,判断代码如下:(完整代码,文末会给出链接)

private void downloadAPK(){      boolean hasInstallPerssion = getPackageManager().canRequestPackageInstalls();            if (hasInstallPerssion ) {               //安装应用的逻辑            } else {               //跳转至“安装未知应用”权限界面,引导用户开启权限,可以在onActivityResult中接收权限的开启结果                Intent intent = new Intent(Settings.ACTION_MANAGE_UNKNOWN_APP_SOURCES);                startActivityForResult(intent, REQUEST_CODE_UNKNOWN_APP);            }          }//接收“安装未知应用”权限的开启结果@Override    protected void onActivityResult(int requestCode, int resultCode, Intent data) {        super.onActivityResult(requestCode, resultCode, data);        if (requestCode == REQUEST_CODE_UNKNOWN_APP) {            downloadAPK();        }    }

这样点击更新时引导用户开启“允许安装未知来源”的权限后,APK文件下载成功后也
成功的跳转到应用安装界面。第三个问题也得到了解决。

至此应用更新在Android O(Android 8.0)上的问题就都得到了解决,成功的适配了Android O。

应用更新的完整实现请结合上一篇 Android 实现应用更新(适配Anndroid N)

应用跟新的完整代码地址:
https://github.com/maqing-programmer/AppUpdateDemo

更多相关文章

  1. 反编译apk文件
  2. Android日志打印类LogUtils,能够定位到类名,方法名以及出现错误的
  3. 对于Android DEX文件详细说明
  4. 利用Android SDK免root权限抓屏
  5. android webview处理h5打开本地文件浏览器的功能
  6. Android之RemoteViews篇上————通知栏和桌面小控件
  7. android系统文件的权限
  8. Android通知MediaScanner扫描指定的文件

随机推荐

  1. Android开发——手机拨号程序实现
  2. Android中动画实现单击按钮控制开屏关屏
  3. Android中AlarmManager+Notification实现
  4. Android(安卓)app的混淆打包
  5. Android(安卓)logcat 后台运行
  6. Android(安卓)4.x下基于wm8994的mic检测
  7. Android四大组件中每个组件的作用是什么?
  8. 认识 android 中的 LayoutInflater
  9. Android教程之如何使用自定义字体
  10. 不同android 版本的webview底层实现有差