Android Min SDK版本与目标SDK版本


442

在为Android开发应用程序时,Min版本和Target SDK版本之间有什么区别?除非Min和Target版本相同,否则Eclipse不允许我创建新项目!


1
从我正在阅读的内容来看,听起来目标SDK版本对应用程序的编译方式没有影响。只是在告诉设备该应用程序正在运行,它不需要启用任何特殊的兼容性功能即可使您的应用程序正常运行。这是正确的吗?在我看来,直到您编译并进行了大量测试之后,您才知道目标SDK版本是什么。为什么编译器不能仅查看您的代码并弄清楚您的应用程序自身兼容哪些平台?
Michael Novello 2010年

5
上面的评论者误解了为什么使用targetSDK功能的原因。有关更多详细信息,请参见下面的答案。
史蒂夫·海利

157
接受的答案不正确。请阅读Steve H.的答案
tylerl

3
@tylerl但这并不是不正确,而是引用了Google Android文档。我还没有添加任何东西。
Vikas Patidar

3
我认为卡尔的答案是最详细,最精确的。
Ilya Kogan

Answers:


136

android:minSdkVersion

一个整数,指定运行应用程序所需的最低API级别。如果系统的API级别低于此属性中指定的值,则Android系统将阻止用户安装应用程序。您应该始终声明此属性。

android:targetSdkVersion

一个整数,指定应用程序要定位的API级别。

设置了此属性后,应用程序会说它能够在较旧的版本(最低至minSdkVersion)上运行,但经过了明确测试,可以与此处指定的版本一起使用。指定此目标版本可以使平台禁用目标版本不需要的兼容性设置(否则可以启用该功能以保持前向兼容性)或启用较旧的应用程序不可用的较新功能。这并不意味着您可以为平台的不同版本编程不同的功能,它只是告知平台您已经针对目标版本进行了测试,并且平台不应执行任何额外的工作来维持与目标版本的前向兼容性。

有关更多信息,请参考以下URL:

http://developer.android.com/guide/topics/manifest/uses-sdk-element.html


总的来说,您将把两者都设置为同一件事。将它们设置为不同的值可能是不寻常的情况。
jjb 2010年

66
关于jjb的评论:我不同意。为什么有不同的minSDK和targetSDK有很多充分的理由。请参阅我的答案以获取更多详细信息。
史蒂夫·海利

871

OP对该问题发表的评论(基本上表明targetSDK不会影响应用的编译)完全是错误的!抱歉,直白了。

简而言之,这里的目的是声明与minSDK不同的targetSDK:这意味着您使用的是更高级别的SDK中的功能,而不是最低级别的SDK,但是您已确保向后兼容。换句话说,假设您要使用的功能是最近才引入的,但对您的应用程序并不重要。然后,您可以将targetSDK设置为引入此新功能的版本,并将最低值设置为较低的值,以便每个人仍然可以使用您的应用程序。

