Android:目标SDK大于BuildTarget的后果

18

我想了解 targetSDK > buildTarget 的后果。

我最近观察到,如果我保持 buildTarget=16targetSDK=17,我的平板电脑上的选项卡(运行4.1.1,API 级别为 16)将移动到 actionBar 的中心。我无法理性化这种行为。有人能够解释一下为什么会发生这种情况吗?

2个回答

13

很不错的问题!我以前也遇到过类似的情况,当buildTarget和targetSDK有所不同时。花了一些时间才搞清楚,但我会尝试总结我的理解。

你必须区分三个重要的值:

  1. minSdkVersion

    这是应用程序将(或应该!)运行的最低可用版本。在安装.apk文件到Android时,该值将被检查,如果你运行的Android版本低于指定的版本,则不会安装。

  2. buildTarget

    这是应用程序的.apk将编译的SDK(Eclipse也将针对该值进行检查以检查编译错误)。如果buildTarget高于minSdkVersion,即使您的Android版本不支持所有方法,您仍然可以安装该应用程序。默认情况下,它设置为您SDK中可用的最新Android版本。您仍然可以构建支持较旧版本的应用程序,但将构建目标设置为最新版本允许您启用新功能并优化您的应用程序以获得最佳用户体验。

    您需要检查您是否使用的方法在低API级别下运行时是否存在,否则应用程序可能会崩溃!

  3. targetSdkVersion

    targetSdkVersion 指定应用应该在哪个SDK平台上运行良好。因此,如果您针对API 17进行了测试,则可以将API 17添加为targetSdkVersion。如果使用的是Android版本>targetSdkVersion,则Android系统将进入某种前向兼容模式,以确保支持应用程序。输入此兼容性行为将确保您的应用程序继续按照您的期望工作,因为在不同的API级别之间可能会有一些行为变化(这里是一些最重要的变化)。因此,为较低的API级别开发的任何应用程序都将能够在较高版本上运行,因为旧的行为(如过时值)可能在兼容性模式中被“模拟”。
    例如: 如果您将targetSdkVersion设置为HONEYCOMB(API 11),默认主题将更改为Theme_Holo(即黑色全息UI)。将targetSdkVersion设置为较低的值将影响系统保持默认的浅色主题,无论使用哪个构建API!
    在您的情况下,似乎在API 16和17之间没有许多明显的变化,这应该不会影响设计更改,但我猜想,更高的targetSdkVersion将在编译时引起一些附加变化(例如包括额外的类,主题,值等),这将导致不同的行为,就像上面的主题示例一样。
    希望这有助于您解决奇怪的行为。在Android开发者文档中还有更多相关信息可供阅读。
    PS:存在某种前后向混乱现象:Android系统具有向后兼容性,以确保Android应用程序的前向兼容性。这意味着:如果通过OTA更新Android版本等,所有旧的应用程序应该仍然运行(因此它们将保持向前兼容)。

如果我正确理解了文档,当android version > targetSDK时,将启用向前兼容性(在您的术语中,系统进入向前兼容性),而当android version <= targetSDK时,将禁用向前兼容性并使用该平台上可用的本机API。这与您的观点(在3. targetSDK下)直接矛盾。 - 500865
感谢您的提醒。您是完全正确的。我修改和改进了我的答案,因为在写作时我陷入了某种“前后混乱”的状态。我希望现在它更好了,应该能够回答您的问题。很抱歉,没有“具体”的答案可以解释ActionBar的确切行为为什么像您描述的那样,但这应该是API更改的影响(就像LTR <-> RTL返回值更改一样),这将通过使用更高的目标SDK版本来包含。我对此非常感兴趣,因为这确实是一个非常有趣的问题! - ConcurrentHashMap

