当前位置:   article > 正文

Android App 保活服务的配置与禁用_android10 保活 2023

android10 保活 2023

Android应用保活是应用、系统、用户三个角色相互影响的产物。几乎每一款应用都希望自己能实现永久保活,并通过保活实现消息推送、信息上报等等交互行为;几乎所有的系统厂商都想把应用关在笼子里,通过控制应用的运行时间来避免过多的电量和性能的消耗,这样可以大大提高系统流畅度和手机使用时间;对于用户来说我们希望使用的时候应用可以更好的运行,比如音乐、导航、通信软件,但是我们又希望不使用时彻底关闭应用,但是大部分用户都不清楚如何彻底关闭一个应用并让它不再运行。那么本文介绍一下在Android系统里面是如何实现保活方案,如何启动或禁用应用的保活。

Android应用自启与白名单

Android应用的保活一般会从两个方面着手:一是如何提高应用的存活周期;二是如何唤醒关闭的应用。一般情况下会通过Android账户的自动同步机制和开机广播唤醒已关闭的应用;然后通过定时任务、前台服务、在屏幕上显示控件等方式提高应用的存活周期。在账户同步的服务和开机广播接收器中为应用开启一个前台Service就实现了应用保活的基本策略。下面分别介绍各个方式的实现。

Android应用自启与白名单

通过静态注册开机广播可以在系统启动时唤醒应用,应用被唤醒后可以检查并初始化前台服务等保活策略。

  1. public class BootReceiver extends BroadcastReceiver {
  2. @Override
  3. public void onReceive(Context context, Intent intent) {
  4. //检查并初始化前台服务等保活策略
  5. }
  6. }
  1. <receiver
  2. android:name=".receiver.BootReceiver"
  3. android:directBootAware="true"
  4. android:enabled="true"
  5. android:exported="true">
  6. <!--通过priority指定广播的优先级-->
  7. <intent-filter android:priority="2147483647">
  8. <action android:name="android.intent.action.BOOT_COMPLETED" />
  9. <action android:name="android.intent.action.LOCKED_BOOT_COMPLETED" />
  10. </intent-filter>
  11. </receiver>

账户同步机制

Android应用可以在运行时注册系统账户,并通过service与系统账户进行关联,当系统运行时会在特定时期同步账户,同步账户的时候会启动所关联的service,在关联service中可以检查保活方案,通过账户同步机制可以唤醒被关闭的应用。

在开始之前首先定义两常量,在文中通过{常量名}的方式方式指代:

accountType=“xxxxxx”

