Android 8.0适配指北

又到了7月,这是我一年一度的写适配文章的时间,今年到了安卓8.0。为什么我会总会选在这个时间点,因为国内的手机升级总是慢一拍,还有好多的新特性可能也不支持。所以在没有真机的情况下,这类的适配也只是面向模拟器的适配,感觉只能是个参考,并不敢直接用到自己的项目上。不过这几年升级跟进速度是越来越快了,大概从去年底到五月基本都已经吃上奥利奥了。所以使用8.0的用户也越来越多了,适配的时机也就来了。好吧,结束这段瞎掰。。。

适配是个循序渐进的事情,不要想着一步到位。所以如果你还没有适配6.0或7.0可以先看看我之前的两篇了解一下。

1.准备工作

将我们项目中的targetSdkVersion改为 26(8.0) 或者 27(8.1),记住不要超过27,毕竟我还没有告诉你Android P怎么适配(滑稽)。

2.运行时权限

首先引用官方的原文。


 

所谓权限组如下: 
Android 8.0适配指北

所以总结下来,如果你之前是用什么权限就去申请什么权限,那么恭喜你,这个变化不会影响到你。如果你只申请了权限组中的某些权限,却用了同组的其他权限,那么你就需要去适配一下了。

那么怎么适配呢,如果你去检查之前每个申请权限的地方,未免太过麻烦。那么你可以根据你项目中的Manifest文件中需要的权限与权限组去对比,整理出你需要申请的各个权限组。比如你需要android.permission.CALL_PHONE(打电话)与android.permission.READ_PHONE_STATE(读取手机状态) 这两个权限。那么你就整理出了类似下面的类。

public class PermissionGroup { 
   //Phone权限 public static String[] PHONE = new String[] 
       { 
         Manifest.permission.READ_PHONE_STATE, Manifest.permission.CALL_PHONE 
       }; 
... }
到时在申请权限时就可以直接获取它,一次将它们都申请了。这样就防止了遗漏某个权限,导致的异常。

3.通知适配

其实8.0在通知这里变化还挺多的,比如通知渠道通知标志通知超时背景颜色的等,详细的说明可以去看官方的Android 8.0 功能和 API。虽然变化很多,但是国内的机子貌似支持的不多。。。我在小米的文档中了解到,Android 已将通知渠道的逻辑纳入 Android Compatibility Definition Document (CDD) 中,意味着所有 Android 厂商都必须支持。所以我们可以放心的去适配。

Android 8.0适配指北

 

我个人很喜欢这个新特性。也就是说,我们可以将我们给用户的通知进行分类,我用高德地图app来举例,从左到右分别是小米(MIUI10)、华为(EMUI 8.1.0)、一加(氢OS 5.1):

Android 8.0适配指北   Android 8.0适配指北   Android 8.0适配指北

可以看到高德地图分的很细致,分为四个组共13个类别(华为貌似对组不生效)。这样有个好处,我们可以控制我们想收到的通知,比如我不喜欢运营活动通知,那我就可以把它关闭。这样避免大量的不必要通知,否则使得用户觉得烦,一棒子打死。直接关闭你的允许通知。当然了,大量app都还没有适配,适配的也都分的不是很细致,比如下图的QQ。(没有对比就没有伤害)

Android 8.0适配指北    Android 8.0适配指北

当然更重要的问题是,如果不去适配,可能通知都不会弹出来。那么适配的方法如下:


效果如下: 
Android 8.0适配指北    Android 8.0适配指北    Android 8.0适配指北

华为手机当只有一个渠道时,不会显示,会当做默认通知处理,除非一个以上。

 

删除渠道代码如下:


4.悬浮窗适配

使用 SYSTEM_ALERT_WINDOW 权限的应用无法再使用以下窗口类型来在其他应用和系统窗口上方显示提醒窗口:

  • TYPE_PHONE
  • TYPE_PRIORITY_PHONE
  • TYPE_SYSTEM_ALERT
  • TYPE_SYSTEM_OVERLAY
  • TYPE_SYSTEM_ERROR

相反,应用必须使用名为 TYPE_APPLICATION_OVERLAY 的新窗口类型。

也就是说需要在之前的基础上判断一下:

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { 
mWindowParams.type = WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY 
}else 
{ 
mWindowParams.type = WindowManager.LayoutParams.TYPE_SYSTEM_ALERT 
}

当然记得需要有权限

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

再进行判断:

5.安装APK

Android 8.0去除了“允许未知来源”选项,所以如果我们的App有安装App的功能(检查更新之类的),那么会无法正常安装。

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

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

这样系统会自动询问用户完成授权。当然你也可以先使用 canRequestPackageInstalls()查询是否有此权限,如果没有的话使用Settings.ACTION_MANAGE_UNKNOWN_APP_SOURCES这个action将用户引导至安装未知应用权限界面去授权。


对于权限组、悬浮窗还有安装未知来源应用的权限适配,我们也可以使用AndPermission。这样更加便捷。

6.集合的处理

现在,AbstractCollection.removeAll(null) 和 AbstractCollection.retainAll(null)始终引发 NullPointerException;之前,当集合为空时不会引发 NullPointerException。所以我们需要做判空处理。

7.后台执行限制

应用在两个方面受到限制:

  • 后台服务限制:处于空闲状态时,应用可以使用的后台服务存在限制。 这些限制不适用于前台服务,因为前台服务更容易引起用户注意。

  • 广播限制:除了有限的例外情况,应用无法使用清单注册隐式广播。 它们仍然可以在运行时注册这些广播,并且可以使用清单注册专门针对它们的显式广播。

在大多数情况下,应用都可以使用 JobScheduler 克服这些限制。 这种方式让应用安排为在未活跃运行时执行工作,不过仍能够使系统可以在不影响用户体验的情况下安排这些作业。关于的用法可以参考官方例子:android-JobScheduler

当然还有后台位置的限制需要去注意。

8.参考