Android 应用进程保活方案实战

这篇具有很好参考价值的文章主要介绍了Android 应用进程保活方案实战。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

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

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

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

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

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

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

一、前台服务

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

复制<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
<uses-permission android:name="android.permission.FOREGROUND_SERVICE"/>

2.创建一个后台服务,让 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);
    }
}

3.在 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() 方法来停止服务,不然可能会一直在后台运行造成系统负担增大。

二、双进程守护

  • 1.创建一个守护服务类 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;
        }
    }
    

    2.创建一个拉活服务类 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;
        }
    }
    

    3.在 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 来唤醒应用,让它重新处于前台运行的状态,保证在后台时极少被杀死的情况。同时,由于开启了前台服务,又频繁切换前台后台可能会导致用户的通知栏被大量的“常驻通知”,需要注意这一点。

  • android保活第三方,android,java,开发语言

    对上述功能增加手机开机启动功能
  • android保活第三方,android,java,开发语言

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

    1.创建一个 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);
            }
        }
    }
    

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

    复制<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
    
    <receiver
        android:name=".BootReceiver"
        android:enabled="true"
        android:exported="true"
        android:permission="android.permission.RECEIVE_BOOT_COMPLETED" >
        <intent-filter>
            <action android:name="android.intent.action.BOOT_COMPLETED" />
        </intent-filter>
    </receiver>
    

    3.在 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<ActivityManager.RunningServiceInfo> list = am.getRunningServices(Integer.MAX_VALUE);
    
            for (ActivityManager.RunningServiceInfo info : list) {
                if (serviceName.equals(info.service.getClassName())) {
                    return true;
                }
            }
    
            return false;
        }
    }
    

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

三、JobScheduler

1.创建一个 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;
    }
}

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

复制<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
<uses-permission android:name="android.permission.WAKE_LOCK" />

<application>
    ...

    <service
        android:name=".MyJobService"
        android:permission="android.permission.BIND_JOB_SERVICE" />

    ...
</application>

3.在应用启动时调起对应的 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

1.创建一个常驻进程 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);
    }
}

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

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

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

复制<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />

<receiver
    android:name=".KeepAliveReceiver"
    android:enabled="true"
    android:exported="true">
    <intent-filter>
        <action android:name="android.intent.action.BOOT_COMPLETED" />
        <action android:name="myAction" />
    </intent-filter>
</receiver>

<service
    android:name=".KeepAliveService"
    android:exported="false" />

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

4.在 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

1.创建一个 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();
    }
}

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

复制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 表示如果当前已经有相同名字的任务在执行,则保持不变,不会重新启动。

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

复制<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
<uses-permission android:name="android.permission.WAKE_LOCK" />

<application>
    ...

    <receiver
        android:name=".KeepAliveReceiver"
        android:enabled="true"
        android:exported="false">
        <intent-filter>
            <action android:name="android.intent.action.BOOT_COMPLETED" />
        </intent-filter>
    </receiver>

    ...
</application>

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

4.创建一个 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));
        }
    }
}

5.创建一个常驻服务,确保应用在后台运行的同时能够通过 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 定时任务被系统强杀时,能够通过广播重启服务,达到保活效果。

6.最后在 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实现应用进程保活的接入方案
  • android保活第三方,android,java,开发语言

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

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

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

    2.创建一个自定义的 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() 方法,用于停止保活任务。

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

    复制<service
        android:name=".MyService"
        android:enabled="true"
        android:exported="false" />
    
    <receiver
        android:name=".MyReceiver"
        android:priority="1000"
        android:exported="false">
        <intent-filter>
            <action android:name="android.intent.action.BOOT_COMPLETED" />
            <action android:name="android.intent.action.USER_PRESENT" />
        </intent-filter>
    </receiver>
    

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

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

    复制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 中进行实现。

    6.最后在 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://www.toymoban.com/news/detail-617539.html