contentAuthority=“xxxx”

  1. <?xml version="1.0" encoding="utf-8"?>
  2. <sync-adapter xmlns:android="http://schemas.android.com/apk/res/android"
  3. android:accountType="{accountType}"
  4. android:allowParallelSyncs="false"
  5. android:contentAuthority="{contentAuthority}"
  6. android:isAlwaysSyncable="true"
  7. android:supportsUploading="true"
  8. android:userVisible="true" />
  1. <?xml version="1.0" encoding="utf-8"?>
  2. <account-authenticator xmlns:android="http://schemas.android.com/apk/res/android"
  3. android:accountType="com.qihoo.qa.ticker.account"
  4. android:icon="@mipmap/ic_launcher" <!--在系统设置中显示的账户图标-->
  5. android:label="@string/app_name" /><!--在系统设置中显示的账户名称-->
  1. public class AccountSyncProvider extends ContentProvider {
  2. @Override
  3. public boolean onCreate() {
  4. return false;
  5. }
  6. @Nullable
  7. @Override
  8. public Cursor query(@NonNull Uri uri, @Nullable String[] projection, @Nullable String selection,
  9. @Nullable String[] selectionArgs, @Nullable String sortOrder) {
  10. return null;
  11. }
  12. @Nullable
  13. @Override
  14. public String getType(@NonNull Uri uri) {
  15. return null;
  16. }
  17. @Nullable
  18. @Override
  19. public Uri insert(@NonNull Uri uri, @Nullable ContentValues values) {
  20. return null;
  21. }
  22. @Override
  23. public int delete(@NonNull Uri uri, @Nullable String selection, @Nullable String[] selectionArgs) {
  24. return 0;
  25. }
  26. @Override
  27. public int update(@NonNull Uri uri, @Nullable ContentValues values, @Nullable String selection,
  28. @Nullable String[] selectionArgs) {
  29. return 0;
  30. }
  31. }
  1. <provider
  2. android:name=".account.AccountSyncProvider"
  3. android:authorities="{contentAuthority}"
  4. android:enabled="true"
  5. android:exported="true" />
  1. public class AuthenticationService extends Service {
  2. private AccountAuthenticator accountAuthenticator;
  3. @Nullable
  4. @Override
  5. public IBinder onBind(Intent intent) {
  6. return accountAuthenticator.getIBinder();//返回binder对象供系统使用
  7. }
  8. @Override
  9. public void onCreate() {
  10. super.onCreate();
  11. accountAuthenticator = new AccountAuthenticator(this);
  12. }
  13. public static class AccountAuthenticator extends AbstractAccountAuthenticator {
  14. public AccountAuthenticator(Context context) {
  15. super(context);
  16. }
  17. @Override
  18. public Bundle editProperties(AccountAuthenticatorResponse response, String accountType) {
  19. return null;
  20. }
  21. @Override
  22. public Bundle addAccount(AccountAuthenticatorResponse response, String accountType, String authTokenType,
  23. String[] requiredFeatures, Bundle options) throws NetworkErrorException {
  24. return null;
  25. }
  26. @Override
  27. public Bundle confirmCredentials(AccountAuthenticatorResponse response, Account account,
  28. Bundle options) throws NetworkErrorException {
  29. return null;
  30. }
  31. @Override
  32. public Bundle getAuthToken(AccountAuthenticatorResponse response, Account account,
  33. String authTokenType, Bundle options) throws NetworkErrorException {
  34. return null;
  35. }
  36. @Override
  37. public String getAuthTokenLabel(String authTokenType) {
  38. return null;
  39. }
  40. @Override
  41. public Bundle updateCredentials(AccountAuthenticatorResponse response, Account account,
  42. String authTokenType, Bundle options) throws NetworkErrorException {
  43. return null;
  44. }
  45. @Override
  46. public Bundle hasFeatures(AccountAuthenticatorResponse response, Account account,
  47. String[] features) throws NetworkErrorException {
  48. return null;
  49. }
  50. }
  51. }
  1. <service android:name=".account.AuthenticationService">
  2. <intent-filter>
  3. <action android:name="android.accounts.AccountAuthenticator" />
  4. </intent-filter>
  5. <meta-data
  6. android:name="android.accounts.AccountAuthenticator"
  7. android:resource="@xml/account_authenticator" /> <!--指定账户配置文件-->
  8. </service>
  1. public class AccountSyncService extends Service {
  2. private SyncAdapter mSyncAdapter;
  3. private static final String TAG = "SyncService";
  4. @Nullable
  5. @Override
  6. public IBinder onBind(Intent intent) {
  7. return mSyncAdapter.getSyncAdapterBinder();
  8. }
  9. @Override
  10. public void onCreate() {
  11. super.onCreate();
  12. mSyncAdapter = new SyncAdapter(getApplicationContext(), true);
  13. }
  14. ;
  15. public static class SyncAdapter extends AbstractThreadedSyncAdapter {
  16. public SyncAdapter(Context context, boolean autoInitialize) {
  17. super(context, autoInitialize);
  18. }
  19. @Override
  20. public void onPerformSync(Account account, Bundle extras, String authority, ContentProviderClient provider, SyncResult syncResult) {
  21. //账户同步时回调此方法,在此处检测保活业务
  22. }
  23. }
  24. }
  1. <service
  2. android:name=".account.AccountSyncService"<!--指定service文件-->
  3. android:enabled="true"
  4. android:exported="true">
  5. <intent-filter>
  6. <action android:name="android.content.SyncAdapter" />
  7. </intent-filter>
  8. <meta-data
  9. android:name="android.content.SyncAdapter"
  10. android:resource="@xml/account_sync_adapter" /><!--指定配置文件,该配置文件需要手动添加-->
  11. </service>
  1. accountName="test"
  2. accountPwd="pwd"
  3. //添加账户
  4. AccountManager accountManager = (AccountManager) context.getSystemService(Context.ACCOUNT_SERVICE);
  5. Account account = new Account(accountName, {accountType});
  6. accountManager.addAccountExplicitly(account, accountPwd, new Bundle());
  7. //设置账户同步
  8. Account account = new Account(accountName, {accountType});
  9. // 下面三个都需要同一个权限 WRITE_SYNC_SETTINGS
  10. // 设置同步
  11. ContentResolver.setIsSyncable(account, {contentAuthority}, 1);
  12. // 自动同步
  13. ContentResolver.setSyncAutomatically(account, {contentAuthority}, true);
  14. // 设置同步周期
  15. ContentResolver.addPeriodicSync(account, {contentAuthority}, new Bundle(), 1);

