我的编程空间,编程开发者的网络收藏夹
学习永远不晚

Android 应用进程保活方案实战

短信预约 -IT技能 免费直播动态提醒
省份

北京

  • 北京
  • 上海
  • 天津
  • 重庆
  • 河北
  • 山东
  • 辽宁
  • 黑龙江
  • 吉林
  • 甘肃
  • 青海
  • 河南
  • 江苏
  • 湖北
  • 湖南
  • 江西
  • 浙江
  • 广东
  • 云南
  • 福建
  • 海南
  • 山西
  • 四川
  • 陕西
  • 贵州
  • 安徽
  • 广西
  • 内蒙
  • 西藏
  • 新疆
  • 宁夏
  • 兵团
手机号立即预约

请填写图片验证码后获取短信验证码

看不清楚,换张图片

免费获取短信验证码

Android 应用进程保活方案实战

  1. 前台服务:将应用运行的服务设置为前台服务,让用户知道应用正在后台运行,系统会给予一定的优先级,减少被系统杀掉的概率。但是需要注意,使用前台服务保活不能大量占用用户的通知栏,否则用户可能会感到烦躁而卸载应用。

  2. JobScheduler:Android 5.0 开始引入的一种调度任务的方式,可以灵活地安排应用的任务执行时间,提高任务执行的效率和稳定性。

  3. AlarmManager:可以在后台定时启动应用的服务或广播,保证应用在后台不会被系统杀掉。但同时也需要注意避免过度使用 AlarmManager,减少应用在后台的功耗和资源占用。

  4. 双进程守护:通过开启两个进程来使应用在系统中运行两条不同的进程,相互守护,保证一旦有一条进程被系统销毁,则另一条进程会重新唤醒应用。但是双进程守护会造成应用的内存占用较高,并且一些手机厂商可能会禁用该功能。

  5. 保活框架:市面上有一些第三方保活框架,可以通过一些技术手段来维持应用的活跃性,如 CPU 占用、唤醒锁等。但需要注意这些框架可能会带来额外的资源消耗和电量消耗。

以上是 Android 应用进程保活的主要方案。当然,不同应用的保活策略可能因应用特性和开发需要而有所不同。

一、前台服务

在 AndroidManifest.xml 文件中添加访问网络状态和前台服务的权限:

复制

创建一个后台服务,让 Service 继承 Service 类,实现其 onBind() 方法和 onStartCommand() 方法,保持服务在前台运行,并在服务被销毁时再次启动:

复制public class MyService extends Service {    @Override    public IBinder onBind(Intent intent) {        return null;    }    @Override    public int onStartCommand(Intent intent, int flags, int startId) {        Notification notification = new NotificationCompat.Builder(this, "CHANNEL_ID")                .setContentTitle("App is running in background")                .setContentText("Tap to open")                .setSmallIcon(R.mipmap.ic_launcher)                .setContentIntent(PendingIntent.getActivity(this, 0, intent, 0))                .build();        startForeground(1, notification);        return START_STICKY;    }    @Override    public void onDestroy() {        super.onDestroy();        Toast.makeText(this, "Service destroyed", Toast.LENGTH_SHORT).show();        Intent intent = new Intent(getApplicationContext(), MyService.class);        startService(intent);    }}

在 MainActivity 类中启动服务:

复制public class MainActivity extends AppCompatActivity {    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_main);        Intent intent = new Intent(getApplicationContext(), MyService.class);        startService(intent);    }}

在前台服务中的通知栏中使用了一个 PendingIntent 来启动 MainActivity,使得用户可以在单击通知栏时打开应用。在服务被销毁时,通过启动另一个 Intent 对象的方式重新启动服务,从而实现了保活的功能。需要注意的是,在程序退出后服务仍会继续运行,需要通过调用 stopService() 方法或者调用 stopForeground() 方法来停止服务,不然可能会一直在后台运行造成系统负担增大。

