Android通过JobScheduler与设置前台服务实现进程保活

在Android系统中,后台服务很容易由于各种原因被系统(手机厂商)杀掉,这就需要开发者对自己的应用进程进行保活,以满足一些功能需求(例如消息推送,音乐播放)。常见的保活方案很多,详情可以看Android进程保活招式大全,本文就新版本比较常用的方案设置前台服务与JobScheduler展开讨论。

一、设置前台服务

1.1如何设置前台服务

设置前台服务在代码中的设置很简单即在service中调用:

startForeground(1,getNotification());

第一个参数是通知id,第二个参数是Notification实例。这个通知也就是这个前台服务要绑定的通知。没错,前台服务必须要绑定一个通知,不然你以为google能给你无缘无故提升服务优先级吗?那么有没有方法去除这个通知栏,降低用户感知度呢?下一节介绍。
好了,设置前台服务是不是很简单呢?别急,我在调用的时候突然发现跟startForeground方法很像的一个方法startForegroundService(Intent service),而且这还是个android O中的新方法,于是google了一下官网,结果发现:


android o关于后台服务限制.png

但是我调试了一下,在我的小米mix2(android8.0.0)和nexus6p(android8.0.0)直接使用startService启动服务都没有问题!当然使用startForegroundService启动服务,然后再使用startForeground设置前台进程也没有问题。难道是官网骗我???可能在比较新的android O中会有这个限制吧。。。

1.2如何去除前台服务的通知栏提醒

方案也是google找的,这里就复述一下,思路就是利用2个同进程的service,利用相同的notificationID,2个service分别startForeground,然后只在1个service里stopForeground,这样即可去掉通知栏的显示。
代码实现:
在你想保活的service的onCreate()方法中,绑定一个用来消除通知的服务:

if (mConnection == null) {
       mConnection = new InnerServiceConnection();
}
this.bindService(new Intent(this, InnerService.class), mConnection, Service.BIND_AUTO_CREATE);

InnerService中的代码:

public class InnerService extends Service {
    @Nullable
    @Override
    public IBinder onBind(Intent intent) {
        return new LocalBinder();
    }

    public class LocalBinder extends Binder {
        public InnerService getService() {
            return InnerService.this;
        }
    }

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        return super.onStartCommand(intent, flags, startId);
    }
}

InnerServiceConnection的实现:

private class InnerServiceConnection implements ServiceConnection {
        @Override
        public void onServiceDisconnected(ComponentName name) {
            Log.d(TAG, "MyService: onServiceDisconnected");
        }

        @Override
        public void onServiceConnected(ComponentName name, IBinder binder) {
            Log.d(TAG, "MyService: onServiceConnected");
            // 的,会在通知栏显示service正在运行,这里不要让用户感知,所以这里的实现方式是利用2个同进程的service,利用相同的notificationID,
            // 2个service分别startForeground,然后只在1个service里stopForeground,这样即可去掉通知栏的显示
            Service innerService = ((InnerService.LocalBinder) binder)
                    .getService();
            MainService.this.startForeground(1, getNotification());
            innerService.startForeground(1, getNotification());
            innerService.stopForeground(true);
            MainService.this.unbindService(mConnection);
            mConnection = null;
        }
    }

1.3设置前台服务总结

设置了前台服务后,服务一般就不会被系统自动清除了,但在miui这类专治流氓软件的系统中,用户手动清除后台,你的进程仍然会被杀掉(android原生系统中,亲测不会被杀掉)。那该怎么办呢?一般的方案是用一些手段重启服务。接下来介绍JobScheduler

二、JobScheduler

JobScheduler是android 5.0提供的一个API,可以指定一段时间循环执行特定的任务,这些任务都会被系统统一调度执行。因为以前大家的应用都是监听各种广播自启动,google终于忍不了了。

2.1JobScheduler的使用

