升级targetSdkVersion为26以后

前言

google从下个月开始,所有在play上架的app都会要求升级的。为了与时俱进,我们的app也要升级到targetSdkVersion=26了,虽然我们的APP是助手类,不可能上架google play。

关于升级后8.0的各种介绍,参考这里https://developer.android.com/about/versions/oreo/

8.0行为变更看这里https://developer.android.com/about/versions/oreo/android-8.0-changes

基本上,看完上面链接里的内容以后,你就能针对你的代码做修改了。下面主要记录一下实际修改中的几处重点。

后台限制

官方介绍:https://developer.android.com/about/versions/oreo/background

Service

如果改成了targetSdkVersion=26+,是不允许在后台启动service的。但是,要注意这里的后台两个字。google文档里已经讲的很清楚,当你的应用处于前台应用时,仍然可以使用startService。

所以,首先要做的是,把之前在Application中startService的代码删除掉,挪到activity的onCreate方法中。或者,在Application中,调用registerActivityLifecycleCallbacks,在回调里startService。

当然,如果你的程序在运行时,有一个常驻通知,那么你可以将你的service变成一个前台service。此时,不能使用startService来启动,要使用startForegroundService,调用该方法就没有必须前台应用的限制了,任何地方都可以。但是,在startForegroundService开启一个service后,必须在5s内,调用它的startForeground()方法,将某个通知和其绑定起来,否则也会出错。

google也给了另外一种官方的后台任务实现方式,那就是使用JobService,关于用法网上一大堆,不再介绍,需要注意的是,这里要规范它的id。如果相同的id重复schedule,那么会先调用onStopJob再调用onStartJob。

如果之前是IntentService,那可以直接用JobIntentService,使用起来更简单。

JobIntentService

附上官方demo

官方DEMO:https://github.com/googlesamples/android-JobScheduler

Receiver

静态注册广播监听系统事件,失效了。关于广播的限制,官方文档里讲的也很清楚。我们要做的就是,把注册了一系列系统action的Receiver,再动态注册一次。比如常用的网络状态切换监听,之前只要写到manifest中就OK,现在必须手动调用一次register方法。还有我们项目中监听其它应用的安装卸载,一样需要动态注册。

registerReceiver()的文档中明确写到,你的Receiver是注册到Application中,我就直接将receiver注册到了application上。

Context-registered receivers receive broadcasts as long as their registering context is valid. For an example, if you register within an Activity context, you receive broadcasts as long as the activity is not destroyed. If you register with the Application context, you receive broadcasts as long as the app is running.

Notification

Notification要求必须设置一个channel,否则是不予展示的。

https://developer.android.com/training/notify-user/channels.html?hl=zh-cn

官方DEMO:https://github.com/googlesamples/android-Notifications

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
if (Build.VERSION.SDK_INT>= Build.VERSION_CODES.O) {
NotificationManager manager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
NotificationChannelGroup group = new NotificationChannelGroup(GROUP_ID, GROUP_NAME);
manager.createNotificationChannelGroup(group);
NotificationChannel channel = new NotificationChannel(CHANNEL_ID, CHANNEL_NAME, NotificationManager.IMPORTANCE_DEFAULT);
channel.setGroup(GROUP_ID);
// ...
manager.createNotificationChannel(channel);
notification = new Notification.Builder(getApplicationContext(), CHANNEL_ID)
// ...
.build();
} else {
notification = new NotificationCompat.Builder(getApplicationContext(), CHANNEL_ID)
// ...
.build();
}

其它影响的地方

升级以后还是有不少影响需要注意:

  1. 第三方SDK,像push sdk,大多使用了service,要在26以上支持,必须更新了。
  2. 权限问题,比如设置屏幕亮度,悬浮窗等。
  3. API变更,比如getRunningService方法在api26以上就失效了。