举个例子,假设您正在编写一个广泛使用手势检测的应用程序。但是,手势可以识别的每个命令也可以通过按钮或菜单来完成。在这种情况下,手势是“很酷的附加功能”,但不是必需的。因此,您可以将目标sdk设置为7(引入了GestureDetection库时为“ Eclair”),将minimumSDK设置为3级(“ Cupcake”),这样即使是拥有旧手机的人也可以使用您的应用。您要做的就是确保您的应用在尝试使用手势库之前检查了其运行的Android版本,以避免在不存在的情况下尝试使用它。(不可否认,这是一个过时的示例,因为几乎没有人仍然拥有v1.5手机,但是有一段时间需要保持与v1的兼容性。

再举一个例子,如果您想使用Gingerbread或Honeycomb的功能,可以使用它。有些人很快就会获得更新,但是其他人,尤其是使用较旧的硬件的人,可能会在购买新设备之前坚持使用Eclair。这将使您能够使用一些很酷的新功能,但又不排除您可能的市场的一部分。

Android开发人员博客中有一篇非常不错的文章内容涉及如何使用此功能,尤其是我上面提到的如何设计“在使用前检查该功能是否存在”代码。

给OP:我写这篇文章主要是为了将来碰巧遇到这个问题的任何人的利益,因为我意识到您的问题是很久以前提出的。


2
您能否提供准确的解释,说明targetSDKversion如何影响应用程序的编译?因为编译版本还是您需要设置的另一种配置。在此先感谢您
hnviet 2011年

9
我认为Steve在清单xml属性android:targetSdkVersion(没有确切的说法)与驻留在project.properties文件中的target属性之间感到困惑,该属性代表应该编译什么代码。我再说一遍,xml attr targetSdkVersion没有真正的含义!!!
2012年

3
@kilaka您的评论有一半是有效的,但另一半是错误的。我假设某人在XML和project.properties中使用了相同的值(也可以通过在Eclipse中右键单击-> properties访问),所以您正确地指出他们存储在不同的位置。但是,Android Market无疑会关心您在xml属性targetSdkVersion中输入的值。例如,它在确定是否应为Honeycomb及更高版本的应用程序使用ActionBar或兼容性菜单时使用。
史蒂夫·海利

2
@Nate我无法说出这种“复杂代码”使运行时变慢多少,但我确实认为,就代码复杂性而言,拆分和使用多个APK更为糟糕。现在,您必须记住在进行每个导出之前,注释掉/注释掉或合并源代码管理中的更多分支。在去年10月举行的一次Android会议上,他们说他们推出了多APK系统作为一种让步,但很高兴很少有人在使用它。
史蒂夫·海利2012年

2
但是处理多个版本是版本控制系统的主要作用。这就是开发人员所熟悉的(大多数软件(无论是否为移动设备)针对不同平台发布的版本都略有不同)。这个Android的“功能”并没有降低复杂性。它只是将其推送到正在运行的应用程序中,并且正如该线程所证明的那样,造成了混乱。当然,谷歌将为很少有人使用它而感到高兴……这有助于他们说:“瞧瞧,我们一开始就忽略了这一点是正确的”。另外,有些人不使用它,因为他们还不知道它的存在。
Nate 2012年

97

当您设置targetSdkVersion =“ xx”时,即表示您的应用在API级别xx正常运行(例如,已经过全面且成功的测试)。

在xx 以上的API级别运行的Android版本将自动应用兼容性代码,以支持您可能依赖的任何功能,这些功能可能在API xx级别或之前可用,但现在在该Android版本的更高级别已过时。

相反,如果您正在使用 xx级或之前已过时的任何功能,则更高版本的API级别(不再包含这些功能)的OS版本将不会自动应用兼容性代码来支持这些用途。在这种情况下,您自己的代码必须有特殊情况的条款该测试的API级别,如果操作系统级检测是一个较高的不再具有给定的API功能,您的代码必须使用备用功能可在运行OS的API级别。

如果执行此操作失败,则可能根本不会出现通常会触发代码内事件的某些界面功能,并且您可能会缺少用户需要触发这些事件并访问其功能的关键界面功能(例如下面的示例)。

如其他答案所述,如果您想使用最初以比minSdkVersion更高的API级别定义的某些API功能,并且可以采取措施确保您的代码可以检测并处理这些功能的缺失,则可以将targetSdkVersion设置为高于minSdkVersion。低于targetSdkVersion的级别。

为了警告开发人员专门测试使用功能所需的最低API级别,如果代码包含对在minSdkVersion之后的API级别定义的任何方法的调用,编译器将发出错误(不仅仅是警告),即使targetSdkVersion大于或等于该方法首次可用的API级别。要消除此错误,编译器指令

@TargetApi(nn)

告诉编译器该指令范围内的代码(将在方法或类之前)已编写为在调用至少依赖于该API级别的任何方法之前测试API级别至少为nn 。例如,以下代码定义了可从minSdkVersion小于11且targetSdkVersion为11或更高的应用程序中的代码调用的方法:

@TargetApi(11)
    public void refreshActionBarIfApi11OrHigher() {
      //If the API is 11 or higher, set up the actionBar and display it
      if(Build.VERSION.SDK_INT >= 11) {
        //ActionBar only exists at API level 11 or higher
        ActionBar actionBar = getActionBar();

        //This should cause onPrepareOptionsMenu() to be called.
        // In versions of the API prior to 11, this only occurred when the user pressed 
        // the dedicated menu button, but at level 11 and above, the action bar is 
        // typically displayed continuously and so you will need to call this
        // each time the options on your menu change.
        invalidateOptionsMenu();

        //Show the bar
        actionBar.show();
    }
}

你可能想声明更高targetSdkVersion如果你已经在这个更高的水平测试,一切正常,即使你使用从API级别的任何功能比你的minSdkVersion高。这仅仅是为了避免访问旨在从目标级别降至最低级别的兼容性代码的开销,因为您已经(通过测试)确认不需要进行此类修改。

取决于已声明的targetSdkVersion的UI功能的一个示例是,当那些应用程序在API 11或更高版本下运行时,出现在具有小于11的应用程序状态栏上的三个垂直点菜单按钮。如果您的应用程序的targetSdkVersion为10或更低,则假定您的应用程序的界面取决于专用菜单按钮的存在,因此三点按钮似乎代替了较早的专用硬件和/或屏幕版本当OS具有更高的API级别(不再假定设备上的专用菜单按钮)时,该按钮的大小(例如,在Gingerbread中看到)。但是,如果您将应用程序的targetSdkVersion设置为11或更高,则假定您已利用在该级别引入的功能代替了专用菜单按钮(例如 (例如操作栏),或者您已经避免了使用系统菜单按钮的需要;因此,三垂直点菜单“兼容性按钮”消失了。在这种情况下,如果用户找不到菜单按钮,则无法按菜单按钮,这又意味着您的活动的onCreateOptionsMenu(menu)覆盖可能永远不会被调用,这又意味着您的应用功能的很大一部分可能会被剥夺其用户界面。当然,除非您已经实现了操作栏或其他供用户访问这些功能的替代方法。找不到菜单按钮,她无法按该按钮,这又意味着您的活动的onCreateOptionsMenu(menu)覆盖可能永远不会被调用,这又意味着您的应用功能的重要部分可能是失去了其用户界面。当然,除非您已经实现了操作栏或其他供用户访问这些功能的替代方法。找不到菜单按钮,她无法按该按钮,这又意味着您的活动的onCreateOptionsMenu(menu)覆盖可能永远不会被调用,这又意味着您的应用功能的重要部分可能是失去了其用户界面。当然,除非您已经实现了操作栏或其他供用户访问这些功能的替代方法。

相比之下,minSdkVersion声明了设备的OS版本必须至少具有该API级别才能运行您的应用程序。这会影响当它们在Google Play应用商店(以及其他应用商店)中时,哪些设备能够查看和下载您的应用。这是一种说明您的应用程序依赖于在该级别上建立的OS(API或其他)功能的方式,而对于没有这些功能的情况没有可接受的方式。

使用的minSdkVersion,以确保这是一个特征的存在的例子并不 API相关的将是的minSdkVersion为了设置为8,以确保您的应用程序将只在Dalvik解释的启用JIT版本上运行(因为JIT介绍到API级别8的Android解释器)。由于启用JIT的解释器的性能可能是缺少该功能的解释器的五倍,因此,如果您的应用大量使用处理器,那么您可能需要API级8或更高级别,以确保足够的性能。


感谢您提供有关使用TargetApi指令的说明。
samir105 '16

@Carl是否意味着我总是可以将targetSdkVersion设置为高于minSdkVersion的任何版本(特别是获得那些UI增强),而无需进行任何测试(本身),只要我限制我的代码库只使用minSdkVersion中可用的API ?
Damilola Olowookere

Olowookere Emmanuel:如果我对您的理解正确,那么不,那并不意味着那样。我的回答是:“如果您使用的任何功能在xx级别或之前已过时,兼容性代码将不会在更高API级别的操作系统版本中自动应用。” 因此,如果您的代码使用的功能在API级别8中可用,而该功能在级别10时已过时,那么如果将targetSdkVersion提升到10以上,则将没有兼容代码可用于调整对该功能已升级到新的操作系统级别。
卡尔

(续):而如果您将targetSdkVersion保留在第8级,则虽然您将无法使用在更高级别引入的功能,但是将应用兼容代码,以允许您在运行时使用第8级功能更高的操作系统级别。
卡尔

(继续):这样考虑:假设您在可用的最高Android级别为8时编写了一些代码,并且将targetSdkVersion设置为8(因为当时是最高级别)。现在,出现了一些新版本的Android,并且您使用的某些第8级功能不可用。仍然拥有旧APK的用户应该不会遇到错误,对吗?因此,为确保它们不会,兼容性代码将自动应用,以调整旧的API调用,以在用户运行较新版本的OS时调用它们时做一些合理的事情。
卡尔

50

始终可以通过示例更好地实现一个概念。在阅读了Android开发人员源代码和相关的stackoverflow线程中的所有文档之后,直到我深入研究Android框架源代码并进行一些实验之前,我都难以理解这些概念。我将分享两个例子,这些例子对我完全理解这些概念很有帮助。

一个DatePickerDialog将根据你把在AndroidManifest.xml文件的targetSDKversion(水平会有所不同<uses-sdk android:targetSdkVersion="INTEGER_VALUE"/>)。如果将值设置为10或更低,则DatePickerDialog将看起来像左图。另一方面,如果将值设置为11或更高,则DatePickerDialog将看起来与正确的代码相同

使用targetSDKversion 10或更低版本的DatePickerDialog外观 使用targetSDKversion 11或更高版本的DatePickerDialog外观

我用来创建此示例的代码非常简单。MainActivity.java看起来:

public class MainActivity extends Activity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
    }

    public void onClickButton(View v) {
        DatePickerDialog d = new DatePickerDialog(this, null, 2014, 5, 4);
        d.show();       
    }
}