二、双进程守护

  • 创建一个守护服务类 DaemonService:

    复制public class DaemonService extends Service {    private final static String TAG = DaemonService.class.getSimpleName();    @Override    public void onCreate() {        super.onCreate();        Log.i(TAG, "onCreate: DaemonService created.");    }    @Override    public void onTaskRemoved(Intent rootIntent) {        super.onTaskRemoved(rootIntent);        Log.i(TAG, "onTaskRemoved: App is killed.");        // 在应用被杀死前,启动 ProtectService 来尝试拉活        Intent intent = new Intent(getApplicationContext(), ProtectService.class);        startService(intent);    }    @Nullable    @Override    public IBinder onBind(Intent intent) {        return null;    }}

    创建一个拉活服务类 ProtectService:

    复制public class ProtectService extends Service {    private final static String TAG = ProtectService.class.getSimpleName();    private final static int NOTIFY_ID = 1;    private final static String CHANNEL_NAME = "keep_alive";    private final static String CHANNEL_DESCRIPTION = "keep_alive";    @Override    public void onCreate() {        super.onCreate();        Log.i(TAG, "onCreate: ProtectService created.");        startForeground(NOTIFY_ID, getNotification());        startService(new Intent(getApplicationContext(), DaemonService.class));    }    private Notification getNotification() {        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {            NotificationManager notificationManager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);            NotificationChannel channel = new NotificationChannel(CHANNEL_NAME, CHANNEL_DESCRIPTION, NotificationManager.IMPORTANCE_HIGH);            notificationManager.createNotificationChannel(channel);            Notification.Builder builder = new Notification.Builder(this, CHANNEL_NAME);            builder.setSmallIcon(R.mipmap.ic_launcher);            builder.setContentTitle(getString(R.string.app_name));            builder.setContentText(getString(R.string.text_keep_alive));            return builder.build();        } else {            NotificationCompat.Builder builder = new NotificationCompat.Builder(this);            builder.setSmallIcon(R.mipmap.ic_launcher);            builder.setContentTitle(getString(R.string.app_name));            builder.setContentText(getString(R.string.text_keep_alive));            return builder.build();        }    }    @Nullable    @Override    public IBinder onBind(Intent intent) {        return null;    }}

    在 MainActivity 中启动守护服务和拉活服务:

    复制public class MainActivity extends AppCompatActivity {    private final static String TAG = MainActivity.class.getSimpleName();    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_main);        Log.i(TAG, "onCreate: MainActivity created.");        startService(new Intent(getApplicationContext(), DaemonService.class));        startService(new Intent(getApplicationContext(), ProtectService.class));    }}

    若应用被系统杀死,实时捕捉到,并且尝试调用 ProtectService 来唤醒应用,让它重新处于前台运行的状态,保证在后台时极少被杀死的情况。同时,由于开启了前台服务,又频繁切换前台后台可能会导致用户的通知栏被大量的“常驻通知”,需要注意这一点。

  • 对上述功能增加手机开机启动功能
  • 好的,以下是在上述方案基础上增加手机开机启动功能的完整代码示例:

    创建一个 BroadcastReceiver 类,用于监听手机开机广播,创建一个 Intent 对象用于启动守护服务和拉活服务:

    复制public class BootReceiver extends BroadcastReceiver {    @Override    public void onReceive(Context context, Intent intent) {        if (intent.getAction().equals(Intent.ACTION_BOOT_COMPLETED)) {            Intent service = new Intent(context, DaemonService.class);            context.startService(service);            Intent protect = new Intent(context, ProtectService.class);            context.startService(protect);        }    }}

    在 AndroidManifest.xml 文件中注册权限和 BroadcastReceiver:

    复制                

    在 MainActivity 类中检查守护服务和拉活服务是否在运行,如果没有则手动启动:

    复制public class MainActivity extends AppCompatActivity {    private final static String TAG = MainActivity.class.getSimpleName();    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_main);        Log.i(TAG, "onCreate: MainActivity created.");        if (!isServiceRunning(this, DaemonService.class.getName())) {            startService(new Intent(getApplicationContext(), DaemonService.class));        }        if (!isServiceRunning(this, ProtectService.class.getName())) {            startService(new Intent(getApplicationContext(), ProtectService.class));        }    }    private boolean isServiceRunning(Context context, String serviceName) {        ActivityManager am = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);        List list = am.getRunningServices(Integer.MAX_VALUE);        for (ActivityManager.RunningServiceInfo info : list) {            if (serviceName.equals(info.service.getClassName())) {                return true;            }        }        return false;    }}

    以上就是增加手机开机启动功能的完整代码示例,可以在设备重启后自动启动服务,并保持应用在后台的运行状态。