2
构建目标是用于应用程序开发的,目标 SDK 是用于应用程序兼容性的。
构建目标指定您在实现应用程序时可以访问哪些 API。例如,如果将构建目标设置为 Android API 级别 10,则就您的代码而言,没有 ActionBar 这样的东西。您在开发期间使用的 API 只是 Android 的存根实现,因此必须通过仿真或在实际设备上运行。因此,构建目标定义了您正在使用的 Android 接口(对于编译器和 IDE)。一旦编译完成,基于构建目标不应有任何差异(Android 系统看不到构建目标,它是一个编译时标志)。这是您与 Android 编译器(和您的 IDE)之间的严格合同,定义了您能够在应用程序中使用哪些 Android 组件;如果尝试使用超出设置为构建目标的 Android 版本的内容,则会出现编译错误。
目标SDK是您与Android系统签署的合同,保证您的应用程序已准备好从最低SDK到目标SDK(有效的最大SDK,因为通常应避免使用最大SDK设置)正常工作。我相信有一些东西无法进行向前兼容,比如一些安全更改(可能来自于应用程序开发之外并且是系统范围内的更改)。这个合同是一份协议,意味着您已经采取措施确保您的应用程序在该范围内处理Android API中的任何更改,以便在所有情况下提供您期望的行为。合同的另一端来自于Android系统,它同意使用不超过您的目标SDK的Android实现,即使在运行更高版本Android的设备上(这不包括我之前提到的少数更改)。
关于向前兼容性的说明意味着您的构建目标应始终至少与您的目标SDK匹配。您说您已经测试了您的应用程序在目标SDK上运行,那么为什么要针对较低的API级别构建它呢?
实际生活中构建目标和目标SDK的示例: ActionBarSherlock提供向后兼容的操作栏。以下是使用该库的要求摘录。
这段文字的第一段表明需要使用 Android 4.0(API 级别14)来构建库,而您的项目应该尽可能使用最新版本的 SDK,只要它是 4.0 或更高版本。第二段说明需要以 API 级别 11 或更高级别为目标,因为这将导致 Android 在较新的设备上自动添加本机操作栏。由于您将编译新的 API,但您的应用程序可能在旧版 Android 设备上运行,因此必须特别小心地避免使用或正确检查和调用在您的最低 SDK 版本之后引入的任何方法。

第一段文字显示需要一个包含 4.0 ActionBar API 的构建目标,因为库使用它并且没有它无法编译。第二段文字显示需要一个包含 3.0 ActionBar API 的目标 SDK,因为库在这些设备上使用本机 ActionBar,但如果您的目标 SDK 低于 3.0,则 Android 系统不会提供 ActionBar,因为这告诉它不要使用比目标更高的任何内容(例如 3.0 ActionBar)。

一些参考:

构建目标

目标 SDK


我并没有真正理解语句“一旦编译,基于构建目标不应有任何差异”。但是最后一句话对我来说很有意义:“...你已经测试了你的应用程序在目标SDK上运行,那么为什么要针对较低的API级别构建它呢?” - 500865
@500865 构建目标是编译时的标志,应用程序编译后它就不存在了,只有IDE和编译器能看到构建目标标志,因此它只影响开发过程中可以使用的代码。而目标SDK是运行时标志,Android系统会看到它,并用于影响Android系统在运行您的应用程序时选择使用哪些代码。 - Dandre Allison
@nlsbshtr 你搞反了。你不应该将它设置得比你的targetSDK更高,Lint会帮助你提醒当你使用一个比你的minSDK更高的API时,以便你可以确保它只在支持该API的设备上使用。如果你将它设置为你的minSDK,那么你永远无法使用不存在的新API。谁建议你这样做?这就是Build.VERSION.SDK_INT(版本门控)的全部原因。 - Dandre Allison
@nlsbshtr 请查看ActionBarSherlock的常见问题解答,网址为http://actionbarsherlock.com/faq.html。它提供了对ActionBar的向后兼容性支持,但为了使其正常工作,您必须构建在API 14+和targetSDK 11+的基础之上。这是一个在广泛使用且备受尊重的库中的明显例子。 - Dandre Allison
@500865 我已经更新了我的答案,加入了ActionBarSherlock的示例,希望能够更清楚地解决疑惑。 - Dandre Allison

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接