activity_main.xml看起来:

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent" >
<Button
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:onClick="onClickButton"
    android:text="Button" />
</RelativeLayout>


而已。实际上,这就是我需要测试的每个代码。

当您看到Android框架源代码时,这种外观上的变化非常明显。它像:

public DatePickerDialog(Context context,
    OnDateSetListener callBack,
    int year,
    int monthOfYear,
    int dayOfMonth,
    boolean yearOptional) {
        this(context, context.getApplicationInfo().targetSdkVersion >= Build.VERSION_CODES.HONEYCOMB
                ? com.android.internal.R.style.Theme_Holo_Light_Dialog_Alert
                : com.android.internal.R.style.Theme_Dialog_Alert,
        callBack, year, monthOfYear, dayOfMonth, yearOptional);
}

如您所见,该框架获取当前的targetSDKversion并设置了不同的主题。这种代码段(getApplicationInfo().targetSdkVersion >= SOME_VERSION)可以在Android框架中找到。

另一个示例是有关WebView类的。Webview类的公共方法应该在主线程上调用,否则RuntimeException,当您将targetSDKversion设置为18或更高时,运行时系统将抛出。此行为可以通过其源代码清楚地实现。就是这样写的。

sEnforceThreadChecking = context.getApplicationInfo().targetSdkVersion >=
            Build.VERSION_CODES.JELLY_BEAN_MR2;