三、JobScheduler

创建一个 JobService 类,并实现其 onStartJob() 和 onStopJob() 方法:

复制public class MyJobService extends JobService {    @Override    public boolean onStartJob(JobParameters params) {        Log.i(TAG, "onStartJob");        // 在此添加需要执行的任务        // ...        jobFinished(params, false);        return true;    }    @Override    public boolean onStopJob(JobParameters params) {        return true;    }}

在 AndroidManifest.xml 文件中注册 JobService 和必要的权限:

复制    ...        ...

在应用启动时调起对应的 JobScheduler,实现保活:

复制public class MainActivity extends AppCompatActivity {    private static final int JOB_ID = 100;    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_main);        JobScheduler scheduler = (JobScheduler) getSystemService(JOB_SCHEDULER_SERVICE);        JobInfo.Builder builder = new JobInfo.Builder(JOB_ID, new ComponentName(getPackageName(), MyJobService.class.getName()));        builder.setPeriodic(10000);        builder.setRequiredNetworkType(JobInfo.NETWORK_TYPE_ANY);        if (scheduler.schedule(builder.build()) <= 0) {            Log.e(TAG, "onCreate: JobScheduler failed.");        }    }}

这里我们设置保活时间为10秒,设置网络请求不区分Wifi或移动网络。在应用被回收后,JobScheduler 会重新启动应用并调起 MyJobService 类的 onStartJob() 方法,在该方法中添加需要执行的任务,完成应用的保活。

需要注意的是,JobScheduler 并不是100%保证能够精确按照设定的时间执行任务,系统可能会因为一些原因推迟任务的执行时间,而且不同版本的Android可能会有不同支持程度。

如果任务要求立即执行,可以使用 startService() 方法或者 ForegroundService 实现,同时结合 JobScheduler 使用以保证在后台时不会被杀掉。

四、AlarmManager

创建一个常驻进程 Service,实现其 onBind()、onStartCommand() 和 onDestroy() 方法:

复制public class KeepAliveService extends Service {    private static final int NOTIFY_ID = 1001;    private static final String CHANNEL_ID = "MY_CHANNEL_ID";    private static final String CHANNEL_NAME = "MY_CHANNEL_NAME";    private PendingIntent pendingIntent;    @Override    public IBinder onBind(Intent intent) {        return null;    }    @Override    public int onStartCommand(Intent intent, int flags, int startId) {        Log.i(TAG, "onStartCommand");        Intent notificationIntent = new Intent(this, MainActivity.class);        pendingIntent = PendingIntent.getActivity(this, 0, notificationIntent, 0);        Notification notification = null;        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {            NotificationChannel channel = new NotificationChannel(CHANNEL_ID, CHANNEL_NAME, NotificationManager.IMPORTANCE_LOW);            NotificationManager manager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);            manager.createNotificationChannel(channel);            notification = new Notification.Builder(this, CHANNEL_ID)                    .setContentTitle(getString(R.string.app_name))                    .setContentText(getString(R.string.text_keep_alive))                    .setSmallIcon(R.mipmap.ic_launcher)                    .setContentIntent(pendingIntent)                    .setAutoCancel(false)                    .setCategory(NotificationCompat.CATEGORY_SERVICE)                    .build();        } else {            notification = new NotificationCompat.Builder(this)                    .setContentTitle(getString(R.string.app_name))                    .setContentText(getString(R.string.text_keep_alive))                    .setSmallIcon(R.mipmap.ic_launcher)                    .setContentIntent(pendingIntent)                    .setAutoCancel(false)                    .setPriority(NotificationCompat.PRIORITY_MIN)                    .setCategory(NotificationCompat.CATEGORY_SERVICE)                    .build();        }        startForeground(NOTIFY_ID, notification);        // 定时发送广播        AlarmManager am = (AlarmManager) getSystemService(Context.ALARM_SERVICE);        Intent alarmIntent = new Intent(getApplicationContext(), KeepAliveReceiver.class);        pendingIntent = PendingIntent.getBroadcast(getApplicationContext(), 0, alarmIntent, 0);        am.setExactAndAllowWhileIdle(AlarmManager.RTC_WAKEUP, System.currentTimeMillis() + 30000, pendingIntent);        return super.onStartCommand(intent, flags, startId);    }    @Override    public void onDestroy() {        super.onDestroy();        Log.i(TAG, "onDestroy");        AlarmManager am = (AlarmManager) getSystemService(Context.ALARM_SERVICE);        am.cancel(pendingIntent);        stopForeground(true);    }}

创建一个广播监听器 KeepAliveReceiver,用来接收定时广播并重新启动常驻服务:

复制public class KeepAliveReceiver extends BroadcastReceiver {    @Override    public void onReceive(Context context, Intent intent) {        Intent service = new Intent(context, KeepAliveService.class);        context.startService(service);    }}

在 AndroidManifest.xml 中注册 BroadcastReceiver 和相应的权限:

复制                        

可以看到这里注册了一个 BroadcastReceiver 来监听 app 的定时任务,同时也添加了 BOOTCOMPLETED 权限和注册了 BOOTCOMPLETED 广播监听器,来接收设备启动完成的广播。

在 MainActivity 的 onCreate() 方法中启动常驻服务:

复制public class MainActivity extends AppCompatActivity {    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_main);        Intent service = new Intent(getApplicationContext(), KeepAliveService.class);        startService(service);    }}