Schedule定时任务

  1. @RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
  2. public class LiveJobService extends JobService {
  3. @Override
  4. public boolean onStartJob(JobParameters params) {
  5. //执行任务时回调
  6. return false;
  7. }
  8. @Override
  9. public boolean onStopJob(JobParameters params) {
  10. return false;
  11. }
  12. }
  1. <service
  2. android:name=".service.LiveJobService"
  3. android:enabled="true"
  4. android:exported="true"
  5. android:permission="android.permission.BIND_JOB_SERVICE" /><!--指定服务权限-->
  1. JobScheduler jobScheduler = (JobScheduler) context.getSystemService(Context.JOB_SCHEDULER_SERVICE);
  2. //setPersisted 在设备重启依然执行
  3. JobInfo.Builder builder = new JobInfo.Builder(lastJobId+i, new ComponentName(context.getPackageName(),
  4. LiveJobService.class.getName())).setPersisted(true);
  5. // 50s后执行任务
  6. if (Build.VERSION.SDK_INT < Build.VERSION_CODES.N) {
  7. builder.setPeriodic(50000);
  8. } else {
  9. // 延迟执行任务
  10. builder.setMinimumLatency(50000);
  11. }
  12. jobScheduler.schedule(builder.build());

前台服务

保活服务一般在Service中后台运行,而Android系统对后台服务有一些列的运行限制,所以把服务绑定为前台服务会提高服务的优先级,在系统资源紧张时可以更好的运行。

  1. /**
  2. * @author walker
  3. * @date 2020/12/25.
  4. * @description 在应用后台处理数据
  5. */
  6. public class NotificationService extends Service {
  7. @Nullable
  8. @Override
  9. public IBinder onBind(Intent intent) {
  10. return null;
  11. }
  12. @Override
  13. public void onCreate() {
  14. super.onCreate();
  15. }
  16. @Override
  17. public int onStartCommand(Intent intent, int flags, int startId) {
  18. // 如果Service被终止
  19. // 当资源允许情况下,重启service
  20. //绑定前台通知
  21. if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
  22. setForegroundService();
  23. }
  24. return START_STICKY;
  25. }
  26. /**
  27. * 通过通知启动服务
  28. */
  29. @androidx.annotation.RequiresApi(api = Build.VERSION_CODES.O)
  30. public void setForegroundService() {
  31. //设定的通知渠道名称
  32. String channelName = "slient_name";
  33. String CHANNEL_ID = "slient_id";
  34. //设置通知的重要程度
  35. int importance = NotificationManager.IMPORTANCE_LOW;
  36. //构建通知渠道
  37. NotificationChannel channel = new NotificationChannel(CHANNEL_ID, channelName, importance);
  38. channel.setDescription("test");
  39. //在创建的通知渠道上发送通知
  40. NotificationCompat.Builder builder = new NotificationCompat.Builder(this, CHANNEL_ID);
  41. builder.setSmallIcon(R.drawable.ic_launcher) //设置通知图标
  42. .setContentTitle("通知")//设置通知标题
  43. .setContentText("前台服务")//设置通知内容
  44. .setAutoCancel(true) //用户触摸时,自动关闭
  45. .setOngoing(true);//设置处于运行状态
  46. //向系统注册通知渠道,注册后不能改变重要性以及其他通知行为
  47. NotificationManager notificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
  48. notificationManager.createNotificationChannel(channel);
  49. //将服务置于启动状态 NOTIFICATION_ID指的是创建的通知的ID
  50. startForeground(111, builder.build());
  51. }
  52. @Override
  53. public void onDestroy() {
  54. super.onDestroy();
  55. }
  56. }
  1. <!--通过android:process标签指定独立进程名-->
  2. <service
  3. android:name=".service.DataService"
  4. android:enabled="true"
  5. android:exported="false"
  6. android:process=":sync" />
  1. 在应用启动时开启服务
  1. startService(new Intent(context,DataService.class));

如何禁用后台运行

我们在开发或配置应用保活相关功能时主要通过开机自启、后台运行、关联启动、账户同步几个方面入手,不同的手机设置入口有可能不一样,但是可以参考这几点进行设置,下面介绍一下华为荣耀20上的配置方式。

01

开机自启权限的处理

以华为系统为例,在【手机管家】app中找到【应用启动管理】,并在应用启动管理中找到对应的app,将对应app切换为【手动管理】,并为激活【允许自动启动】【允许关联启动】【允许后台活动】三个选项。

允许设备开机自启以及后台服务的配置:

1000×473 57.2 KB

禁止后台服务以及开机自启的设置:

1000×494 59.9 KB

02

账户同步服务的处理

我们在【设置】/【账户】下可以看到系统内所有的账户信息,并可以在这里管理同步服务

允许账户同步设置:

允许账户同步时系统会按既定策略回调注册同步Service,在Service内可以启动应用其他服务,但是部分机型上可能存在适配问题

1000×464 37.4 KB

1000×596 51.1 KB

1000×617 39.4 KB

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/2023面试高手/article/detail/633798
推荐阅读
相关标签
  

闽ICP备14008679号