if (sEnforceThreadChecking) {
    throw new RuntimeException(throwable);
}


Android文档说:“ 随着Android随着每个新版本的发展,某些行为甚至外观可能会发生变化。” 因此,我们研究了行为和外观的变化,以及变化是如何实现的。

总之,Android文档说:“ 此属性(targetSdkVersion)通知系统您已经针对目标版本进行了测试,并且系统不应启用任何兼容性行为以维持应用程序与目标版本的前向兼容性。 ”。对于WebView情况,这确实很清楚。直到释放JELLY_BEAN_MR2以在非主线程上调用WebView类的公共方法,这是可以的。如果Android框架在JELLY_BEAN_MR2设备上引发RuntimeException,这是胡说八道。它只是不应出于自己的兴趣启用新引入的行为,否则会导致致命的后果。因此,我们要做的是检查某些targetSDK版本上的一切是否正常。通过设置更高的targetSDKversion,我们可以获得诸如外观增强之类的好处,

编辑:免责声明。DatePickerDialog构造函数基于当前的targetSDKversion(如上所述)设置了不同的主题,实际上在以后的commit中已更改。尽管如此,我还是使用了该示例,因为逻辑没有更改,并且这些代码段清楚地显示了targetSDKversion概念。


2
“通过设置更高的targetSDKversion,我们可以获得诸如外观增强之类的好处,但这是责任。” 如果他们在文档中提到了这一行,我就不会在寻找它。
pulp_fiction

@김준호我有两个问题:1.)在上面的日期选择器示例中,如果将targetSdkVersion设置为10或更低,并在运行最新Android(例如API 22)的设备上运行该应用,日期选择器仍会像旧版本一样显示在左图上?2.)这是否意味着我可以始终将targetSdkVersion设置为高于minSdkVersion的任何版本(例如,从更高的API获得UI增强功能,例如清晰的日期选择器),而无需进行任何测试(本身),只要我限制我的代码库即可只使用minSdkVersion中可用的API?
Damilola Olowookere

@Olowookere 1)是的。只是运行它。2)如果目标版本高于minSDKVersion,则可以将targetSDKVersion设置为任何所需的版本。但是您仍然需要测试它是否可以在目标版本上正常运行。无论您是否坚持使用minSDKVersion api,都没有关系。考虑一下DatePicker示例。
김 준 호

考虑一下您将最小版本14和目标sdk版本设置为16的情况,而您只使用了14或更低版本的api。假设您使用了API级别1中引入的TextView。会发生什么?
김 준 호

@김준호谢谢。但是对于您的第二个答案,我感到困惑。如果我的代码仅在minSdkVersion中使用API​​,而我的目标是更高的SDK,为什么需要测试?考虑一下DatePicker示例,高targetSdkVersion仅改善了DatePicker小部件的外观,并且没有任何中断,因为我没有在API中使用任何高于minSdkVersion的代码。我只想要更高的targetSdkVersion,因为我想要小部件的新外观,而不是我想要使用在更高的API中引入的新功能
Damilola Olowookere