最后在 MainActivity 的 onCreate() 方法中启动常驻服务即可完成 Android 应用的进程保活功能。

五、保活框架

当应用进入后台或者长时间未操作时,Android 系统的进程管理机制会将其进程杀掉,从而避免因应用长时间占用资源导致系统运行不稳定或者其他应用运行出现问题。但是某些的应用,比如推送、IM 类应用,需要在后台一直保持连接,这就需要让应用进程长期存活。

为了解决这个问题,开源社区中出现了一些保活框架,它们的主要功能是通过不同的方式让应用进程保持存活状态,保证应用可以在后台进行连接等任务。以下是一些知名的保活框架:

  1. Daemon

Daemon 是 Android 平台上一个进程守护框架,其包含 app 守护、进程保活、服务保活等多个子模块。Daemon 针对不同的应用场景提供了不同的保活方法,包括 Service 方式、 Alarm 机制、JobScheduler 等,其能够在不同的 Android 版本中支持不同的保活方式。

GitHub: https://github.com/Leaking/daemon

  1. Xposed

Xposed 是一个用来定制和修改 APK 的工具,它允许用户在不修改 APK 文件的情况下更改应用的行为和外观,也可以用来实现应用保活。Xposed 使用应用内的模块来实现保活功能,但需要 root 权限。

GitHub: https://github.com/rovo89/Xposed

  1. Android-Job

Android-Job 是 Android 系统上作业调度框架,是一个基于 JobScheduler API 的库。Android-Job 允许您创建并执行非常容易使用的作业,此库可以非常方便地创建短暂的异步任务或长时间运行的操作。

GitHub: https://github.com/Evernote/android-job

  1. JobSchedulerCompat

JobSchedulerCompat 利用 JobScheduler API 在 Android 5.0 以下版本中实现了 JobScheduler 的所有功能。JobSchedulerCompat 在实现 JobScheduler 的同时可以支持保活等场景的使用。

GitHub: https://github.com/evant/JobSchedulerCompat

  1. WorkManager

WorkManager 是 Google 推出的一款用于管理后台调度任务的库,可以兼容 Api Level 14+ 的设备。WorkManager 是Android Jetpack 的一部分,结合 WorkManager 可以轻松实现工作调度和长期运行的任务.

GitHub: https://github.com/android/architecture-components-samples/tree/master/WorkManagerSample

以上是一些知名的保活框架,它们都有各自独特的特点和适用场景,可以根据具体的开发需求来选择使用。

六、WorkManager

创建一个 WorkManager 的 Worker 类:

