APP開發實戰175-針對Android7.0及更高版本的後臺優化方案
31.18 針對Android7.0及更高版本的後臺優化方案
Android 7.0刪除了三項隱式廣播,以幫助優化記憶體使用和電量消耗。隱式廣播會在後臺頻繁啟動已註冊偵聽這些廣播的應用。刪除這些廣播可以顯著提升裝置效能和使用者體驗。
移動裝置會經歷頻繁的連線變更,例如在 WLAN 和移動資料之間切換時。目前,可以通過在應用清單中註冊一個接收器來偵聽隱式 CONNECTIVITY_ACTION 廣播,讓應用能夠監控這些變更。由於很多應用會註冊接收此廣播,因此單次網路切換即會導致所有應用被喚醒並同時處理此廣播。
同理,在之前版本的 Android 中,應用可以註冊接收來自其他應用(例如相機)的隱式 ACTION_NEW_PICTURE 和 ACTION_NEW_VIDEO 廣播。當使用者使用相機應用拍攝照片時,這些應用即會被喚醒以處理廣播。
為了減少這樣的情況發生,從Android7.0(API level24)開始,系統做了以下限制:
對於針對Android7.0(API level 24)或更高版本系統的APP,如果在manifest檔案中註冊了CONNECTIVITY_ACTION 廣播接收器,那不會再收到CONNECTIVITY_ACTION 廣播。如果使用Context.registerReceiver() 動態註冊的廣播接收器,且context還是有效的,那仍然能接收到CONNECTIVITY_ACTION 廣播。
APP不能再傳送和接收到 ACTION_NEW_PICTURE和ACTION_NEW_VIDEO 廣播,這個影響到所有的APP,而不僅限於針對Android7.0(API level 24)或更高版本系統的APP。
如果APP使用了涉及上述廣播的intent,需要儘快刪除,以便APP可以正常在Android7.0(API level 24)或更高版本系統的裝置上執行。
Android框架提供了幾種解決方案,以減少這些隱式廣播的使用。例如,JobScheduler和GcmNetworkmManager提供了強大的機制在當特定的條件被滿足時,如裝置連線到wifi熱點時,排程網路操作,可以使用JobScheduler對內容提供者的變化做出反應。Jobinfo物件封裝了JobScheduler用於安排job的引數。當執行job的條件滿足時,系統呼叫APP的JobService執行這些job。
31.18.1 對於CONNECTIVITY_ACTION 限制的解決方案
1 排程網路Job(當使用Wifi上網時)
當使用Jobinfo.Builder構建Jobinfo物件時,使用setRequirednNetworktType()方法傳遞Jobinfo.NETWORK_TYPE_UNMETERED作為job引數。下面的程式碼示例當裝置連線到wifi熱點時和充電時,會啟動一個服務:
public static final int MY_BACKGROUND_JOB =0;
...
public static void scheduleJob(Context context) {
JobScheduler js =
(JobScheduler)context.getSystemService(Context.JOB_SCHEDULER_SERVICE);
JobInfo job = new JobInfo.Builder(
MY_BACKGROUND_JOB,
new ComponentName(context, MyJobService.class))
.setRequiredNetworkType(JobInfo.NETWORK_TYPE_UNMETERED)
.setRequiresCharging(true)
.build();
js.schedule(job);
}
當job執行的條件被滿足時,APP接收到一個回撥執行JobService類中的onStartJob() 方法。
使用GMSCore服務的APP,當針對Android 5(API Level 21)或更低系統版本時,可以使用GcmnNetworkmManager和指定Task.NETWORK_STATE_UNMETERED實現類似功能。
2 當APP執行時,監聽網路連線狀態
執行中的APP仍然可以接收到CONNECTIVITY_CHANGE廣播。然而,ConnectivityManager API提供了一個更強大的方法來請求一個回撥僅當特定的網路條件滿足時。
NetworkrRequest物件定義和NetworkCapabilities相關的引數。用NetworkrRequest.Builder類的registerNetworkCallback()建立NetworkrReques物件,然後傳遞NetworkrRequest物件給系統。在網路條件具備的情況下,APP接收到一個回撥函式,執行ConnectivityManager.Networkcallback類定義的onAvailable()方法。
APP會持續收到回撥直到APP退出或呼叫unregisterNetworkCCallback()。
31.18.2 關於NEW_PICTUREand NEW_VIDEO的限制
Android7.0 (API level 24) 擴充套件 JobInfo和JobParameters 提供替代的解決方法。
1 新的JobInfo 方法
Android7.0 (API level 24)擴充套件了JobInfo 如下方法:
JobInfo.TriggerContentUri()
封裝被要求觸發job(當content UR改變時)的引數
JobInfo.Builder.addTriggerContentUri()
傳遞TriggerContentUri 物件給 JobInfo
增加TriggerContentUri.FLAG_NOTIFY_FOR_DESCENDANTS flag觸發job如果被給的URI的任何派生的URI發生變化時
注:TriggerContentuUri()不可與setpPeriodic()或setPersisted()組合使用。如要持續監測內容的變化,需要在應用的JobService處理完最近收到的回撥之前建立一個新的Jobinfo物件。
如下程式碼示例當系統報告content URI(MEDIA_URI)變化時,啟動一個job:
public static final int MY_BACKGROUND_JOB =0;
...
public static void scheduleJob(Context context) {
JobScheduler js =
(JobScheduler)context.getSystemService(Context.JOB_SCHEDULER_SERVICE);
JobInfo.Builder builder = new JobInfo.Builder(
MY_BACKGROUND_JOB,
new ComponentName(context,MediaContentJob.class));
builder.addTriggerContentUri(
newJobInfo.TriggerContentUri(MediaStore.Images.Media.EXTERNAL_CONTENT_URI,
JobInfo.TriggerContentUri.FLAG_NOTIFY_FOR_DESCENDANTS));
js.schedule(builder.build());
}
2 新的JobParameter方法
Android7.0 (API level 24) 也擴充套件了 JobParameters 方法允許APP接什麼contentauthorities和 URIs觸發了job的資訊:
Uri[]getTriggeredContentUris()
返回觸發job的URI陣列,當改變的URI個數超過50時,返回值為null
String[]getTriggeredContentAuthorities()
返回觸發job的content authorities 的字串陣列
如下程式碼重寫了JobService.onStartJob()方法,記錄觸發job的content authorities 和URIs:
@Override
public boolean onStartJob(JobParameters params) {
StringBuilder sb = new StringBuilder();
sb.append("Media content has changed:\n");
if (params.getTriggeredContentAuthorities() != null) {
sb.append("Authorities: ");
boolean first = true;
for (String auth :
params.getTriggeredContentAuthorities()) {
if (first) {
first = false;
} else {
sb.append(", ");
}
sb.append(auth);
}
if (params.getTriggeredContentUris() != null) {
for (Uri uri :params.getTriggeredContentUris()) {
sb.append("\n");
sb.append(uri);
}
}
} else {
sb.append("(No content)");
}
Log.i(TAG, sb.toString());
return true;
}
31.18.3 對於APP的測試
Android 7.0 (APIlevel 24) 提供了新的 AndroidDebug Bridge (ADB) 命名測試當APP的後臺程式不能啟動時,APP是否可以正常執行:
模擬隱式廣播和後臺服務都不能用,輸入以下命令:
$ adb shell cmd appops set<package_name> RUN_IN_BACKGROUND ignore
隱式廣播和後臺服務都可以用,輸入以下命令:
$ adb shell cmd appops set<package_name> RUN_IN_BACKGROUND allow
相關文章
- 針對於早期版本的flutter開發的app的處理FlutterAPP
- APP開發實戰119-APP程式碼優化APP優化
- 針對行動網路開發的優化建議優化
- 微信後臺開發實戰教程
- iphone app開發實戰很重要:《iPhone App開發實戰手冊》讀後感iPhoneAPP
- MySQL 針對 like 條件的優化MySql優化
- 得物App H5秒開優化實戰APPH5優化
- 平臺化軟體開發對企業的優勢
- Java 效能優化技巧及實戰Java優化
- 情指一體化實戰平臺開發,智慧警務系統開發解決方案
- 前端開發效能優化方案前端優化
- 針對enq: KO - fast object checkpoint的優化ENQASTObject優化
- js開發實戰優化小技巧001JS優化
- App監控和效能優化實戰APP優化
- webpack優化之HappyPack 實戰Web優化APP
- Android 後臺耗電分析及優化Android優化
- Hive使用Calcite CBO優化流程及SQL優化實戰Hive優化SQL
- 情指一體化實戰指揮平臺建設方案,合成作戰系統開發
- Hybrid App開發實戰APP
- 情指勤一體化情報指揮實戰平臺開發方案,智慧警務系統開發
- 情指勤一體化實戰平臺建設解決方案,合成作戰系統開發
- 語音社交app開發,如何實現介面優化?APP優化
- Java高併發實戰,鎖的優化Java優化
- 探討針對iOS VS. Android開發遊戲的優劣iOSAndroid開發遊戲
- Android開發優化之——對介面UI的優化(1)Android優化UI
- Android開發優化之——對介面UI的優化(2)Android優化UI
- Android開發優化之——對介面UI的優化(3)Android優化UI
- 【真·乾貨】MySQL 索引及優化實戰MySql索引優化
- 前端開發和後端開發,哪個薪酬更高?前端後端
- 如何針對SEO優化您的WordPress Robots.txt優化
- 【譯】針對 Airbnb 清單頁的 React 效能優化AIReact優化
- 智慧公安情指勤一體化情報指揮實戰平臺開發解決方案
- Android開發優化之——對Bitmap的記憶體優化Android優化記憶體
- 【筆記】《app後臺開發運維和架構實踐》筆記APP運維架構
- 情指勤一體化實戰指揮平臺搭建方案,情指一體化系統開發
- AppCan前端速度優化方案APPPCA前端優化
- iOS 實際開發中對效能優化的幾點建議iOS優化
- 優化動畫卡頓:卡頓原因分析及優化方案優化動畫