Android服务保活-JobScheduler拉活
方案设计
Android5.0 以后系统对 Native 进程等加强了管理,Native 拉活方式失效。系统在 Android5.0 以上版本提供了 JobScheduler 接口,系统会定时调用该进程以使应用进行一些逻辑操作。
方案适用范围
该方案主要适用于 Android5.0 以上版本手机。
该方案在 Android5.0 以上版本中不受 forcestop 影响,被强制停止的应用依然可以被拉活,在 Android5.0 以上版本拉活效果非常好。
仅在小米手机可能会出现有时无法拉活的问题。
方案实现
JobSchedulerService
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 | package com.aoaoyi.service; import android.annotation.TargetApi; import android.app.job.JobParameters; import android.app.job.JobService; import android.content.Intent; import android.os.Build; /** * Created by xy on 2016/12/2. */ @TargetApi(Build.VERSION_CODES.LOLLIPOP) public class JobSchedulerService extends JobService{ @Override public boolean onStartJob(JobParameters params) { startMainService(); jobFinished(params, false); return true; } @Override public boolean onStopJob(JobParameters params) { startMainService(); return false; } @Override public void onTaskRemoved(Intent rootIntent) { startMainService(); } public void startMainService(){ startService(MainService.getIntentAlarm(this)); } } |
在AndroidManifest.xml中注册
1 2 3 4 5 6 | <service android:name="com.aoaoyi.service.JobSchedulerService" android:permission="android.permission.BIND_JOB_SERVICE" android:enabled="true" android:exported="true" android:process=":push"/> |
在AndroidManifest.xml中加入权限
1 | <uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" /> |
MainService
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 | package com.aoaoyi.service; import android.app.AlarmManager; import android.app.PendingIntent; import android.app.Service; import android.app.job.JobInfo; import android.app.job.JobScheduler; import android.content.ComponentName; import android.content.Context; import android.content.Intent; import android.os.Build; import android.os.IBinder; public class MainService extends Service { /** * 每10分钟检查一次链接状态,确保service不被杀掉 */ private static final int KEEP_ALIVE_INTERVAL = BuildConfig.DEBUG ? 1 * 60 * 1000 : 10 * 60 * 1000; /** * ACTION Start */ private static final String ACTION_START = "MainService.Action.Start"; /** * ACTION Alarm */ private static final String ACTION_ALARM = "MainService.Action.Alarm"; /** * ACTION end start */ private static final String ACTION_END_START = "MainService.Action.EndStart"; private boolean mIsAddAliveAlarm = false; public MainService() { } @Override public IBinder onBind(Intent intent) { return null; } @Override public void onCreate() { if (!mIsAddAliveAlarm){ addAliveAlarm(); mIsAddAliveAlarm = true; } super.onCreate(); } @Override public int onStartCommand(Intent pIntent, int pFlags, int pStartId) { if (null != pIntent){ switch (pIntent.getAction()){ case ACTION_START: break; case ACTION_ALARM: break; case ACTION_END_START: break; } } if (!mIsAddAliveAlarm){ addAliveAlarm(); mIsAddAliveAlarm = true; } return START_STICKY; } @Override public void onTaskRemoved(Intent pIntent) { onEnd(); } @Override public void onDestroy() { onEnd(); super.onDestroy(); } private void onEnd() { startService(getIntentEndStart(getApplicationContext())); } /** * 添加重复唤醒闹钟,用于不停唤起服务 */ private void addAliveAlarm() { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { JobInfo.Builder _Builder = new JobInfo.Builder(0, new ComponentName(getApplication(), JobSchedulerService.class)); _Builder.setPeriodic(KEEP_ALIVE_INTERVAL); _Builder.setPersisted(true); JobScheduler _JobScheduler = (JobScheduler) getSystemService(JOB_SCHEDULER_SERVICE); _JobScheduler.schedule(_Builder.build()); }else { PendingIntent _PendingIntent = PendingIntent.getService(this, 0, getIntentAlarm(this), PendingIntent.FLAG_UPDATE_CURRENT); AlarmManager _AlarmManager = (AlarmManager) getSystemService(ALARM_SERVICE); _AlarmManager.cancel(_PendingIntent); _AlarmManager.setRepeating(AlarmManager.RTC_WAKEUP, System.currentTimeMillis() + KEEP_ALIVE_INTERVAL, KEEP_ALIVE_INTERVAL, _PendingIntent); } } /** * Start * * @param pContext */ public static Intent getIntentStart(Context pContext) { return getActionIntent(pContext, ACTION_START); } /** * Alarm * * @param pContext */ public static Intent getIntentAlarm(Context pContext) { return getActionIntent(pContext, ACTION_ALARM); } /** * EndStart * * @param pContext */ public static Intent getIntentEndStart(Context pContext) { return getActionIntent(pContext, ACTION_END_START); } /** * Service Intent * * @param pContext * @param pAction * @return */ private static Intent getActionIntent(Context pContext, String pAction) { Intent _Intent = new Intent(pContext, MainService.class); _Intent.setAction(pAction); return _Intent; } } |
最后一步,在主Activity启动一次MainService
1 | startService(MainService.getIntentStart(this)); |
效果试试哦^_^
Jady
Greetings from Ohio! I’m bored at work so I decided to check out your website on my iphone during lunch break. I enjoy the knowledge you present here and can#;8217&t wait to take a look when I get home. I’m amazed at how fast your blog loaded on my cell phone .. I’m not even using WIFI, just 3G .. Anyhow, great blog!
Kailee
Oi Vany tudo bem?Menina amei as bijus!! Parabéns por ter sido sorteada!!É muito bom ganhar!!Ah!! Parabéns pelo niver de casamento!!Não deixem de coBjeorar!!mmieos
Erin Gama
You are the master