复制public class KeepAliveWorker extends Worker {    private static final String TAG = "KeepAliveWorker";    public KeepAliveWorker(            @NonNull Context context,            @NonNull WorkerParameters workerParams) {        super(context, workerParams);    }    @NonNull    @Override    public Result doWork() {        Log.i(TAG, "doWork");        // 在此添加需要执行的任务        // ...        return Result.success();    }}

创建一个定时任务,并调度执行:

复制PeriodicWorkRequest keepAliveWork =        new PeriodicWorkRequest.Builder(KeepAliveWorker.class, 15, TimeUnit.MINUTES)                .setConstraints(Constraints.NONE)                .build();WorkManager workManager = WorkManager.getInstance(context);workManager.enqueueUniquePeriodicWork(        "keep_alive_work",        ExistingPeriodicWorkPolicy.KEEP,        keepAliveWork);

此处我们创建了一个周期性执行的任务,每隔 15 分钟执行一次。通过 WorkManager 调度执行该任务,其中的 WorkPolicy 设置为 ExistingPeriodicWorkPolicy.KEEP 表示如果当前已经有相同名字的任务在执行,则保持不变,不会重新启动。

在 AndroidManifest.xml 文件中声明以及申请一些必要的权限:

复制    ...                                        ...

可以看到,我们在 AndroidManifest.xml 中注册了一个 BroadcastReceiver 来接收 BOOT_COMPLETED 广播,这样当设备启动完成后能够自动重启任务。

创建一个 BroadcastReceiver,接收 BOOT_COMPLETED 广播并重新启动任务:

复制public class KeepAliveReceiver extends BroadcastReceiver {    private static final String TAG = "KeepAliveReceiver";    @Override    public void onReceive(Context context, Intent intent) {        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {            context.startForegroundService(new Intent(context, KeepAliveService.class));        } else {            context.startService(new Intent(context, KeepAliveService.class));        }    }}

创建一个常驻服务,确保应用在后台运行的同时能够通过 WorkManager 定时执行任务:

复制public class KeepAliveService extends Service {    private static final int NOTIFY_ID = 1001;    private static final String CHANNEL_ID = "MY_CHANNEL_ID";    private static final String CHANNEL_NAME = "MY_CHANNEL_NAME";    private PendingIntent pendingIntent;    @Override    public IBinder onBind(Intent intent) {        return null;    }    @Override    public int onStartCommand(Intent intent, int flags, int startId) {        Log.i(TAG, "onStartCommand");        Intent notificationIntent = new Intent(this, MainActivity.class);        pendingIntent = PendingIntent.getActivity(this, 0, notificationIntent, 0);        Notification notification = null;        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {            NotificationChannel channel = new NotificationChannel(CHANNEL_ID, CHANNEL_NAME, NotificationManager.IMPORTANCE_LOW);            NotificationManager manager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);            manager.createNotificationChannel(channel);
 notification = new Notification.Builder(this, CHANNEL_ID)                    .setContentTitle(getString(R.string.app_name))                    .setContentText(getString(R.string.text_keep_alive))                    .setSmallIcon(R.mipmap.ic_launcher)                    .setContentIntent(pendingIntent)                    .setAutoCancel(false)                    .setCategory(NotificationCompat.CATEGORY_SERVICE)                    .build();        } else {            notification = new NotificationCompat.Builder(this)                    .setContentTitle(getString(R.string.app_name))                    .setContentText(getString(R.string.text_keep_alive))                    .setSmallIcon(R.mipmap.ic_launcher)                    .setContentIntent(pendingIntent)                    .setAutoCancel(false)                    .setPriority(NotificationCompat.PRIORITY_MIN)                    .setCategory(NotificationCompat.CATEGORY_SERVICE)                    .build();        }        startForeground(NOTIFY_ID, notification);        startWorkManager();        return super.onStartCommand(intent, flags, startId);    }    @Override    public void onDestroy() {        super.onDestroy();        Log.i(TAG, "onDestroy");        stopWorkManager();        stopForeground(true);        Intent intent = new Intent(this, KeepAliveReceiver.class);        intent.setAction("myAction");        PendingIntent pendingIntent = PendingIntent.getBroadcast(this, 0, intent, 0);        AlarmManager am = (AlarmManager) getSystemService(Context.ALARM_SERVICE);        am.setExactAndAllowWhileIdle(AlarmManager.RTC_WAKEUP, System.currentTimeMillis() + 2000, pendingIntent);    }    private void startWorkManager() {        Log.i(TAG, "startWorkManager");        PeriodicWorkRequest keepAliveWork =                new PeriodicWorkRequest.Builder(KeepAliveWorker.class, 15, TimeUnit.MINUTES)                        .setConstraints(Constraints.NONE)                        .build();        WorkManager workManager = WorkManager.getInstance(getApplicationContext());        workManager.enqueueUniquePeriodicWork(                "keep_alive_work",                ExistingPeriodicWorkPolicy.KEEP,                keepAliveWork        );    }    private void stopWorkManager() {        Log.i(TAG, "stopWorkManager");        WorkManager workManager = WorkManager.getInstance(getApplicationContext());        workManager.cancelUniqueWork("keep_alive_work");    }}

我们在 onStartCommand() 方法中启动了一个常驻的前台服务(通过 Notification),同时调用了 startWorkManager() 方法来开启 WorkManager 的定时任务。在 onDestroy() 方法中,我们调用了 stopWorkManager() 来关闭任务,停止 WorkManager 进程运行。

另外值得注意的是,在 onDestroy() 方法中,我们使用 AlarmManager 来启动一个定时广播,其目的是在 WorkManager 定时任务被系统强杀时,能够通过广播重启服务,达到保活效果。

最后在 MainActivity 的 onCreate() 方法中启动该 Service:

复制public class MainActivity extends AppCompatActivity {    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_main);        Intent service = new Intent(getApplicationContext(), KeepAliveService.class);        startService(service);    }}

