Android14中《此应用专为旧版 Android 系统打造...》弹窗
问题
测试机升级到Android14后,当打开应用时,会出现一个弹窗,弹窗信息如下图:
刚开始点击确认之后,后面并不会出现也就没去管,然而,在我执行benchmark
的Startup测试的时候,每次都会提醒而影响测试。这事必须得解决。
原因
通过搜索,很多文章都提到一个方法showDeprecatedTargetDialogIfNeeded()
。可以根据这个方法展开去了解。
定位
这是一个简单的定位过程:
- 打开platform_frameworks_base这个仓库。
- 作为Android开发者,都知道硬编码的字符串是存在res目录下的strings.xml文件中,笔者系统默认英文,直接找默认的文件即可,目录为
platform_frameworks_base/core/res/res/values/strings.xml
,不同语言根据不同目录去找。 - 在strings.xml文件中找对对应字符串的那行
<string name="deprecated_target_sdk_message">This app was built for an older version...
,从而得知key为deprecated_target_sdk_message - 使用Github Command Palette查找key,找到对应使用的代码。搜索结果右边有个Paths的section可以看到只有一个是java代码的,点击它便可看到调用的代码。
- 这时候你应该看到
DeprecatedTargetSdkVersionDialog.java
文件了,双击该类名,右侧可以看到References(引用)
,点击调用方法进入对应代码块。 - 这时候你应该是在
AppWarnings.java
文件中,继续根据引用链,最后也一样找到showDeprecatedTargetDialogIfNeeded()
方法
为什么会出现这个弹窗
public void showDeprecatedTargetDialogIfNeeded(ActivityRecord r) {
if (r.info.applicationInfo.targetSdkVersion < Build.VERSION.MIN_SUPPORTED_TARGET_SDK_INT) {
mUiHandler.showDeprecatedTargetDialog(r);
}
}
根据applicationInfo.targetSdkVersion
和Build.VERSION.MIN_SUPPORTED_TARGET_SDK_INT
判断是否执行警告弹窗代码,那这两个玩意是什么呢?
// 来自
/**
* The minimum SDK version this application targets. It may run on earlier
* versions, but it knows how to work with any new behavior added at this
* version. Will be {@link android.os.Build.VERSION_CODES#CUR_DEVELOPMENT}
* if this is a development build and the app is targeting that. You should
* compare that this number is >= the SDK version number at which your
* behavior was introduced.
*/
public int targetSdkVersion;
// 来自Build.java
public static final int MIN_SUPPORTED_TARGET_SDK_INT = SystemProperties.getInt(
"ro.build.version.min_supported_target_sdk", 0);
注释很清楚,applicationInfo.targetSdkVersion
就是我们配置的min SDK。而MIN_SUPPORTED_TARGET_SDK_INT
是一个System配置中key为ro.build.version.min_supported_target_sdk
的属性,其中Android14中配置为28
ro.build.version.min_supported_target_sdk in line42
为什么只提醒一次
以下是两个相关代码块,注释部分则可以表示同一个包只会出现一次弹窗的原因
DeprecatedTargetSdkVersionDialog(final AppWarnings manager, Context context,
ApplicationInfo appInfo) {
super(manager, appInfo.packageName);
...
final CharSequence message = context.getString(R.string.deprecated_target_sdk_message);
final AlertDialog.Builder builder = new AlertDialog.Builder(context)
.setPositiveButton(R.string.ok, (dialog, which) ->
// 设置 package flag
manager.setPackageFlag(
mPackageName, AppWarnings.FLAG_HIDE_DEPRECATED_SDK, true))
.setMessage(message)
.setTitle(label);
...
}
@UiThread
private void showDeprecatedTargetSdkDialogUiThread(ActivityRecord ar) {
if (mDeprecatedTargetSdkVersionDialog != null) {
mDeprecatedTargetSdkVersionDialog.dismiss();
mDeprecatedTargetSdkVersionDialog = null;
}
// 根据package flag 判断是否弹出
if (ar != null && !hasPackageFlag(
ar.packageName, FLAG_HIDE_DEPRECATED_SDK)) {
mDeprecatedTargetSdkVersionDialog = new DeprecatedTargetSdkVersionDialog(
AppWarnings.this, mUiContext, ar.info.applicationInfo);
mDeprecatedTargetSdkVersionDialog.show();
}
}
解决问题
我们知道这个弹窗的流程并了解其判断条件了,解决问题自然简单,简单把我们min SDK改成28或更高就可以了。再执行benchmark测试,没有再出现这个弹窗,问题解决。