Android 8.0后台执行限制

Android O对应用在后台运行时可以执行的操作施加了限制,称为后台执行限制(Background Execution Limits),这可以大大减少应用的内存使用和耗电量,提高用户体验。后台执行限制分为两个部分:后台服务限制(Background Service Limitations)、广播限制(BroadcastLimitations)。


后台服务限制

如何才算是后台应用?除了下面情况外都是后台应用

1. 具有可见的Activity

2. 具有前台服务

3. 另一个前台应用已关联到该应用(通过bindService或者使用该应用的ContentProvider)。


当应用处于后台时:

1.在后台运行的服务在几分钟内会被stop掉(模拟器测试在1分钟左右后被kill掉)。在这段时间内,应用仍可以创建和使用服务。

2.在应用处于后台几分钟后(模拟器测试1分钟左右),应用将不能再通过startService创建后台服务,如果创建则抛出以下异常

Caused by: java.lang.IllegalStateException: Not allowed to start service Intent { cmp=com.example.samsung.test/.TestService }: app is in background
应用处于后台时,虽然不能通过 startService 创建后台服务,但仍可以通过下面的方式创建前台服务。

NotificationManager noti = (NotificationManager)getApplicationContext().getSystemService(NOTIFICATION_SERVICE);
noti.startServiceInForeground();

后台服务会被kill掉,官方推荐可使用AlarmManager、SyncAdapter、JobScheduler代替后台服务。


广播限制

如果应用监听一些系统广播,当系统发出广播时,很多应用都会被唤醒,这会导致所有应用快速地连续消耗资源,从而降低用户体验。其实,大部分应用都不会处理这个广播,应用只是唤醒一下看看和自己是否有关,为了缓解这一问题,Android N对一些广播做出了限制:

1.targetSdkVersionAndroid NAPI level 24)及以上的应用,如果应用在AndroidManifest.xml中静态注册CONNECTIVITY_ACTION这个receiver,应用将不能收到此广播。如果应用使用Context.registerReceiver()动态注册receiver,应用仍可以收到这个广播。

2.运行在Android N及以上设备的应用,无论是targetSdkVersion是否是Android N,应用都不能发送或者接收ACTION_NEW_PICTUREACTION_NEW_VIDEO这两个广播。


Android O执行了更为严格的限制。

1.动态注册的receiver,可接收任何显式和隐式广播。

2.targetSdkVersionAndroid OAPI level 26)及以上的应用,静态注册的receiver将不能收到隐式广播,但可以收到显式广播。下面例子说明

清单文件的receiver声明

<receiver
    android:name=".TestReceiver"
    android:enabled="true">
    <intent-filter>
        <action android:name="com.test.example.testreceiver.action"></action>
    </intent-filter>
</receiver>


Receiver类定义

public class TestReceiver extends BroadcastReceiver {
    @Override
    public void onReceive(Context context, Intent intent) {
        Toast.makeText(context, "onReceive", Toast.LENGTH_SHORT).show();
    }
}


①如果这样发送隐式广播,receiver将接收不到广播。

Intent intent = new Intent();
intent.setAction("com.test.example.testreceiver.action");
sendBroadcast(intent);


②如果这样发送显式广播,receiver仍可以接收到广播

Intent intent = new Intent();
intent.setClassName("com.test.example.testreceiver", "com.test.example.testreceiver.TestReceiver");
sendBroadcast(intent);


虽然静态注册的receiver不能接收隐式广播,但Google考虑到一些广播也不频繁发生,也有一些例外,对这些例外的静态注册的receiver,仍可接收隐式和显式广播。

ACTION_LOCKED_BOOT_COMPLETED、ACTION_BOOT_COMPLETED

ACTION_USER_INITIALIZE

ACTION_TIMEZONE_CHANGED

ACTION_LOCALE_CHANGED

ACTION_USB_ACCESSORY_ATTACHED

ACTION_USB_ACCESSORY_DETACHED

ACTION_USB_DEVICE_ATTACHED

ACTION_USB_DEVICE_DETACHED

ACTION_HEADSET_PLUG

