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 保活服務的配置與禁用"}]}]}]}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章