Android P上懂版,有的應(yīng)用打開時,會彈出對話框缓窜,內(nèi)容:“此應(yīng)用專為舊版Android打造定续,因此可能無法正常運行谍咆。請嘗試檢查更新或與開發(fā)者聯(lián)系”。用戶會感到困惑私股,真正的原因是什么摹察?
舉例,如下圖某應(yīng)用倡鲸,版本:6.072.001供嚎,下面通過Android P源碼,分析原因:
應(yīng)用啟動峭状,startActivity時克滴,流程會執(zhí)行到realStartActivityLocked方法,代碼位于ActivityStackSupervisor.java优床,可參考我之前一篇文章:startActivity啟動流程的源碼學(xué)習(xí)劝赔。
realStartActivityLocked方法中,會調(diào)用AppWarnings.java的onStartActivity方法胆敞,如下:
final boolean realStartActivityLocked(ActivityRecord r, ProcessRecord app, boolean andResume, boolean checkConfig) throws RemoteException {
try {
// ...
mService.getAppWarningsLocked().onStartActivity(r);
// ...
} catch (RemoteException e) {
// ...
}
}
onStartActivity方法實現(xiàn):
/**
* Called when an activity is being started.
*
* @param r record for the activity being started
*/
public void onStartActivity(ActivityRecord r) {
showUnsupportedCompileSdkDialogIfNeeded(r);
showUnsupportedDisplaySizeDialogIfNeeded(r);
showDeprecatedTargetDialogIfNeeded(r);
}
其中第三個函數(shù)showDeprecatedTargetDialogIfNeeded重點分析:
/**
* Shows the "deprecated target sdk" warning, if necessary.
*
* @param r activity record for which the warning may be displayed
*/
public void showDeprecatedTargetDialogIfNeeded(ActivityRecord r) {
if (r.appInfo.targetSdkVersion < Build.VERSION.MIN_SUPPORTED_TARGET_SDK_INT) {
mUiHandler.showDeprecatedTargetDialog(r);
}
}
重點:這里出現(xiàn)一個判斷方法着帽,正是其決定是否彈窗,判斷條件中Build.VERSION.MIN_SUPPORTED_TARGET_SDK_INT移层,如下:
public static final int MIN_SUPPORTED_TARGET_SDK_INT = SystemProperties.getInt(
"ro.build.version.min_supported_target_sdk", 0);
此屬性默認值仍翰,一般是17。也就是說:
Android P機型上观话,當應(yīng)用的targetSdk版本低于17時予借,應(yīng)用啟動時會彈窗“此應(yīng)用專為舊版Android打造,因此可能無法正常運行频蛔。請嘗試檢查更新或與開發(fā)者聯(lián)系”灵迫。
那么查看截圖的某應(yīng)用Package信息:
Package [com.qqgame.hlddz] (5ecd50f):
......
versionCode=196 minSdk=8 targetSdk=8
versionName=6.043.001
果然其App的targetSdk是8,遠低于17帽驯。
解決了核心問題龟再,繼續(xù)跟進showDeprecatedTargetDialog方法的實現(xiàn),會發(fā)現(xiàn)其主要是調(diào)用對話框類DeprecatedTargetSdkVersionDialog尼变,來彈出此對話框,并顯示提示浆劲。
這里有一個問題嫌术,既然是在每個Activity啟動時會調(diào)用AppWarnings.java的onStartActivity方法,那會不會每次打開新Activity牌借,都彈此對話框度气?如果這樣,用戶體驗也會非常不好膨报。
答案:不會的磷籍,這里有一個小技巧适荣,第一次彈出對話框后,用戶如果選擇“確定”院领,AMS會給此應(yīng)用設(shè)置一個Flag標識:FLAG_HIDE_DEPRECATED_SDK弛矛。每次準備彈窗時,會先判斷此標識值是否為true比然,如果是丈氓,說明已經(jīng)提示過用戶,無需再彈窗强法。代碼如下:
public DeprecatedTargetSdkVersionDialog(final AppWarnings manager, Context context, ApplicationInfo appInfo) {
// ...
final AlertDialog.Builder builder = new AlertDialog.Builder(context)
.setPositiveButton(R.string.ok, (dialog, which) ->
manager.setPackageFlag(
mPackageName, AppWarnings.FLAG_HIDE_DEPRECATED_SDK, true))
.setMessage(message)
.setTitle(label);
// ...
}
最后万俗,結(jié)論如下:
Android P機型上,當應(yīng)用的targetSdk版本低于17時饮怯,應(yīng)用啟動時會彈窗“此應(yīng)用專為舊版Android打造闰歪,因此可能無法正常運行。請嘗試檢查更新或與開發(fā)者聯(lián)系”蓖墅。標準值由ro.build.version.min_supported_target_sdk值設(shè)定的课竣,一般默認是17
作者:kevin song,2019.1.23于南京建鄴區(qū)