一、前言
隨着Android應用市場的飛速發展,如何保障應用的用戶體驗一直是開發者熱議的話題。然而長期運行後台服務卻面臨著系統殺進程和省電等問題。如何保證服務長時間的運行,無疑是保障應用運行穩定性的關鍵。本文將從多個方面進行探索android service保活的方法。
二、Foreground Service保活
Foreground Service被定義為一種前台服務,其在拉通知欄通知的同時具備了持續性和穩定性的特點。使用Foreground Service保活的方式需要調用startForeground方法,將服務設置為前台運行狀態。
public class MyService extends Service { private static final int NOTIFICATION_ID = 1; @Override public void onCreate() { super.onCreate(); Notification notification = new Notification.Builder(this, CHANNEL_ID) .setContentTitle(getText(R.string.notification_title)) .setContentText(getText(R.string.notification_message)) .setSmallIcon(R.drawable.icon) .build(); startForeground(NOTIFICATION_ID, notification); } @Override public void onDestroy() { super.onDestroy(); stopForeground(true); } }
保活效果:前台服務優先級較高,可以在後台保持長時間運行。
三、相互喚醒保活
相互喚醒保活是一種互相喚醒的方式,通過廣播、定時器等手段來實現服務的重啟,從而達到保持服務一直運行的效果。
1. 定時器喚醒
利用定時器喚醒服務的方式比較簡單,可以通過創建一個定時器,每隔一段時間就發送一個廣播,喚醒服務。在服務中重置定時器,達到前後互相喚醒的效果。
public class MyService extends Service { private static final String ACTION_ALARM = "com.example.androidservice.KEEP_ALIVE_ALARM"; private static final int INTERVAL = 5 * 60 * 1000; private PendingIntent mPendingIntent; private BroadcastReceiver mReceiver = new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { if (intent != null && ACTION_ALARM.equals(intent.getAction())) { // do something to keep the service alive // ... // reset the alarm AlarmManager alarmManager = (AlarmManager) getSystemService(Context.ALARM_SERVICE); alarmManager.setExact( AlarmManager.ELAPSED_REALTIME_WAKEUP, SystemClock.elapsedRealtime() + INTERVAL, mPendingIntent); return; } } }; @Override public void onCreate() { super.onCreate(); Intent intent = new Intent(ACTION_ALARM); mPendingIntent = PendingIntent.getBroadcast( this, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT); AlarmManager alarmManager = (AlarmManager) getSystemService(Context.ALARM_SERVICE); alarmManager.setExact( AlarmManager.ELAPSED_REALTIME_WAKEUP, SystemClock.elapsedRealtime() + INTERVAL, mPendingIntent); registerReceiver(mReceiver, new IntentFilter(ACTION_ALARM)); } @Override public void onDestroy() { super.onDestroy(); unregisterReceiver(mReceiver); AlarmManager alarmManager = (AlarmManager) getSystemService(Context.ALARM_SERVICE); alarmManager.cancel(mPendingIntent); } }
保活效果:通過定時器喚醒服務,讓服務可以在一定時間內保持運行。
2. 監聽系統廣播喚醒
監聽系統廣播,利用系統事件喚醒服務也是一種不錯的方法。如果開啟了網絡、屏幕、電源等系統事件監聽,當這些事件發生時可以通過回調函數重新啟動服務。
public class MyService extends Service { private BroadcastReceiver mReceiver = new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { if (Intent.ACTION_SCREEN_ON.equals(intent.getAction())) { // do something to keep the service alive // ... return; } if (ConnectivityManager.CONNECTIVITY_ACTION.equals(intent.getAction())) { // do something to keep the service alive // ... return; } if (Intent.ACTION_POWER_CONNECTED.equals(intent.getAction())) { // do something to keep the service alive // ... return; } if (Intent.ACTION_POWER_DISCONNECTED.equals(intent.getAction())) { // do something to keep the service alive // ... return; } } }; @Override public void onCreate() { super.onCreate(); IntentFilter intentFilter = new IntentFilter(); intentFilter.addAction(Intent.ACTION_SCREEN_ON); intentFilter.addAction(Intent.ACTION_SCREEN_OFF); intentFilter.addAction(Intent.ACTION_USER_PRESENT); intentFilter.addAction(ConnectivityManager.CONNECTIVITY_ACTION); intentFilter.addAction(Intent.ACTION_POWER_CONNECTED); intentFilter.addAction(Intent.ACTION_POWER_DISCONNECTED); registerReceiver(mReceiver, intentFilter); } @Override public void onDestroy() { super.onDestroy(); unregisterReceiver(mReceiver); } }
保活效果:通過監聽系統廣播,喚醒服務,讓服務可以在特定的系統事件觸發時保持運行。
四、雙進程守護保活
雙進程守護保活是一種通過創建另一個進程來保障主進程和服務運行的方法。當主進程或服務被殺死時,另一個進程依舊可以運行,並在適當的時候將主進程和服務重啟。
public class RemoteService extends Service { @Nullable @Override public IBinder onBind(Intent intent) { return null; } @Override public int onStartCommand(Intent intent, int flags, int startId) { startForeground(1, new Notification()); stopForeground(true); Intent intent1 = new Intent(this, LocalService.class); startService(intent1); return super.onStartCommand(intent, flags, startId); } } public class LocalService extends Service { private static final String TAG = "LocalService"; private MyBinder mBinder = new MyBinder(); @Nullable @Override public IBinder onBind(Intent intent) { return mBinder; } @Override public int onStartCommand(Intent intent, int flags, int startId) { startForeground(2, new Notification()); stopForeground(true); startRemoteService(); return super.onStartCommand(intent, flags, startId); } private void startRemoteService() { Intent intent = new Intent(this, RemoteService.class); startService(intent); } @Override public void onTaskRemoved(Intent rootIntent) { // restart the service when it is killed startRemoteService(); super.onTaskRemoved(rootIntent); } public static class MyBinder extends Binder { public LocalService getService() { return LocalService.this; } public void wakeUp() { Log.i(TAG, "wake up by local binder"); startRemoteService(); } } }
保活效果:啟動另一個進程,使主進程和服務能夠相互喚醒,達到保證服務一直運行的效果。
五、JNI保活
JNI保活是一種通過C/C++代碼調用java虛擬機,執行java代碼來保證進程運行。由於C/C++是一種底層語言,較少會被系統殺死,因此可以利用這一點實現保活效果。
jint JNI_OnLoad(JavaVM* vm, void* reserved) { JNIEnv* env; if ((*vm)->GetEnv(vm, (void **)&env, JNI_VERSION_1_6) != JNI_OK) { return JNI_ERR; } jclass clazz = (*env)->FindClass(env, "com.example.androidservice.MyService"); if (clazz == NULL) return JNI_ERR; jmethodID methodID = (*env)->GetMethodID(env, clazz, "onAlive", "()V"); if (methodID == NULL) return JNI_ERR; jobject obj = (*env)->AllocObject(env, clazz); if (obj == NULL) return JNI_ERR; (*env)->CallVoidMethod(env, obj, methodID); return JNI_VERSION_1_6; }
保活效果:通過JNI的方式調用java虛擬機,執行java代碼,達到保證進程一直運行的效果。
原創文章,作者:GVGLK,如若轉載,請註明出處:https://www.506064.com/zh-hant/n/324753.html