Android 最近几版的特色主要集中在省电和后台管理上,O的发布,对ServiceBroadcast又近一步加强了管束。主要可概括为如下两点:

      1、后台应用不被允许创建后台服务,必须通过JobScheduler或者Context.startForegroundService()进行创建

      2、特定的隐式广播不再被允许启动,必须通过JobScheduler调用或者显式注册的方式才能启动

      google之所以限制隐式广播,是因为广播的滥用导致设备在息屏等状态下,依然无法有效的做到省电,往往一个系统广播,会唤醒多个未启动的第三方应用。因此在O中,隐式广播的限制是很严厉的。谷歌给出了允许隐式注册的广播列表https://developer.android.com/preview/features/background-broadcasts.html为了方便懒得上墙的小伙伴们,贴出整理的广播列表:

开机广播,之所以被允许,因为每次设备启动只会发送一次1、ACTION_LOCKED_BOOT_COMPLETED(直接启动模式下才会发出)2、ACTION_BOOT_COMPLETED以下三个广播有权限限制,一般应用无法接受。3、ACTION_USER_INITIALIZE4、android.intent.action.USER_ADDED5、android.intent.action.USER_REMOVED地区变更广播,这个地区指的是国家一级,一般不会发送6、ACTION_LOCALE_CHANGED7、时区闹钟变更相关的广播,一般时间类APP需要7、ACTION_TIMEZONE_CHANGED8、ACTION_NEXT_ALARM_CLOCK_CHANGED9、android.intent.action.TIME_SETusb事件广播,需要设备触发usb事件才能发送10、ACTION_USB_ACCESSORY_ATTACHED11、ACTION_USB_ACCESSORY_DETACHED12、ACTION_USB_DEVICE_ATTACHED13、ACTION_USB_DEVICE_DETACHED蓝牙事件广播,需要设备触发蓝牙事件才能发送14、ACTION_CONNECTION_STATE_CHANGED15、ACTION_ACL_CONNECTED16、ACTION_ACL_DISCONNECTEDOEM相关的广播,一般是OEM通讯类应用会需要17、ACTION_CARRIER_CONFIG_CHANGED18、TelephoneyIntents.ACTION_*_SUBSCRIPTION_CHANGED19、TelephoneyIntents.SECRET_CODE_ACTION登录用户状态发生改变时,这里指的是google登录,一般我们用不到,同时这个广播也在API26中废弃了。20、LOGIN_ACCOUNTS_CHANGED_ACTION用户通过设置页面清除掉应用数据后才会发出21、ACTION_PACKAGE_DATA_CLEARED来电广播22、ACTION_NEW_OUTGOING_CALL设备隐私状态变更广播23、ACTION_DEVICE_OWNER_CHANGED日历提醒广播,是由日历提供者发送给日历程序的24、ACTION_EVENT_REMINDER程序卸载广播,跟程序卸载相关的广播中只有这个是被允许的。25、ACTION_PACKAGE_FULLY_REMOVED设备媒体相关广播,但是一般会在开机时发出或者是在物理设备交互时发出。26、ACTION_MEDIA_MOUNTED27、ACTION_MEDIA_UNMOUNTABLE28、ACTION_MEDIA_CHECKING29、ACTION_MEDIA_UNMOUNTED30、ACTION_MEDIA_EJECT31、ACTION_MEDIA_REMOVED32、ACTION_MEDIA_BAD_REMOVAL短信接收广播33、SMS_RECEIVED_ACTION34、WAP_PUSH_RECEIVED_ACTION

    可以概括的说,可以进行隐式注册的广播都是非频繁发送的,或者有着特定的触发场景的。google的目的就是杜绝一个广播唤醒多个后台应用这种现象如果我们的应用中涉及到了列表以外的广播,就有必要进行O的适配了。

    google针对前台应用的定义,认为如果满足以下任意条件,应用将被视为处于前台:

   1、具有可见 Activity(不管该 Activity 已启动还是已暂停)。   2、具有前台服务。   3、另一个前台应用已关联到该应用(不管是通过绑定到其中一个服务,还是通过使用其中一个内容提供程序)。

  但在开发中,我们会更多的遇到后台运行的需求,当应用处于后台时,监听特定的系统广播或者设置守护Service显然不能很好的适应高版本,所以按照google的剧本走才是正道。以上两各变更点都提到了JobSchedulerJobScheduler作为API21新增类,如它的名字计划任务一样,通过设置约束条件,使系统可以在不影响用户体验的情况下安排这些作业执行。应用作业不会主动挤占系统运行时间,而是在约束范围下执行工作。Android也在不断地增加JobScheduler支持的约束条件,Oreo就新增了一个运行场景:

       1、NETWORK_TYPE_METERED 作业需要一个按流量计费的网络连接,比如大多数移动数据网络数据套餐。

