您的位置:

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代码,达到保证进程一直运行的效果。

Android Service保活探索

2023-05-20
印象笔记记录java学习(Java成长笔记)

2022-11-12
Mac笔记:在日常生活中高效实用的笔记工具

2023-05-18
python笔记第六天,python第六周笔记

2022-11-21
java方法整理笔记(java总结)

2022-11-08
java笔记,大学java笔记

2022-11-28
私有云笔记:无界写作的安全保障

2023-05-17
python基础学习整理笔记,Python课堂笔记

2022-11-21
java笔记,尚硅谷java笔记

2022-12-01
java学习笔记(java初学笔记)

2022-11-14
探索Android应用构建的奥秘

一、反编译Android应用 想要了解一个App的构建原理,我们可以使用反编译的方式获得源码,并深入研究其代码逻辑。反编译的过程需要使用到工具,具体步骤如下: 1、下载并安装Android Studi

2023-12-08
数据库的笔记mysql,数据库管理系统笔记

2022-11-24
我的ipynb笔记本

2023-05-10
最新python学习笔记3,python基础笔记

2022-11-17
Cherrytree笔记应用

2023-05-21
发篇java复习笔记(java课程笔记)

2022-11-09
Android四大组件:Activity、Service、B

一、Activity作用 Activity是Android应用程序界面的载体,负责显示和响应用户的操作,通常可以看作是一种界面、视图或者屏幕。在整个Android应用程序的生命周期内,Activity

2023-12-08
Android四大组件:Activity、Service、B

一、Activity作用 Activity是Android应用程序界面的载体,负责显示和响应用户的操作,通常可以看作是一种界面、视图或者屏幕。在整个Android应用程序的生命周期内,Activity

2023-12-08
python随笔之(Python笔记)

2022-11-09
python学习之笔记(python的笔记)

2022-11-10