Skip to content

Latest commit

 

History

History
109 lines (74 loc) · 4.48 KB

0014-android-8.0-changes.asc

File metadata and controls

109 lines (74 loc) · 4.48 KB

Android 8.0 Changes

在我看来,需要重点关注如下方面:

  • 对Broadcast的限制

  • 对后台Service的限制

1. 所有应用

1.1. 后台运行限制

从Android M以来,Android每个版本都为提升Android设备的电池续航做了不少努力,同时也为应用带来了越来越多的限制。

在Android O中,如果应用进入cached状态(即没有任何正在运行的component),系统将自动释放wakelock。

1.2. 对Service的限制

Android O不再允许background应用运行background service。

对于一个正在运行的应用,如果下列条件之一成立,那么该应用为foreground:

  • 它有一个可见的Activity(不论是started状态还是paused状态)。

  • 它有一个foreground service。

  • 有其它foreground应用连接到它(不论是通过bind service还是访问content provider)。

如果上述条件都不满足,那么该应用为background。

当一个应用为foreground时,它可以自由地运行foreground service和background service。 在它转变为background时,它有一个几分钟的时间窗口,在此期间它依然可以运行service。 在那时间窗口之后,该应用将为idle状态。此时,系统会停掉该应用的background service。

当一个应用为background时,如果发生了某些特定事件(如,收到FCM高优先级消息、收到SMS/MMS broadcast、 执行Notification的PendingIntent等),该应用也会有一个几分钟的时间窗口,在此期间,它可以无限制地运行service。

💡
在OPP3版本中,测试结果表明,系统在等待1~1.5分钟后会stop background service。
💡
不论应用是foreground还是background状态,其它应用都可以正常地去bind该应用的bound service。

在Android O中,创建foreground service的方式也发生了变化:

  1. 由于Android O不允许background应用创建background service。因此 ,需要先调用Context#startForegroundService()来启动一个foreground service。

  2. app需要在5秒内调用Service#startForeground()来展示用户可见的notification。 如果app没能在5秒内调用Service#startForeground(),系统将停掉该service,并把该应用置为ANR状态。

2. target SDK为Android 8.0及以上版本的应用

2.1. 对Broadcast的限制

当我们调用 Context#sendBroadcast() 发送broadcast时,这个broadcast要么是explicit,要么是implicit。 如何判断呢?如果一个broadcast有明确的接收app,那么其就是explicit(例如,指定了component,或者指定了包名); 如果一个broadcast没有明确的接收app,那么它就是implicit。

例如,

// case 1: explicit
Intent intent1 = new Intent(CommonConstants.ACTION_APP1_TEST_SELF);
intent1.setPackage(getPackageName());
context.sendBroadcast(intent1);

// case 2: explicit
Intent intent2 = new Intent();
intent2.setComponent(cn);
context.sendBroadcast(intent2);

// case 3: implicit
Intent intent3 = new Intent(CommonConstants.ACTION_APP1_TEST_NORMAL);
context.sendBroadcast(intent3);

// case 4: implicit with permission
Intent inten4 = new Intent(CommonConstants.ACTION_APP1_TEST_PERM_SIGN);
context.sendBroadcast(inten4, CommonConstants.PERM_SIGN);

在Android O中,对Broadcast新增了如下限制:

  • 如果应用的target SDK为Android O或者以上版本,在AndroidManifest.xml中注册的 BroadcastReceiver将无法再接收到implicit broadcast。 有一个例外情况,如果此implicit broadcast是通过"signature"保护级别的权限发送的,且目标应用也有此权限, 那么在AndroidManifest.xml中注册的Broadcast依然可以接收到此broadcast。

没有变化的地方:

  • 在AndroidManifest.xml中注册的BroadcastReceiver依然可以接收到explicit broadcast。

  • 通过Context#registerReceiver()注册的BroadcastReceiver依然可以接收到所有broadcast。

  • 如果app的target SDK为Android 8.0之前的版本,在AndroidManifest.xml中注册的BroadcastReceiver依然可以接收所有broadcast。

💡
AndroidOExplorer 中的测试代码。
💡
即使app的target SDK为Android O之前,用户也可以在Settings中app详情页面强制禁用app在后台运行。