Android最小SDK版本vs目标SDK版本

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

207294 次浏览

android: minSdkVersion

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

android: targetSdkVersion

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

有了这个属性设置,应用程序表示它能够在旧版本(直到minSdkVersion)上运行,但是显式地测试它是否可以使用这里指定的版本。指定此目标版本允许平台禁用目标版本不需要的兼容性设置(为了保持向前兼容性,可能会打开目标版本)或启用旧应用程序不可用的新特性。这并不意味着您可以为不同版本的平台编写不同的特性—它只是通知平台您已经针对目标版本进行了测试,并且平台不应该执行任何额外的工作来保持与目标版本的向前兼容性。

更多信息请参考这个URL:

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

OP对这个问题的评论(基本上是说targetSDK不会影响应用程序的编译)是完全错误的!很抱歉我这么直率。

简而言之,这就是从minSDK声明不同的targetSDK的目的:这意味着你正在使用来自更高级别SDK的特性,而不是你的最低级别,但你有确保向后兼容。换句话说,假设您想要使用一个最近才引入的特性,但它对您的应用程序并不重要。然后将targetSDK设置为引入该新特性的版本,并将minimum设置为更低的版本,以便每个人仍然可以使用您的应用程序。

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

再举一个例子,如果你想使用Gingerbread或Honeycomb的特性,你可以使用这个。一些人很快就会得到更新,但许多人,尤其是使用较老硬件的人,可能会继续使用Eclair,直到他们购买新设备。这将允许你使用一些很酷的新功能,但不会排除部分可能的市场。

Android开发者博客中有一篇关于如何使用此特性的非常好的文章,特别是如何设计我上面提到的“在使用该特性之前检查它是否存在”的代码。

致OP:我写这篇文章主要是为了让将来偶然遇到这个问题的人受益,因为我意识到你的问题很久以前就被问过了。

对于那些想要总结的人,

android:minSdkVersion

是应用程序支持的最低版本。如果您的设备是低版本的android,应用程序将无法安装。

同时,

android:targetSdkVersion

是API级别,直到你的应用程序被设计运行。这意味着,你的手机系统不需要使用任何兼容性行为来保持向前兼容性,因为你已经测试了这个API。

你的应用仍然会运行在高于targetSdkVersion的Android版本上,但Android兼容性行为会开始。

免费的东西- - - - - -

android:maxSdkVersion

如果你的设备的API版本更高,应用程序将无法安装。Ie。这是你允许你的应用程序安装的最大API。

ie。对于MinSDK -4, maxSDK - 8, targetSDK - 8我的应用程序至少在1.6上工作,但我也使用了仅在2.2中支持的功能,如果安装在2.2设备上,这些功能将可见。此外,对于maxSDK - 8,这个应用程序将不会安装在使用API > 8的手机上。

在我写这个答案的时候,Android文档并没有很好地解释这个问题。现在已经解释得很清楚了。点击这里查看

当你设置targetSdkVersion="xx"时,你是在证明你的应用程序在API级别xx上正常工作(例如,已经彻底和成功地测试了)。

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

相反,如果你正在使用任何已经过时的之前到xx级别的功能,兼容性代码将被更高API级别(不再包括这些功能)的操作系统版本自动应用,以支持这些用途。在这种情况下,你自己的代码必须有特殊情况子句来测试API级别,如果检测到的操作系统级别更高,不再具有给定的API特性,你的代码必须使用运行的操作系统API级别可用的替代特性。

如果它没有做到这一点,那么一些通常会在代码中触发事件的接口特性可能就不会出现,并且您可能会缺少用户触发这些事件并访问其功能所需的关键接口特性(如下面的示例所示)。

正如在其他回答中所述,如果您想使用一些最初定义在比您的minSdkVersion更高API级别上的API特性,并且已经采取步骤确保您的代码可以检测和处理在比targetSdkVersion更低级别上缺乏这些特性,则可以将targetSdkVersion设置为高于minSdkVersion。

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

@TargetApi(nn)

告诉编译器,该指令范围内的代码(在方法或类之前)已经被编写为在调用任何依赖于至少具有该API级别的方法之前测试至少nn的API级别。例如,下面的代码定义了一个方法,可以从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,如果你已经在那个更高的级别上进行了测试并且一切正常,即使你是使用任何来自高于你的minSdkVersion的API级别的特性。这只是为了避免访问旨在从目标级别调整到最小级别的兼容性代码的开销,因为您已经确认(通过测试)不需要这样的调整。

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