这样就完成了使用 WorkManager 实现 Android 应用进程保活的示例。

七、

  • Daemon实现应用进程保活的接入方案
  • 好的,以下是使用 Daemon 实现 Android 应用进程保活的示例:

    在 build.gradle 文件中导入依赖:

    复制repositories {    maven { url "https://jitpack.io" }}dependencies {    implementation 'com.github.Leaking:Daemon:2.1.13'}

    创建一个自定义的 Service 继承自 DaemonInnerService。DaemonInnerService 是 Daemon 库中提供的一个基础服务,用于在后台开启常驻进程。

    复制public class MyService extends DaemonInnerService {    private static final String TAG = "MyService";    // ...    @Override    public void onCreate() {        super.onCreate();        Log.i(TAG, "onCreate");    }    @Override    public int onStartCommand(Intent intent, int flags, int startId) {        Log.i(TAG, "onStartCommand");        startWork();        return START_STICKY;    }    @Override    public void onDestroy() {        super.onDestroy();        Log.i(TAG, "onDestroy");        stopWork();    }    // ...}

    在这里我们创建的 MyService 继承了 DaemonInnerService,覆写了 onStartCommand() 和 onDestroy() 方法。需要注意的是,我们在 onStartCommand() 中调用了 startWork() 方法,这个方法用于启动一些需要保活的任务。同时在 onDestroy() 方法中,我们调用了 stopWork() 方法,用于停止保活任务。

    在 AndroidManifest.xml 文件中注册服务:

    复制                        

    在这里我们同时注册了一个广播接收器 MyReceiver,用于接收 BOOTCOMPLETED 和 USERPRESENT 广播,当设备启动完成或解锁时启动服务。

    创建一个保活延迟任务类来执行保活相关操作:

    复制public class MyDelayService extends AbsWorkService {    private static final String TAG = "MyDelayService";    @Override    public Boolean shouldStopService(Intent intent, int flags, int startId) {        Log.i(TAG, "shouldStopService");        return super.shouldStopService(intent, flags, startId);    }    @Override    public void startWork(Intent intent, int flags, int startId) {        Log.i(TAG, "startWork");        new Handler().postDelayed(new Runnable() {            @Override            public void run() {_    Intent service = new Intent(getApplicationContext(), MyService.class);            startService(service);            startDaemonService(MyDelayService.class);        }, 10000);    }    @Override    public void stopWork(Intent intent, int flags, int startId) {        Log.i(TAG, "stopWork");        stopDaemonService(MyDelayService.class);    }    @NonNull    @Override    public Result onRunTask(Intent intent, int flags, int startId) {        Log.i(TAG, "onRunTask");        return Result.SUCCESS;    }}在 MyDelayService 中我们定义了一个 startWork() 方法,在该方法中需要手动启动 MyService,并启动 DaemonInnerService 类型为 MyDelayService 的服务。同时需要注意,需要在 10 秒后执行任务,保证能够在服务启动完成后调用 startWork() 方法。5.创建一个广播接收器 MyReceiver,接收系统广播并重启保活服务:
  • 复制public class MyReceiver extends AbsReceiver {    private static final String TAG = "MyReceiver";    @Override    public void onReceive(Context context, Intent intent) {        super.onReceive(context, intent);        Log.i(TAG, "onReceive");        boolean isScreenOn = isScreenOn(context);        if (isScreenOn) {            Intent service = new Intent(context, MyService.class);            context.startService(service);        }    }}

    在 MyReceiver 中我们根据广播的类型判断设备是否解锁,并根据结果重启服务。注意,这里我们需要通过 isScreenOn() 方法来判断设备是否解锁,该方法需要在 AbsReceiver 中进行实现。

    最后在 MainActivity 中启动保活服务:

    复制public class MainActivity extends AppCompatActivity {    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_main);        Intent service = new Intent(getApplicationContext(), MyService.class);        startService(service);    }}

    以上是使用 Daemon 实现 Android 应用进程保活的示例。通过 Daemon 库,我们可以非常简单地实现应用进程保活功能,支持在不同的场景下保活,并能够通过

