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

{"type":"doc","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"Android应用保活是应用、系统、用户三个角色相互影响的产物。几乎每一款应用都希望自己能实现永久保活,并通过保活实现消息推送、信息上报等等交互行为;几乎所有的系统厂商都想把应用关在笼子里,通过控制应用的运行时间来避免过多的电量和性能的消耗,这样可以大大提高系统流畅度和手机使用时间;对于用户来说我们希望使用的时候应用可以更好的运行,比如音乐、导航、通信软件,但是我们又希望不使用时彻底关闭应用,但是大部分用户都不清楚如何彻底关闭一个应用并让它不再运行。那么本文介绍一下在Android系统里面是如何实现保活方案,如何启动或禁用应用的保活。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"heading","attrs":{"align":null,"level":2},"content":[{"type":"text","text":"Android应用自启与白名单"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"Android应用的保活一般会从两个方面着手:一是如何提高应用的存活周期;二是如何唤醒关闭的应用。一般情况下会通过Android账户的自动同步机制和开机广播唤醒已关闭的应用;然后通过定时任务、前台服务、在屏幕上显示控件等方式提高应用的存活周期。在账户同步的服务和开机广播接收器中为应用开启一个前台Service就实现了应用保活的基本策略。下面分别介绍各个方式的实现。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"heading","attrs":{"align":null,"level":3},"content":[{"type":"text","text":"Android应用自启与白名单"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"通过静态注册开机广播可以在系统启动时唤醒应用,应用被唤醒后可以检查并初始化前台服务等保活策略。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"numberedlist","attrs":{"start":1,"normalizeStart":1},"content":[{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":1,"align":null,"origin":null},"content":[{"type":"text","text":"首先我们需要实现BroadcastReceiver的子类作为开机广播的接收器,并在onReceive方法中处理业务逻辑。"}]}]}]},{"type":"codeblock","attrs":{"lang":"text"},"content":[{"type":"text","text":"public class BootReceiver extends BroadcastReceiver {\n @Override\n public void onReceive(Context context, Intent intent) {\n \/\/检查并初始化前台服务等保活策略\n }\n}"}]},{"type":"paragraph","attrs":{"indent":0,"number":2,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"2. 然后我们将开机广播接收器注册到AndroidManifest.xml中,并增加开机动作过滤器。"}]},{"type":"codeblock","attrs":{"lang":"text"},"content":[{"type":"text","text":"\n \n \n \n \n \n "}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"heading","attrs":{"align":null,"level":3},"content":[{"type":"text","text":"账户同步机制"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"Android应用可以在运行时注册系统账户,并通过service与系统账户进行关联,当系统运行时会在特定时期同步账户,同步账户的时候会启动所关联的service,在关联service中可以检查保活方案,通过账户同步机制可以唤醒被关闭的应用。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"在开始之前首先定义两常量,在文中通过{常量名}的方式方式指代:accountType=“xxxxxx”contentAuthority=“xxxx”"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"numberedlist","attrs":{"start":1,"normalizeStart":1},"content":[{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":1,"align":null,"origin":null},"content":[{"type":"text","text":"在项目res\/xml中添加账户配置文件,指定文件名为account_sync_adapter.xml"}]}]}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"codeblock","attrs":{"lang":"text"},"content":[{"type":"text","text":"\n\n"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"2. 在项目res\/xml中配置账户显示信息,命名为account_authenticator.xml"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"codeblock","attrs":{"lang":"text"},"content":[{"type":"text","text":"\n\n\n android:label=\"@string\/app_name\" \/>"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"3. 实现ContentProvider的子类,并在AndroidManifest.xml中注册"}]},{"type":"codeblock","attrs":{"lang":"text"},"content":[{"type":"text","text":"public class AccountSyncProvider extends ContentProvider {\n @Override\n public boolean onCreate() {\n return false;\n }\n\n @Nullable\n @Override\n public Cursor query(@NonNull Uri uri, @Nullable String[] projection, @Nullable String selection,\n @Nullable String[] selectionArgs, @Nullable String sortOrder) {\n return null;\n }\n\n @Nullable\n @Override\n public String getType(@NonNull Uri uri) {\n return null;\n }\n\n @Nullable\n @Override\n public Uri insert(@NonNull Uri uri, @Nullable ContentValues values) {\n return null;\n }\n\n @Override\n public int delete(@NonNull Uri uri, @Nullable String selection, @Nullable String[] selectionArgs) {\n return 0;\n }\n\n @Override\n public int update(@NonNull Uri uri, @Nullable ContentValues values, @Nullable String selection,\n @Nullable String[] selectionArgs) {\n return 0;\n }\n}"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"注册服务"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"codeblock","attrs":{"lang":"text"},"content":[{"type":"text","text":""}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"4. 实现账户的认证service,系统会调用该service认证账户,由于是用于保活的空账户,所以不需要关注具体业务"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"codeblock","attrs":{"lang":"text"},"content":[{"type":"text","text":"public class AuthenticationService extends Service {\n\n private AccountAuthenticator accountAuthenticator;\n\n @Nullable\n @Override\n public IBinder onBind(Intent intent) {\n return accountAuthenticator.getIBinder();\/\/返回binder对象供系统使用\n }\n\n @Override\n public void onCreate() {\n super.onCreate();\n accountAuthenticator = new AccountAuthenticator(this);\n }\n\n public static class AccountAuthenticator extends AbstractAccountAuthenticator {\n\n public AccountAuthenticator(Context context) {\n super(context);\n }\n\n @Override\n public Bundle editProperties(AccountAuthenticatorResponse response, String accountType) {\n return null;\n }\n\n @Override\n public Bundle addAccount(AccountAuthenticatorResponse response, String accountType, String authTokenType,\n String[] requiredFeatures, Bundle options) throws NetworkErrorException {\n return null;\n }\n\n @Override\n public Bundle confirmCredentials(AccountAuthenticatorResponse response, Account account,\n Bundle options) throws NetworkErrorException {\n return null;\n }\n\n @Override\n public Bundle getAuthToken(AccountAuthenticatorResponse response, Account account,\n String authTokenType, Bundle options) throws NetworkErrorException {\n return null;\n }\n\n @Override\n public String getAuthTokenLabel(String authTokenType) {\n return null;\n }\n\n @Override\n public Bundle updateCredentials(AccountAuthenticatorResponse response, Account account,\n String authTokenType, Bundle options) throws NetworkErrorException {\n return null;\n }\n\n @Override\n public Bundle hasFeatures(AccountAuthenticatorResponse response, Account account,\n String[] features) throws NetworkErrorException {\n return null;\n }"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"在AndroidManifest.xml中注册账户认证服务"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"codeblock","attrs":{"lang":"text"},"content":[{"type":"text","text":"\n \n \n \n \n"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"5. 编写并配置账户同步服务,系统自动同步账户时回调此服务"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"codeblock","attrs":{"lang":"text"},"content":[{"type":"text","text":"public class AccountSyncService extends Service {\n\n private SyncAdapter mSyncAdapter;\n\n private static final String TAG = \"SyncService\";\n\n @Nullable\n @Override\n public IBinder onBind(Intent intent) {\n return mSyncAdapter.getSyncAdapterBinder();\n }\n\n @Override\n public void onCreate() {\n super.onCreate();\n mSyncAdapter = new SyncAdapter(getApplicationContext(), true);\n }\n\n ;\n public static class SyncAdapter extends AbstractThreadedSyncAdapter {\n public SyncAdapter(Context context, boolean autoInitialize) {\n super(context, autoInitialize);\n }\n\n\n @Override\n public void onPerformSync(Account account, Bundle extras, String authority, ContentProviderClient provider, SyncResult syncResult) {\n \/\/账户同步时回调此方法,在此处检测保活业务\n }\n }\n}"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"在AndroidManifest.xml中注册账户同步服务"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"codeblock","attrs":{"lang":"text"},"content":[{"type":"text","text":"\n android:enabled=\"true\"\n android:exported=\"true\">\n \n \n \n \n"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"6. 添加账户并设置自动同步"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"codeblock","attrs":{"lang":"text"},"content":[{"type":"text","text":"accountName=\"test\"\naccountPwd=\"pwd\"\n\/\/添加账户\n AccountManager accountManager = (AccountManager) context.getSystemService(Context.ACCOUNT_SERVICE);\n Account account = new Account(accountName, {accountType});\n accountManager.addAccountExplicitly(account, accountPwd, new Bundle());\n \/\/设置账户同步\n Account account = new Account(accountName, {accountType});\n\/\/ 下面三个都需要同一个权限 WRITE_SYNC_SETTINGS\n\/\/ 设置同步\nContentResolver.setIsSyncable(account, {contentAuthority}, 1);\n\/\/ 自动同步\nContentResolver.setSyncAutomatically(account, {contentAuthority}, true);\n\/\/ 设置同步周期\nContentResolver.addPeriodicSync(account, {contentAuthority}, new Bundle(), 1);"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"heading","attrs":{"align":null,"level":3},"content":[{"type":"text","text":"Schedule定时任务"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"1. 实现JobService的子类,用于执行任务时回调"}]},{"type":"paragraph","attrs":{"indent":0,"number":1,"align":null,"origin":null}},{"type":"codeblock","attrs":{"lang":"text"},"content":[{"type":"text","text":"@RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)\npublic class LiveJobService extends JobService {\n @Override\n public boolean onStartJob(JobParameters params) {\n \/\/执行任务时回调\n return false;\n }\n\n @Override\n public boolean onStopJob(JobParameters params) {\n return false;\n }\n}"}]},{"type":"paragraph","attrs":{"indent":0,"number":1,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"2. 在AndroidManifest中配置任务service"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"codeblock","attrs":{"lang":"text"},"content":[{"type":"text","text":""}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"3. 设置定时任务"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"codeblock","attrs":{"lang":"text"},"content":[{"type":"text","text":"JobScheduler jobScheduler = (JobScheduler) context.getSystemService(Context.JOB_SCHEDULER_SERVICE);\n\/\/setPersisted 在设备重启依然执行\nJobInfo.Builder builder = new JobInfo.Builder(lastJobId+i, new ComponentName(context.getPackageName(),\nLiveJobService.class.getName())).setPersisted(true);\n\/\/ 50s后执行任务\nif (Build.VERSION.SDK_INT < Build.VERSION_CODES.N) {\n builder.setPeriodic(50000);\n} else {\n \/\/ 延迟执行任务\n builder.setMinimumLatency(50000);\n}\njobScheduler.schedule(builder.build());"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"heading","attrs":{"align":null,"level":3},"content":[{"type":"text","text":"前台服务"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"保活服务一般在Service中后台运行,而Android系统对后台服务有一些列的运行限制,所以把服务绑定为前台服务会提高服务的优先级,在系统资源紧张时可以更好的运行。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"1. 实现Service子类NotificationService,并在在onStartCommand方法中开启常驻通知"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"codeblock","attrs":{"lang":"text"},"content":[{"type":"text","text":"\/**\n * @author walker\n * @date 2020\/12\/25.\n * @description 在应用后台处理数据\n *\/\npublic class NotificationService extends Service {\n\n @Nullable\n @Override\n public IBinder onBind(Intent intent) {\n return null;\n }\n\n @Override\n public void onCreate() {\n super.onCreate();\n }\n\n @Override\n public int onStartCommand(Intent intent, int flags, int startId) {\n \/\/ 如果Service被终止\n \/\/ 当资源允许情况下,重启service\n \/\/绑定前台通知\n if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {\n setForegroundService();\n }\n return START_STICKY;\n }\n\n \/**\n * 通过通知启动服务\n *\/\n @androidx.annotation.RequiresApi(api = Build.VERSION_CODES.O)\n public void setForegroundService() {\n \/\/设定的通知渠道名称\n String channelName = \"slient_name\";\n String CHANNEL_ID = \"slient_id\";\n \/\/设置通知的重要程度\n int importance = NotificationManager.IMPORTANCE_LOW;\n \/\/构建通知渠道\n NotificationChannel channel = new NotificationChannel(CHANNEL_ID, channelName, importance);\n channel.setDescription(\"test\");\n \/\/在创建的通知渠道上发送通知\n NotificationCompat.Builder builder = new NotificationCompat.Builder(this, CHANNEL_ID);\n builder.setSmallIcon(R.drawable.ic_launcher) \/\/设置通知图标\n .setContentTitle(\"通知\")\/\/设置通知标题\n .setContentText(\"前台服务\")\/\/设置通知内容\n .setAutoCancel(true) \/\/用户触摸时,自动关闭\n .setOngoing(true);\/\/设置处于运行状态\n \/\/向系统注册通知渠道,注册后不能改变重要性以及其他通知行为\n NotificationManager notificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);\n notificationManager.createNotificationChannel(channel);\n \/\/将服务置于启动状态 NOTIFICATION_ID指的是创建的通知的ID\n startForeground(111, builder.build());\n }\n\n @Override\n public void onDestroy() {\n super.onDestroy();\n }\n}"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"2. 在AndroidManifest中配置服务"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"codeblock","attrs":{"lang":"text"},"content":[{"type":"text","text":"\n"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"3. 在应用启动时开启服务"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"codeblock","attrs":{"lang":"text"},"content":[{"type":"text","text":"startService(new Intent(context,DataService.class));"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"heading","attrs":{"align":null,"level":2},"content":[{"type":"text","text":"如何禁用后台运行"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"我们在开发或配置应用保活相关功能时主要通过开机自启、后台运行、关联启动、账户同步几个方面入手,不同的手机设置入口有可能不一样,但是可以参考这几点进行设置,下面介绍一下华为荣耀20上的配置方式。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"heading","attrs":{"align":null,"level":3},"content":[{"type":"text","text":"01开机自启权限的处理"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"以华为系统为例,在【手机管家】app中找到【应用启动管理】,并在应用启动管理中找到对应的app,将对应app切换为【手动管理】,并为激活【允许自动启动】【允许关联启动】【允许后台活动】三个选项。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"strong"}],"text":"允许设备开机自启以及后台服务的配置:"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"image","attrs":{"src":"https:\/\/static001.geekbang.org\/infoq\/40\/40a1b52e61d25076dfd74314ed3f91cb.jpeg","alt":"图片","title":null,"style":[{"key":"width","value":"75%"},{"key":"bordertype","value":"none"}],"href":null,"fromPaste":true,"pastePass":true}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"strong"}],"text":"禁止后台服务以及开机自启的设置:"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"image","attrs":{"src":"https:\/\/static001.geekbang.org\/infoq\/41\/418d74587628f403b5fc55e617cf0559.jpeg","alt":"图片","title":null,"style":[{"key":"width","value":"75%"},{"key":"bordertype","value":"none"}],"href":null,"fromPaste":true,"pastePass":true}},{"type":"heading","attrs":{"align":null,"level":3},"content":[{"type":"text","text":"02账户同步服务的处理"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"我们在【设置】\/【账户】下可以看到系统内所有的账户信息,并可以在这里管理同步服务"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"允许账户同步设置:"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"允许账户同步时系统会按既定策略回调注册同步Service,在Service内可以启动应用其他服务,但是部分机型上可能存在适配问题。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"image","attrs":{"src":"https:\/\/static001.geekbang.org\/infoq\/21\/21c1505f370585677afdbfc3d209f9a8.jpeg","alt":"图片","title":null,"style":[{"key":"width","value":"75%"},{"key":"bordertype","value":"none"}],"href":null,"fromPaste":true,"pastePass":true}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"strong"}],"text":"禁用所有账户同步功能:"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"image","attrs":{"src":"https:\/\/static001.geekbang.org\/infoq\/5e\/5eab9e49b67c89e2bb1637ce22af5422.jpeg","alt":"图片","title":null,"style":[{"key":"width","value":"75%"},{"key":"bordertype","value":"none"}],"href":null,"fromPaste":true,"pastePass":true}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"strong"}],"text":"禁用某一应用的账户同步功能:"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"image","attrs":{"src":"https:\/\/static001.geekbang.org\/infoq\/93\/93a27db1050ccfa6fe1a9ebd390e5733.jpeg","alt":"图片","title":null,"style":[{"key":"width","value":"75%"},{"key":"bordertype","value":"none"}],"href":null,"fromPaste":true,"pastePass":true}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"本文转载自:360技术(ID:qihoo_tech)"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"原文链接:"},{"type":"link","attrs":{"href":"https:\/\/mp.weixin.qq.com\/s\/mApIBQemJZyw3dbbzt-h1g","title":"xxx","type":null},"content":[{"type":"text","text":"Android App 保活服务的配置与禁用"}]}]}]}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章