在Android10.0中运行应用会提示“此应用专为旧版Android打造,可能无法正常运行,请尝试更新或与开发者联系”。
为什么在Android10.0会出现这个提示,而在低版本中却没有呐?
我们可以在官方网站中的Android10.0版本中的影响应用的行为变更中找到答案。
可以看出是项目中配置targetSdkVersion的影响。那么什么是targetSdkVersion。
一个用于指定应用的目标 API 级别的整数。如果未设置,其默认值与为 minSdkVersion 指定的值相等。
该属性用于通知系统,您已针对目标版本进行测试,并且系统不应通过启用任何兼容性行为,以保持您的应用与目标版本的向前兼容性。应用仍可在较低版本上运行(最低版本为 minSdkVersion)。
Android 会随新版本的推出而逐渐发展,在此过程中,某些行为乃至外观可能会发生变化。不过,如果平台的 API 级别高于应用 targetSdkVersion 所声明的版本,系统便可通过启用兼容性行为,确保应用继续以您所期望的方式工作。您可以将 targetSdkVersion 指定为符合应用所运行平台的 API 级别,从而停用此类兼容性行为。例如,如果将该值设置为“11”或更高,系统便可在应用运行在 Android 3.0 或更高版本的平台上时对其应用新的默认主题 (Holo),还可在应用运行在更大屏幕上时停用屏幕兼容性模式(因为对 API 级别 11 的支持隐含了对更大屏幕的支持)。
系统可根据您为该属性设置的值启用许多兼容性行为。Build.VERSION_CODES 参考资料中的相应平台版本介绍了其中几种行为。
如要让应用与各 Android 版本保持同步,您应增加该属性的值,使其与最新 API 级别一致,然后在相应平台版本上对应用进行全面测试。
AppWarnings.java,在onStartActivity会检测targetSdkVersion,如果小于系统的支持最小的目标版本,则弹出提示框。代码块如下:
/**
* 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 在Android10.0的时候是等于多少呐?继续跟源码
/**
* The current lowest supported value of app target SDK. Applications targeting
* lower values may not function on devices running this SDK version. Its possible
* values are defined in {@link Build.VERSION_CODES}.
*
* @hide
*/
public static final int MIN_SUPPORTED_TARGET_SDK_INT = SystemProperties.getInt(
"ro.build.version.min_supported_target_sdk", 0);
这是个隐藏属性,android9.0开始限制@hide方法的使用,即使是用反射也无法使用hide方法。
获取的代码块如下:
public static String getSystemProperty(String propName) {
String line;
BufferedReader input = null;
try {
Process p = Runtime.getRuntime().exec("getprop " + propName);
input = new BufferedReader(new InputStreamReader(p.getInputStream()), 1024);
line = input.readLine();
input.close();
} catch (IOException ex) {
Log.d(TAG, "Unable to read sysprop " + propName, ex);
return null;
} finally {
if (input != null) {
try {
input.close();
} catch (IOException e) {
Log.d(TAG, "Exception while closing InputStream", e);
}
}
}
return line;
}
使用方法:
String targetValue = getSystemProperty("ro.build.version.min_supported_target_sdk");
在Android10.0获取到的是23,那么设置项目中targetSdkVersion大于等于23就可以了。但是需要添加动态权限申请。在此有个取巧的方法,targetSdkVersion低的在高版本运行时,系统会默认弹出权限申请框,我们可以根据这个弹框,在项目入口动态的申请这些权限。
特别注意:targetSdkVersion设置需谨慎,一旦发布了targetSdkVersion高的,再发布低targetSdkVersion的,应用无法实现覆盖安装。安装失败后提示应用未安装(三星s8手机)。