来源地址:https://blog.csdn.net/MYBOYER/article/details/129945121

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

Android 应用进程保活方案实战

下载Word文档到电脑,方便收藏和打印~

下载Word文档

猜你喜欢

详解Android进程保活的方法

关于 Android 平台的进程保活这一块,想必是所有 Android 开发者瞩目的内容之一。你到网上搜 Android 进程保活,可以搜出各种各样神乎其技的做法,绝大多数都是极其不靠谱。前段时间,Github还出现了一个很火的“黑科技”进
2022-06-06

Python 多线程与多进程:实战案例剖析,掌握并发编程的应用技巧

Python 多线程、多进程是实现并发编程的两种主要方式,在实践中各有所长。本文将通过两个实战案例,深入剖析多线程、多进程的应用技巧,帮助开发者更好地掌握并发编程。
Python 多线程与多进程:实战案例剖析,掌握并发编程的应用技巧
2024-02-24

Android实战教程第五篇之一键锁屏应用

Device Administration对于这个应用,市场上很多,但是看一下评论就知道效果有多差了,因为99%一键锁屏应用没办法卸载。今天就开发一个小应用,实现轻松点击一键锁屏,同时支持卸载。。。 通查看谷歌原文档,有设备管理器的API,
2022-06-06

Android应用程序保持后台唤醒(使用WakeLock实现)

在使用一些产品列如微信、QQ之类的,如果有新消息来时,手机屏幕即使在锁屏状态下也会亮起并提示声音,这时用户就知道有新消息来临了。但是,一般情况下手机锁屏后,Android系统为了省电以及减少CPU消耗,在一段时间后会使系统进入休眠状态,这时
2022-06-06

Android应用内悬浮窗的实现方案示例

1、悬浮窗的基本介绍悬浮窗,大家应该也不陌生,凌驾于应用之上的一个小弹窗,实现上很简单,就是添加一个系统级别的窗口,Android中通过WindowManagerService( WMS)来管理所有的窗口,对于WMS来说,管你是Activi
2023-05-30

Android Service的跨进程通信实战&amp;Service/AIDL远程调用过程解析(Android Q)

Service的跨进程通信实战设想这么一个场景,我们有2个APP(或者2个进程,均可),其中一个APP需要提供一个Person相关的服务(该服务有一个名为eat的接口),我们叫它PersonServer;另一个APP需要访问PersonSe
2022-06-06

Android 退出应用程序的实现方法

Android 退出应用程序的实现方法 android 退出应用程序会调用android.os.Process.killProcess(android.os.Process.myPid())或是System.exit(0)
2022-06-06

Android实战教程第六篇之一键锁屏应用问题解决