到了这里,关于Android 应用进程保活方案实战的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • Android 13.0 在系统app安装第三方app弹出 解析安装包出现问题 的解决方案

    在13.0的系统定制化开发中,对于系统内置app中用代码调用系统安装接口安装app时抛出Permission Denial: that is not exported from UID 1000的异常,查询资料这个异常发现通常是由于Uri权限导致的问题,这就需要看PMS在安装的时候,需要什么权限,然后根据相关的日志分析 相关的安装流程

    2024年02月10日
    浏览(54)
  • Android app保活(前台服务)

    国内厂商定制,除非厂商给app白名单,否则只能用户手动添加白名单(应用自启和后台运行),才能通过前台服务实现app保活。 这里介绍前台服务相关实现方式。 开启服务: 服务: 清单文件

    2024年02月09日
    浏览(42)
  • Android App保活的方式

    在Android系统中,当应用程序进入后台或者被用户关闭后,系统会自动回收该应用程序的资源,以达到优化系统性能的目的。但是,有些应用程序需要在后台长时间运行,比如音乐播放器、即时通讯等,这时就需要使用一些技术手段来保持应用程序的运行状态,以确保应用程序

    2024年02月16日
    浏览(46)
  • 【Android知识笔记】应用进程(二)

    向AMS发送startService请求 startService 时会首先拿到 AMS 的Binder代理对象,向 AMS 发起 startService 请求: AMS处理startService请求 接下来看 AMS 端处理应用的 startService 请求: 回忆一下应用进程启动流程: 接下来看如果 Service 所在应用进程没有启动的情况,启动应用进程后会向 AMS 报告

    2024年02月16日
    浏览(46)
  • 2023Android白名单保活(后台定位)分享

    Android 系统已经更新到13了,各个Rom厂商也控制越来越严格了,还能做保活App。答案肯定是可以的,然而路线是很艰难的。 最近接到一个项目,需要安装一次app后,就需要一直获取定位。随着Android系统的不断完善,厂商rom的不断优化,想要实现后台不断定位的功能,要面临的

    2024年02月08日
    浏览(90)
  • Android后台驻留:保活和回收的机制

    众所周知,Android平台的管理机制下,App进入后台后,为了提供持续的及时服务(如推送、音乐),或进行驻留获取收益(跟踪、信息收集、广告)等,会利用一些方法来让自身保持活跃,躲过被Android系统或用户发觉、清理,实现后台驻留。 其中,后台驻留的广义概念,除了

    2024年02月07日
    浏览(51)
  • 关于Android 11、12和13服务保活问题

    物联网环境,为了解决不同厂商、不同设备、不同网络情况下使用顺畅,同时也考虑到节约成本,缩小应用体积的好处,我们需要一个服务应用一直存在系统中,保活它以提供服务给其他客户端调用。 开机自启动,通过广播通信, 必要权限 开机自启动Service相关代码 注意

    2023年04月08日
    浏览(87)
  • [Android 13]Input系列--触摸事件在应用进程的分发和处理

    hongxi.zhu 2023-7-21 Android 13 前面我们已经梳理了input事件在native层的传递,这一篇我们接着探索input事件在应用中的传递与处理,我们将按键事件和触摸事件分开梳理,这一篇就只涉及触摸事件。 一、事件的接收 从前面的篇幅我们知道,framework native层 InputDispatcher 向应用通过s

    2024年02月15日
    浏览(39)
  • 【干货】Android系统定制基础篇:第十四部分(禁止第三方应用调用系统设置、增加TP配置、增加摄像头镜像设置、增加摄像头默认角度设置、修改默认语言)

    修改文件 frameworksbasecorejavaandroidappActivityManagerNative.java 如下: 属性配置: Android 主板定制过程中经常出现客户需要临时适配各种 TP(包括 USB TP),因此在设置菜单中加入 xy 交换,x 反转,y 反转常用配置,以客户多样性需求。 以下修改基于Android 8.1 SDK,如下: 属性配置

    2024年02月10日
    浏览(51)
  • 【Android】Android应用安全方案梳理_so防护手段

    对于在 Native 层作签名校验,将上述方法翻译成对应的 JNI 调用即可,这里就不赘述了。 上面是签名校验的逻辑,看似美好,实际上稍微碰到有点破解的经验的就顶不住了。我之前遇到的一种破解上述签名校验的方法是,在自定义 Application 的 onCreate() 方法中读取 APK 的签名并

    2024年04月27日
    浏览(38)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包