新增了两个约束条件:

      1、JobInfo.isRequireStorageNotLow() 如果设备的可用存储空间非常低,作业将不会运行。

      2、JobInfo.isRequireBatteryNotLow() 如果电池电量等于或低于临界阈值,作业将不会运行;临界阈值是指设备显示 Low battery warning系统对话框的电量。

  当你需要持续的后台监听功能时,用守护Service或者监听特定的高频系统广播显然已经不合时宜了,google希望你通过JobSchedular来实现类似的功能。JobScheduler的运行实质是JobServicegoogleJobService的定义有这样一句话:This service executes each incoming job on a {@link android.os.Handler} running on your application's main thread.表明JobService是在主线程处理任务,也就是说当一个JobService处于onStartJob()时,应用进程实际是处于激活状态的,满足上文前台定义中的第二条:具有前台服务。而任务处理又是在系统许可范围内,可谓是皆大欢喜。同时JobService是继承自Service的,它的生命周期是:

onCreated()-->onStartJob-->onStopJob()-->jobFinished()-->onDestroy()

onCreated()继承自ServicegoogleonCreated的定义是这样的:Called by the system when the service is first created.  Do not call this method directly.当前服务被创建时会调用一次,被创建意味着这个服务之前没有存在过或者被onDestroy了。

onStartJob()-->onStopJob()这个工作阶段取决于配置的约束条件,onStartJob()不会无限制的重复执行。如果我们不设定约束条件,那么JobService在创建成功后只会调用一次onStartJob。onDestroy()同样继承自Service的,googleonDestroy的定义有这样一句话:Called by the system to notify a Service that it is no longer used and is being removed.当系统想要回收当前服务时,便会触发onDestroy,至于间隔多久会触发取决于系统当前操作。我们可以在onDestroy()中重新执行一次创建操作,即重新通知系统安排一次计划任务。保证我们的JobScheduler始终存在于系统任务调度队列中了,这样任务就会持续的运行下去,具体操作如下:

    (1)创建一个JobService命名为DetectionService,在onCreated()中显式注册一个BroadcastReceiver,用来接收应用自身的广播或者其他系统广播,作为唤醒JobService的辅助方式。(毕竟还有安全软件这种东西的存在)

    @Override    public void onCreate() {        super.onCreate();        receiver = new AuxiliaryReceiver();        IntentFilter intentFilter = new IntentFilter();        intentFilter.addAction("your app's broadcasts");        intentFilter.addAction(Intent.ACTION_BOOT_COMPLETED);        registerReceiver(receiver, intentFilter);    }

(2)onDestroy()中执行重新创建当前JobService操作,不设定约束条件。

    @Override    public void onDestroy() {        super.onDestroy();        unregisterReceiver(receiver);        JobScheduler scheduler = null;        if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.M){            scheduler = this.getSystemService(JobScheduler.class);        }else{            scheduler = (JobScheduler) this.getSystemService(Context.JOB_SCHEDULER_SERVICE);        }        final JobInfo.Builder builder = new JobInfo.Builder(1024,new ComponentName(this, DetectionService.class));        builder.setPersisted(true);        builder.setOverrideDeadline(1000);        scheduler.schedule(builder.build());    }

(3)onStartJob()中,你可以根据自己的需求安排具体操作。

  这种设计方式,可以实现类似Service常驻后台的效果,同时符合Android O中对后台运行的要求,但是会对省电模式有影响,如果你的APP没有这方面的顾虑话可以采取这种方式,如果有省电相关的需求,那就老老实实的只用JobScheduler启动一次google通过JobScheduler规范后台应用启动的目的,就是为了保证设备的正常休眠和应用功耗的可控,我们在开发过程中更多的去遵守google标准,才能让用户有更好的产品体验。

更多相关文章

  1. 如何在后台运行Linux命令?
  2. Nginx系列教程(六)| 手把手教你搭建 LNMP 架构并部署天空网络电影
  3. 生成release版本的Android系统
  4. ADB使用方法及常用命令
  5. Android(安卓)Wear缺少本质上的创新
  6. Android(安卓)进程保活方案
  7. android toast乱码
  8. android 自定义锁屏
  9. 谷歌推出可穿戴设备专用系统Android(安卓)Wear

随机推荐

  1. Android赢家密码的观点与实践——以软硬
  2. android 自定义ScrollView实现背景图片伸
  3. 这可能是最好的 Android/Kotlin日志输出
  4. Android热修复技术怎么选
  5. Android程序签名详解、打包,分别使用keyto
  6. Sony Tablet S 和 P 的 3G 版本将会在日
  7. Android也能写游戏——五子棋的实现
  8. Android(安卓)反射调用方法并利用此方法
  9. android转型宅家研究小日记(初学者笔记)4
  10. (4.2.2.1)【android开源工具】【Android(安