Android Service保活探索

一、前言

隨著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-tw/n/324753.html

(0)
打賞 微信掃一掃 微信掃一掃 支付寶掃一掃 支付寶掃一掃
GVGLK的頭像GVGLK
上一篇 2025-01-13 13:23
下一篇 2025-01-13 13:23

相關推薦

  • Android ViewPager和ScrollView滑動衝突問題

    Android開發中,ViewPager和ScrollView是兩個常用的控制項。但是當它們同時使用時,可能會發生滑動衝突的問題。本文將從多個方面介紹解決Android ViewPa…

    編程 2025-04-28
  • Android如何點擊其他區域收起軟鍵盤

    在Android應用中,當輸入框獲取焦點彈出軟鍵盤後,我們希望能夠點擊其他區域使軟鍵盤消失,以提升用戶體驗。本篇文章將說明如何實現這一功能。 一、獲取焦點並顯示軟鍵盤 在Andro…

    編程 2025-04-28
  • Android Studio HUD 實現指南

    本文將會以實例來詳細闡述如何在 Android Studio 中使用 HUD 功能實現菊花等待指示器的效果。 一、引入依賴庫 首先,我們需要在 build.gradle 文件中引入…

    編程 2025-04-27
  • Android和Vue3混合開發方案

    本文將介紹如何將Android和Vue3結合起來進行混合開發,以及其中的優勢和注意事項。 一、環境搭建 在進行混合開發之前,需要搭建好相應的開發環境。首先需要安裝 Android …

    編程 2025-04-27
  • Android Java Utils 可以如何提高你的開發效率

    Android Java Utils 是一款提供了一系列方便實用的工具類的 Java 庫,可以幫助開發者更加高效地進行 Android 開發,提高開發效率。本文將從以下幾個方面對 …

    編程 2025-04-27
  • Android JUnit測試完成程序自動退出決方法

    對於一些Android JUnit測試的開發人員來說,程序自動退出是一個經常面臨的困擾。下面從多個方面給出解決方法。 一、檢查測試代碼 首先,我們應該仔細檢查我們的測試代碼,確保它…

    編程 2025-04-25
  • Android Activity啟動流程

    一、Activity概述 Android應用程序是由許多Activity組成的。一個Activity代表一個屏幕上的窗口。用戶與應用程序交互時,Activity會接收用戶的輸入並處…

    編程 2025-04-25
  • Android單元測試詳解

    一、單元測試概述 單元測試是指對軟體中的最小可測試單元進行檢查和驗證。在Android開發中,單元測試是非常重要的一環,可以保證代碼的質量、穩定性以及可維護性。 在Android開…

    編程 2025-04-25
  • Android WebView載入本地HTML

    一、介紹 Android WebView是一個內置的瀏覽器,它允許開發人員在應用中嵌入網頁。使用WebView可以輕鬆地在應用程序中顯示本地或遠程的HTML內容。本篇文章將重點講述…

    編程 2025-04-24
  • Android Wakelock詳解

    一、什麼是Android Wakelock? 在Android應用開發中,Wakelock被廣泛應用於保持屏幕或CPU處於喚醒狀態,以便應用程序可以繼續執行後台任務,直到任務完成。…

    編程 2025-04-24

發表回復

登錄後才能評論