……

详情请参考

https://developer.android.com/preview/features/background-broadcasts.html


据Google工程师透露,Google的目标是充满一次电,手机可用2~3天,这也可看到Google在手机续航方面的努力。

目前只有Android Studio2.4可以下载Android O 预览版SDK,下载地址

https://dl.google.com/dl/android/studio/ide-zips/2.4.0.6/android-studio-ide-171.3934896-windows.zip


Android 8.0新特性-取消大部分静态注册广播

 

    今天楼主在写一个广播的demo,功能非常的简单,就是一个应用发送一个自定义的广播,同时在这个应用里面定义了一个广播接受者,并且在AndroidManifest文件中进行静态的注册。Demo看上去非常的简单,但是在Android  8.0的设备运行这个应用,始终不能接收到这个发送出去的广播,感觉非常的蒙蔽。关键是,在Android 7.0的设备是能够接收到的!

1.原因

   看到这个情况,我就觉得不是我的代码问题,应该是Android 8.0相较于Android 8.0之前的设备有所变换,于是Google了一把,果然被我找到了问题所在。在Google爸爸的Android官网找到了Android 8.0行为变更的介绍,其中有一句说的是:

  这句话的意思就是说,在Android 8.0的平台上,应用不能对大部分的广播进行静态注册,也就是说,不能在AndroidManifest文件对有些广播进行静态注册,这里必须强调是有些广播,因为有些广播还是能够注册的。比如,经过楼主测试,对接收Android 开机的广播通过静态注册还是能够正常接收的。

  Android 8.0行为变更的介绍链接:https://developer.android.com/about/versions/oreo/android-8.0-changes.html?hl=zh-cn,前面那个链接必须通过FQ,当然我们提倡科学上网,所以国内镜像网站链接:https://developer.android.google.cn/about/versions/oreo/android-8.0.html。

2.解决办法

  前面我们知道了是什么原因导致的,只要知道了原因,解决办法就非常容易的想出来的。

  我们知道广播的注册方式分为两种:

    A.静态注册,也就是说在AndroidManifest文件中对BroadcastReceiver进行注册,通常还会加上action用来过滤。

    B.动态注册,调用Context中的registerReceiver对广播进行动态注册,使用unRegisterReceiver方法对广播进行取消注册的操作。

  静态注册不行的话,那我们就动态注册啊!

3.代码

MainActivity文件的代码

复制代码
 1 public class MainActivity extends AppCompatActivity {
 2 
 3     private Button mButton = null;
 4 
 5     private IntentFilter mIntentFilter = null;
 6 
 7     private MyBroadcastReceiver mMyBroadcastRecvier = null;
 8 
 9 
10     @Override
11     protected void onCreate(Bundle savedInstanceState) {
12         super.onCreate(savedInstanceState);
13         setContentView(R.layout.activity_main);
14 
15         //过滤器
16         mIntentFilter = new IntentFilter("pby");
17         //创建广播接收者的对象
18         mMyBroadcastRecvier =  new MyBroadcastReceiver();
19         //注册广播接收者的对象
20         registerReceiver(mMyBroadcastRecvier, mIntentFilter);
21         mButton = (Button) findViewById(R.id.id_button);
22         mButton.setOnClickListener(new View.OnClickListener(){
23             @Override
24             public void onClick(View v) {
25                 Intent intent = new Intent("pby");
26                 //发送一个广播
27                 sendBroadcast(intent);
28             }
29         });
30     }
31 
32     @Override
33     protected void onDestroy() {
34         super.onDestroy();
35         //取消广播接收者的注册
36         unregisterReceiver(mMyBroadcastRecvier);
37     }
38 }
复制代码

MyBroadcastReceiver文件的代码

复制代码
1 public class MyBroadcastReceiver extends BroadcastReceiver {
2     @Override
3     public void onReceive(Context context, Intent intent) {
4         Toast.makeText(context, "收到了自定义的广播", Toast.LENGTH_LONG).show();
5     }
6 }
复制代码

只有上面的简单配置,没有修改AndroidManifest文件中任何的代码


  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值