相比之下,minSdkVersion声明要求设备的操作系统版本至少具有该API级别才能运行应用程序。这影响哪些设备能够在谷歌Play应用程序商店(也可能是其他应用程序商店)上看到和下载应用程序。这是一种说法,说明你的应用程序依赖于OS (API或其他)的功能,建立在该级别,并没有一个可接受的方式来处理这些功能的缺失。

使用minSdkVersion来确保存在与 API相关的特性的一个例子是,将minSdkVersion设置为8,以确保你的应用程序只运行在支持JIT的Dalvik解释器版本上(因为JIT是在API级别8引入到Android解释器的)。由于启用JIT的解释器的性能可能是没有该特性的解释器的5倍,如果你的应用程序大量使用处理器,那么你可能需要API级别8或更高,以确保足够的性能。

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

<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选项#美元inBitmap < / p >

自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**
//...
}
}

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

EDIT:这将导致API级别低于11的运行时错误。在11或更高版本上,它运行起来没有问题。因此,必须确保在版本检查保护的执行路径上调用此方法。TargetApi只允许你编译它,但是你要自担风险。

一个概念可以用例子更好地表达,总是。我在理解这些概念时遇到了麻烦,直到我深入研究了Android框架源代码,并做了一些实验,甚至在阅读了Android开发人员网站上的所有文档之后。相关stackoverflow线程。我将分享两个例子,它们帮助我充分理解这些概念。

根据你在AndroidManifest.xml文件的targetSDKversion(<uses-sdk android:targetSdkVersion="INTEGER_VALUE"/>)中放入的级别,DatePickerDialog看起来会有所不同。如果您将值设置为10或更低,您的DatePickerDialog将看起来像左边。另一方面,如果你设置值11或更高,DatePickerDialog将看起来像与非常相同的代码

DatePickerDialog look with targetSDKversion 10或更低 DatePickerDialog look with targetSDKversion 11或更高

我用来创建这个示例的代码非常简单。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>
< p > < br > 就是这样。这是我需要测试的所有代码。< / p > 当你看到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类的公共方法应该在主线程上调用,如果没有调用,当你设置targetSDKversion 18或更高版本时,运行时系统抛出RuntimeException。此行为可以通过其源代码清楚地传递。它就是这样写的。

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


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

< br >

Android文档表示“随着Android的每一个新版本的发展,一些行为甚至外观可能会发生变化。”我们已经研究了行为和外表的变化,以及这些变化是如何实现的。

总之,Android文档说“这个属性(targetSdkVersion)告诉系统你已经针对目标版本进行了测试,系统不应该启用任何兼容性行为来维持你的应用程序与目标版本的前向兼容性。”。这在WebView案例中非常清楚。直到JELLY_BEAN_MR2发布,才在非主线程上调用WebView类的公共方法。如果Android框架在JELLY_BEAN_MR2设备上抛出RuntimeException,这是毫无意义的。它只是不应该为了自己的利益而启用新引入的行为,这会导致致命的结果。因此,我们要做的是检查某些targetSDKversions上是否一切正常。我们通过设定更高的目标获得了外观提升的好处,但这也伴随着责任。

< p >编辑: 免责声明。DatePickerDialog构造函数根据当前的targetSDKversion(上面显示的)设置不同的主题,实际上已经在后提交中更改了。尽管如此,我还是使用了这个例子,因为逻辑没有改变,而且那些代码片段清楚地显示了targetSDKversion概念

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

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

android:targetSdkVersion:目标sdk版本是设置应用程序的目标API级别。如果这个属性没有在manifest中声明,minSdk版本将是你的TargetSdk版本。这总是正确的,“应用程序支持安装在所有更高版本的API,我们声明为TargetSdk版本”。要使应用程序有限的目标,我们需要声明maxSdkVersion在我们的manifest文件…

如果你正在制作require 危险权限,并设置targetSDK为23或以上的应用程序,你应该小心。如果你在运行时不检查权限,你会得到一个SecurityException,如果你在一个try块中使用代码,例如open camera,如果你不检查logcat,就很难发现错误。

Target sdk是你想要的目标版本,而min sdk是最小的一个。