上一篇,初步开发了这个应用,功能都有了(见//www.jb51.net/article/96992.htm 点击打开链接)。 但是遗留了两个问题:1、还是无法卸载;2、必须手动去点击应用程序进入程序,再点击按钮,这显得很麻烦。这一篇就解决上
2022-06-06

Android跨进程通讯(1)Activity访问其他应用程序的Activity实现

首先我们得明白一点,android系统中应用程序之间是不能共享内存的。 但是,在不同应用程序之间进行数据的交互,也就是跨进程通讯,肯定是有实现的方法,今天我就来讲讲Activity与Activity之间是如何做到的。 在同一个应用程序中:只
2022-06-06

Android应用程序四大组件之使用AIDL如何实现跨进程调用Service

一、问题描述Android应用程序的四大组件中Activity、BroadcastReceiver、ContentProvider、Service都可以进行跨进程。在上一篇我们通过ContentProvider实现了不同应用之间的跨进程调用
2022-06-06

Android编程实现应用程序开机自启动的方法

本文实例讲述了Android编程实现应用程序开机自启动的方法。分享给大家供大家参考,具体如下: Android在开机时自动启动一个应用程序 在启动时自动启动一个应用程序: 1、AndroidManifest.xml
2022-06-06

编程热搜

  • Android:VolumeShaper
    VolumeShaper(支持版本改一下,minsdkversion:26,android8.0(api26)进一步学习对声音的编辑,可以让音频的声音有变化的播放 VolumeShaper.Configuration的三个参数 durati
    Android:VolumeShaper
  • Android崩溃异常捕获方法
    开发中最让人头疼的是应用突然爆炸,然后跳回到桌面。而且我们常常不知道这种状况会何时出现,在应用调试阶段还好,还可以通过调试工具的日志查看错误出现在哪里。但平时使用的时候给你闹崩溃,那你就欲哭无泪了。 那么今天主要讲一下如何去捕捉系统出现的U
    Android崩溃异常捕获方法
  • android开发教程之获取power_profile.xml文件的方法(android运行时能耗值)
    系统的设置–>电池–>使用情况中,统计的能耗的使用情况也是以power_profile.xml的value作为基础参数的1、我的手机中power_profile.xml的内容: HTC t328w代码如下:
    android开发教程之获取power_profile.xml文件的方法(android运行时能耗值)
  • Android SQLite数据库基本操作方法
    程序的最主要的功能在于对数据进行操作,通过对数据进行操作来实现某个功能。而数据库就是很重要的一个方面的,Android中内置了小巧轻便,功能却很强的一个数据库–SQLite数据库。那么就来看一下在Android程序中怎么去操作SQLite数
    Android SQLite数据库基本操作方法
  • ubuntu21.04怎么创建桌面快捷图标?ubuntu软件放到桌面的技巧
    工作的时候为了方便直接打开编辑文件,一些常用的软件或者文件我们会放在桌面,但是在ubuntu20.04下直接直接拖拽文件到桌面根本没有效果,在进入桌面后发现软件列表中的软件只能收藏到面板,无法复制到桌面使用,不知道为什么会这样,似乎并不是很
    ubuntu21.04怎么创建桌面快捷图标?ubuntu软件放到桌面的技巧
  • android获取当前手机号示例程序
    代码如下: public String getLocalNumber() { TelephonyManager tManager =
    android获取当前手机号示例程序
  • Android音视频开发(三)TextureView
    简介 TextureView与SurfaceView类似,可用于显示视频或OpenGL场景。 与SurfaceView的区别 SurfaceView不能使用变换和缩放等操作,不能叠加(Overlay)两个SurfaceView。 Textu
    Android音视频开发(三)TextureView
  • android获取屏幕高度和宽度的实现方法
    本文实例讲述了android获取屏幕高度和宽度的实现方法。分享给大家供大家参考。具体分析如下: 我们需要获取Android手机或Pad的屏幕的物理尺寸,以便于界面的设计或是其他功能的实现。下面就介绍讲一讲如何获取屏幕的物理尺寸 下面的代码即
    android获取屏幕高度和宽度的实现方法
  • Android自定义popupwindow实例代码
    先来看看效果图:一、布局
  • Android第一次实验
    一、实验原理 1.1实验目标 编程实现用户名与密码的存储与调用。 1.2实验要求 设计用户登录界面、登录成功界面、用户注册界面,用户注册时,将其用户名、密码保存到SharedPreference中,登录时输入用户名、密码,读取SharedP
    Android第一次实验

目录