先上调用代码:
        //获取JobScheduler 他是一种系统服务
        JobScheduler jobScheduler = (JobScheduler) getSystemService(Context.JOB_SCHEDULER_SERVICE);
        jobScheduler.cancelAll();
        JobInfo.Builder builder = new JobInfo.Builder(1024, new ComponentName(getPackageName(), JobProtectService.class.getName()));

        if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
            //android N之后时间必须在15分钟以上
//            builder.setMinimumLatency(10 * 1000);
            builder.setPeriodic(15 * 60 * 1000);
        }else{
            builder.setPeriodic(60 * 1000);
        }
        builder.setPersisted(true);
        builder.setRequiredNetworkType(JobInfo.NETWORK_TYPE_ANY);
        int schedule = jobScheduler.schedule(builder.build());
        if (schedule <= 0) {
            Log.w(TAG, "schedule error!");
        }

这里JobInfo中包含了要执行的信息,JobInfo.Builder是他的构造器,其中:

JobInfo.Builder builder = new JobInfo.Builder(1024, new ComponentName(getPackageName(), JobProtectService.class.getName()));

是他的构造方法,指定了要跳转的JobService的信息

builder.setPeriodic(long intervalMillis)

表示间隔一定时间执行该任务,在version>=android N的系统版本中,这个值只能是15分钟以上

builder.setMinimumLatency(long minLatencyMillis);

表示延迟一定时间执行任务,改任务只会调用一次,这个值在android N中没有限制,所以如果你想突破setPeriodic中15分钟的限制,你可以使用setMinimumLatency方法,并在执行任务结束的时候再调用这个方法,等会介绍一下。

builder.setPersisted(true);

是否开机启动?这个方法需要权限

<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />

在国产rom中应用没开自启动你就别想了

 builder.setRequiredNetworkType(JobInfo.NETWORK_TYPE_ANY);

表示网络状态的限制

//不管是否有网络这个任务都会被执行
JobInfo.NETWORK_TYPE_NONE
//任意一种网络任务可以执行
JobInfo.NETWORK_TYPE_ANY
//它表示设备在WIFI连接时任务才会被执行
JobInfo.NETWORK_TYPE_UNMETERED
int schedule = jobScheduler.schedule(builder.build());

表示执行该任务,返回值>0表示执行成功

JobService代码:
public class JobProtectService extends JobService {
    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        return super.onStartCommand(intent,flags,startId);
    }

    @Override
    public boolean onStartJob(JobParameters params) {
        //TODO 写上你的任务逻辑代码
        jobFinished(params, false);
        return false;
    }

    @Override
    public boolean onStopJob(JobParameters params) {
        return false;
    }
}

2.2JobScheduler总结

JobScheduler用来检测你自己的服务是否被杀掉,如果被杀掉了,你重启自己的服务,经过测试,在miui等国产rom中也能够重启服务,前提是你的应用有自启动权限!

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,053评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,527评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,779评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,685评论 1 276
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,699评论 5 366
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,609评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,989评论 3 396
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,654评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,890评论 1 298
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,634评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,716评论 1 330
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,394评论 4 319
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,976评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,950评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,191评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 44,849评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,458评论 2 342

推荐阅读更多精彩内容

  • Android 自定义View的各种姿势1 Activity的显示之ViewRootImpl详解 Activity...
    passiontim阅读 171,418评论 25 707
  • 【Android Service】 Service 简介(★★★) 很多情况下,一些与用户很少需要产生交互的应用程...
    Rtia阅读 3,137评论 1 21
  • 如何能让我们的应用能够在系统后台持续地运行是一个自Android从娘胎里出来时就议论不停的话题,而且这似乎成了一个...
    骏骏的简书阅读 1,102评论 1 19
  • 雨下 徘徊的影子 匆忙的脚步声 雨嘀嗒嗒的歌声 伞下 两人的影子 相互依偎 同起同落 雨夹脚步声 清脆悦耳 檐下 ...
    零摄氏度心情阅读 199评论 0 1
  • 今天上午,我们一家三口去小北湖玩儿了,很开心。 前几天,孩子嚷嚷着要去看昆虫,我不知所云。儿子从书...
    桥上风景阅读 537评论 1 1