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

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
GVGLKGVGLK
上一篇 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

发表回复

登录后才能评论