话不多说,进入正题,由于本人的App最近在适配Android 8.0,因此把适配过程中遇到的一些内容写下来,作为一篇博客,一则可以自己过段时间的回顾。二则也可以给别人一些建议和参考。App主要适配了以下四点
1.通知
官方文档
以 SDK 的 Android 8.0 版本为目标平台的应用必须实现一个或多个通知渠道,以便向用户发布通知。
适配方案
在Android 8.0之前,我们要创建一个通知主要是以下的方法
NotificationCompat.Builder builder = new NotificationCompat.Builder(mContext);
复制代码
或者
Notification.Builder builder = new Notification.Builder(mContext);
复制代码
这两个方案都只需要传入Context一个参数即可。但到了8.0系统引入了ChannelId,ChannelGroup概念。若不加ChannelId这个参数,通知是不会被唤起的。构造通知的话代码需如下处理
- 创建小组(这个可有可无,有点话分类更加清晰)
public static String createNotificationChannelGroup(Context context, String groupId, String groupName) {
if (Build.VERSION.SDK_INT >= 26) {
ArrayList<NotificationChannelGroup> groups = new ArrayList<>();
NotificationChannelGroup group = new NotificationChannelGroup(groupId, groupName);
groups.add(group);
NotificationManager notificationManager = (NotificationManager) context.getSystemService(
Context.NOTIFICATION_SERVICE);
if (notificationManager != null) {
notificationManager.createNotificationChannelGroups(groups);
}
}
return groupId;
}
复制代码
- 创建通道
public static String createNotificationChannel(Context context, String groupId, String channelId, String channelName) {
if (Build.VERSION.SDK_INT >= 26) {
NotificationChannel channel = new NotificationChannel(channelId, channelName, NotificationManager.IMPORTANCE_DEFAULT);
channel.enableLights(true);
channel.setLightColor(ContextCompat.getColor(context, R.color.colorPrimary));
channel.setShowBadge(true);
channel.setLockscreenVisibility(NotificationCompat.VISIBILITY_PRIVATE);
channel.setBypassDnd(true);
channel.setGroup(groupId);
NotificationManager notificationManager = (NotificationManager) context.getSystemService(
Context.NOTIFICATION_SERVICE);
if (notificationManager != null) {
notificationManager.createNotificationChannel(channel);
}
}
return channelId;
}
复制代码
- 构建通知
NotificationCompat.Builder builder = new NotificationCompat.Builder(mContext, channelId);
复制代码
适配后感受
适配完了,效果图如图所示
组名和包名id需注意需要唯一,建议可以使用业务名来进行命名。
2.广播限制
官方文档
Android 8.0 的应用无法继续在其清单中为隐式广播注册广播接收器。
适配方案
Context.registerReceiver()进行动态注册广播或者添加包名发送唯一的显示广播。 本来google有这个限制就是为了你一个广播下去各个App都起来了,导致资源的浪费。发个唯一确定包的广播,当然没什么问题。代码如下。
intent.setPackage(context.getPackageName());
复制代码
适配后感受
这个适配还是比较好处理的。通过反编译查看AndroidManifest.xml中广播接收器即可。不过有个坑是第三方静态广播的处理。尤其是各种推送sdk里面有很多静态广播。这些需要查看相应的文档去适配。自己的项目中用到的推送主要有个推以及信鸽。这两个最新版已经兼容了Android 8.0.
3.应用快捷键
官方文档
Android 8.0 对应用快捷方式做出了以下变更: com.android.launcher.action.INSTALL_SHORTCUT 广播不再会对您的应用有任何影响,因为它现在是私有的隐式广播。相反,您应使用 ShortcutManager 类中的 requestPinShortcut() 函数创建应用快捷方式。
适配方案
简而言之由于Android 8.0对私有的隐式广播的限制,导致8.0之前用隐式广播方法来创建快捷方式将失效。而系统推荐我们使用ShortcutManager类来实现创建快捷方式。 适配代码如下:
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
ShortcutManager scm = (ShortcutManager) context.getSystemService(Context.SHORTCUT_SERVICE);
if (scm != null) {
ShortcutInfo si = new ShortcutInfo.Builder(context, "id")
.setIcon(Icon.createWithResource(context, R.drawable.watermelon))
.setShortLabel(context.getResources().getString(R.string.watermelon))
.setIntent(intent)
.build();
boolean result = scm.requestPinShortcut(si, null);
}
} else {
Intent shortcut = new Intent("com.android.launcher.action.INSTALL_SHORTCUT");
shortcut.putExtra(Intent.EXTRA_SHORTCUT_NAME,context.getResources().getString(R.string.watermelon));
ShortcutIconResource iconRes = ShortcutIconResource.fromContext(context, R.drawable.watermelon);
shortcut.putExtra(Intent.EXTRA_SHORTCUT_ICON_RESOURCE, iconRes);
shortcut.putExtra(Intent.EXTRA_SHORTCUT_INTENT, intent);
shortcut.putExtra("duplicate", false);
context.sendBroadcast(shortcut);
}
复制代码
适配后感受
自己在搞这个适配的时候发现应该是国内各厂商自定义了8.0系统,导致某些现象会和文档有出入。比如华为会默认安装自动生成一个快捷方式。当你再创建一个快捷方式时若名字和Mainfest中清单app名相同时其会当作同一个快捷方式并告知你已有一个快捷方式存在。不过这个并没有什么特别的影响。快捷方式需要注意的避免重复添加。
4.后台服务
官方说明
如果针对 Android 8.0 的应用尝试在不允许其创建后台服务的情况下使用 startService() 函数,则该函数将引发一个 IllegalStateException。
适配方案
刚看到文档有点懵逼,什么是不允许创建后台服务。于是自己写了一个demo,试了一下,思路就是每隔20秒app调用一下startService()函数。果然一分多钟的时候看到了如下内容。
因此也明白了文档所描述的意思,就是当app在后台一定时间以后,app若再调用startService()方法就会报错,这个时间其实跟设备坏境都有关系,但是时间不长。
具体适配跟官方文档给的建议一样。使用了JobScheduler代替了Service的功能
在大多数情况下,应用都可以使用 JobScheduler 作业克服这些限制。 这种方式让应用安排为在未活跃运行时执行工作,不过仍能够使系统可以在不影响用户体验的情况下安排这些作业。
适配后感受
JobScheduler 这个掌握基础的还是比较容易的。可以看下官方文档。
其他Android 8.0行为变更
- 悬浮窗适配
- 运行时权限
- APK安装
这些因为对自己的App没有特定影响所以未进行特定的处理。有需要的可以查看一下google适配的文档 参考资料:developer.android.google.cn/about/versi…