21

对于那些想要总结的人,

android:minSdkVersion

是最低版本,直到您的应用程序支持为止。如果您的设备具有较低版本的android,则不会安装该应用。

而,

android:targetSdkVersion

是应用程序设计要运行的API级别。意味着,您的手机系统无需使用任何兼容性行为即可保持向前兼容性,因为您对此API进行了测试。

您的应用仍将在高于指定版本的Android版本上运行,targetSdkVersion但将启动android兼容性行为。

赠品 -

android:maxSdkVersion

如果您设备的API版本更高,则不会安装该应用。就是 这是允许您安装应用程序的最大API。

即。对于MinSDK -4,maxSDK-8,targetSDK-8我的应用程序最低可运行1.6,但我也使用了仅在2.2中受支持的功能,如果将其安装在2.2设备上,则可见。此外,对于maxSDK-8,该应用程序将无法在使用API​​> 8的手机上安装。

在撰写此答案时,Android文档在解释它方面做得并不出色。现在已经很好地解释了。在这里检查


“是您的应用继承功能的最高版本。” :这是错误的。这是您的应用继承功能的最低版本-即第一个版本,其中包含您的应用所使用的必需功能。
RichieHH

英语是棘手的语言。阅读答案中给出的示例。我认为我在那里有意义。:)
达潘(Darpan)2014年

我不是在书呆子,英语是该组的支持语言。棘手或不说其“该应用程序支持功能的最大版本”不仅是错误的:完全180度错误。它是FIRST或最低版本,可在不使用后备兼容模式/库的情况下支持应用程序的所有预期功能。
RichieHH 2014年

9

例如,如果遇到一些编译错误:

<uses-sdk
            android:minSdkVersion="10"
            android:targetSdkVersion="15" />

private void methodThatRequiresAPI11() {
        BitmapFactory.Options options = new BitmapFactory.Options();
                options.inPreferredConfig = Config.ARGB_8888;  // API Level 1          
                options.inSampleSize = 8;    // API Level 1
                options.inBitmap = bitmap;   // **API Level 11**
        //...
    }

您得到编译错误:

字段需要API级别11(当前最小值为10):android.graphics.BitmapFactory $ Options#inBitmap

自Android开发工具(ADT)版本17开始,有一个新的非常有用的注释@TargetApi可以非常轻松地解决此问题。将其添加到包含有问题的声明的方法之前:

@TargetApi
private void methodThatRequiresAPI11() {            
  BitmapFactory.Options options = new BitmapFactory.Options();
      options.inPreferredConfig = Config.ARGB_8888;  // API Level 1          
      options.inSampleSize = 8;    // API Level 1

      // This will avoid exception NoSuchFieldError (or NoSuchMethodError) at runtime. 
      if (Integer.valueOf(android.os.Build.VERSION.SDK) >= android.os.Build.VERSION_CODES.HONEYCOMB) {
        options.inBitmap = bitmap;   // **API Level 11**
            //...
      }
    }

现在没有编译错误,它将运行!

编辑:这将导致API级别低于11的运行时错误。在11或更高版本上,它将运行没有问题。因此,您必须确保在受版本检查保护的执行路径上调用此方法。TargetApi仅允许您对其进行编译,但运行风险自负。


1
我对此感到困惑。如果稍后在带有sdk 10的系统中运行您的应用程序会怎样?
Fran Marzoa 2012年

它将输出options.inBitmap语句和应用程序应该可以正常工作。
NinjaCoder 2014年

1

android:minSdkVersionandroid:targetSdkVersion两者都是我们需要在Android清单文件中声明,但两者都具有不同特性的整数值。

android:minSdkVersion:这是运行android应用所需的最低API级别。如果我们在较低的API版本上安装相同的应用程序,则会出现解析器错误,并且会出现应用程序不支持的问题。

android:targetSdkVersion:目标SDK版本用于设置应用程序的目标API级别。如果未在清单中声明此属性,则minSdk版本将为您的TargetSdk版本。“在我们声明为TargetSdk版本的所有更高版本的API上的应用程序支持安装”始终是正确的。为了使应用程序成为受限目标,我们需要在清单文件中声明maxSdkVersion ...


0

如果您制作的应用程序需要危险的权限,并将targetSDK设置为23或更高,则应小心。如果不检查运行时的权限,则将获得SecurityException,并且如果您在try块中使用代码(例如打开的摄像头),则不检查logcat可能很难检测到错误。


By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.