應用彈窗“此應用專為舊版Android打造,因此可能無法正常執行...”的原因
Android P上,有的應用開啟時,會彈出對話方塊,內容: “此應用專為舊版Android打造,因此可能無法正常執行。請嘗試檢查更新或與開發者聯絡”。 使用者會感到困惑,真正的原因是什麼?
舉例,如下圖某應用,版本:6.072.001,

下面通過Android P原始碼,分析原因:
應用啟動,startActivity時,流程會執行到realStartActivityLocked方法,程式碼位於ActivityStackSupervisor.java,可參考我之前一篇文章: startActivity啟動流程的原始碼學習 。
realStartActivityLocked方法中,會呼叫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方法實現:
/** * 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); }
其中第三個函式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); } }
重點:這裡出現一個判斷方法,正是其決定是否彈窗,判斷條件中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機型上,當應用的targetSdk版本低於17時,應用啟動時會彈窗“此應用專為舊版Android打造,因此可能無法正常執行。請嘗試檢查更新或與開發者聯絡”。
那麼檢視截圖的某應用Package資訊:
Package [com.qqgame.hlddz] (5ecd50f): ...... versionCode=196 minSdk=8 targetSdk=8 versionName=6.043.001
果然其App的targetSdk是8,遠低於17。
解決了核心問題,繼續跟進showDeprecatedTargetDialog方法的實現,會發現其主要是呼叫對話方塊類DeprecatedTargetSdkVersionDialog,來彈出此對話方塊,並顯示提示。
這裡有一個問題,既然是在每個Activity啟動時會呼叫AppWarnings.java的onStartActivity方法, 那會不會每次開啟新Activity,都彈此對話方塊? 如果這樣,使用者體驗也會非常不好。
答案:不會的,這裡有一個小技巧,第一次彈出對話方塊後,使用者如果選擇“確定”,AMS會給此應用設定一個Flag標識:FLAG_HIDE_DEPRECATED_SDK。每次準備彈窗時,會先判斷此標識值是否為true,如果是,說明已經提示過使用者,無需再彈窗。程式碼如下:
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); // ... }
最後,結論如下:
Android P機型上,當應用的targetSdk版本低於17時,應用啟動時會彈窗“此應用專為舊版Android打造,因此可能無法正常執行。請嘗試檢查更新或與開發者聯絡”。標準值由ro.build.version.min_supported_target_sdk值設定的,一般預設是17
作者:kevin song,2019.1.23於南京建鄴區