ChatGPT解决这个技术问题 Extra ChatGPT

Android Min SDK Version vs. Target SDK Version

When it comes to developing applications for Android, what is the difference between Min and Target SDK version? Eclipse won't let me create a new project unless Min and Target versions are the same!

From what I'm reading, it sounds like the Target SDK version has no impact on how your application is compiled. It is just there to tell the device that the application is running on that it doesn't need to enable any special compatibility features to make your application work properly. Is this right? It seems to me like you wouldn't know what your target SDK version is until AFTER you've compiled and done a lot of testing. Why can't the compiler just look at your code and figure out what platforms your application is compatible with on its own?
The commenter above has misunderstood why one uses the targetSDK feature. See my answer below for more details.
The accepted answer is not correct. Please read the answer by Steve H.
@tylerl But it's not an incorrect rather it's referring the Google Android documentations. I haven't added anything.
Carl's answer is the most detailed and precise in my opinion.

N
Nathaniel Ford

The comment posted by the OP to the question (basically stating that the targetSDK doesn't affect the compiling of an app) is entirely wrong! Sorry to be blunt.

In short, here is the purpose to declaring a different targetSDK from the minSDK: It means you are using features from a higher level SDK than your minimum, but you have ensured backwards compatibility. In other words, imagine that you want to use a feature that was only recently introduced, but that isn't critical to your application. You would then set the targetSDK to the version where this new feature was introduced and the minimum to something lower so that everyone could still use your app.

To give an example, let's say you're writing an app that makes extensive use of gesture detection. However, every command that can be recognised by a gesture can also be done by a button or from the menu. In this case, gestures are a 'cool extra' but aren't required. Therefore you would set the target sdk to 7 ("Eclair" when the GestureDetection library was introduced), and the minimumSDK to level 3 ("Cupcake") so that even people with really old phones could use your app. All you'd have to do is make sure that your app checked the version of Android it was running on before trying to use the gesture library, to avoid trying to use it if it didn't exist. (Admittedly this is a dated example since hardly anyone still has a v1.5 phone, but there was a time when maintaining compatibility with v1.5 was really important.)

To give another example, you could use this if you wanted to use a feature from Gingerbread or Honeycomb. Some people will get the updates soon, but many others, particularly with older hardware, might stay stuck with Eclair until they buy a new device. This would let you use some of the cool new features, but without excluding part of your possible market.

There is a really good article from the Android developer's blog about how to use this feature, and in particular, how to design the "check the feature exists before using it" code I mentioned above.

To the OP: I've written this mainly for the benefit of anyone who happens to stumble upon this question in the future, as I realise your question was asked a long time ago.


Could you please provide precise explanation how the targetSDKversion affects the compilation of the app? Because compilation version is again another configuration that you need to set up. Thank you in advance
I think Steve confused between the manifest xml attribute android:targetSdkVersion (which has no real say) and between the target property that resides in the project.properties file that represents against what should the code be compiled. I'll say again, the xml attr targetSdkVersion has no real meaning!!!
@kilaka Half your comment is valid, but the other half is simply wrong. I was assuming that someone uses the same value in the XML and the project.properties (also accessible through a right click->properties in Eclipse), so you're right to point out they're stored in different places. However, the Android Market most certainly does care about what value you put in the xml attribute targetSdkVersion. For example, it uses that when determining whether you should have a ActionBar or a compatibility menu for Honeycomb and above applications.
@Nate I couldn't say how much slower this 'convoluted code' makes the runtime, but I do think that splitting and using multiple APKs is worse in terms of code complexity. Now you've got to remember to comment in/out or merge through more branches in your source control before you can make each export. When at an Android conference last October, they said they introduced the multiple APK system as a concession, but were happy that very few people were using it.
But handling multiple versions is what version control systems are made for. It's what developers are familiar with (most software, mobile or not, releases slightly different versions for different platforms). This Android "feature" isn't reducing complexity. It's simply pushing it into the running application, and as evidenced by this thread, creating confusion. Sure, Google is going to be happy that few people are using it ... that helps them say, "see, we were right for making this omission in the first place". Plus, some don't use it because they don't yet know it exists.
S
Shailendra Singh Rajawat

android:minSdkVersion

An integer designating the minimum API Level required for the application to run. The Android system will prevent the user from installing the application if the system's API Level is lower than the value specified in this attribute. You should always declare this attribute.

android:targetSdkVersion

An integer designating the API Level that the application is targetting.

With this attribute set, the application says that it is able to run on older versions (down to minSdkVersion), but was explicitly tested to work with the version specified here. Specifying this target version allows the platform to disable compatibility settings that are not required for the target version (which may otherwise be turned on in order to maintain forward-compatibility) or enable newer features that are not available to older applications. This does not mean that you can program different features for different versions of the platform—it simply informs the platform that you have tested against the target version and the platform should not perform any extra work to maintain forward-compatibility with the target version.

For more information refer this URL:

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


By and large, you're going to set both to the same thing. It would likely be an unusual situation to have them set to different values.
Regarding jjb's comment: I disagree. There are many good reasons why you could have a different minSDK and targetSDK. See my answer for more details.
C
Carl

When you set targetSdkVersion="xx", you are certifying that your app works properly (e.g., has been thoroughly and successfully tested) at API level xx.

A version of Android running at an API level above xx will apply compatibility code automatically to support any features you might be relying upon that were available at or prior to API level xx, but which are now obsolete at that Android version's higher level.

Conversely, if you are using any features that became obsolete at or prior to level xx, compatibility code will not be automatically applied by OS versions at higher API levels (that no longer include those features) to support those uses. In that situation, your own code must have special case clauses that test the API level and, if the OS level detected is a higher one that no longer has the given API feature, your code must use alternate features that are available at the running OS's API level.

If it fails to do this, then some interface features may simply not appear that would normally trigger events within your code, and you may be missing a critical interface feature that the user needs to trigger those events and to access their functionality (as in the example below).

As stated in other answers, you might set targetSdkVersion higher than minSdkVersion if you wanted to use some API features initially defined at higher API levels than your minSdkVersion, and had taken steps to ensure that your code could detect and handle the absence of those features at lower levels than targetSdkVersion.

In order to warn developers to specifically test for the minimum API level required to use a feature, the compiler will issue an error (not just a warning) if code contains a call to any method that was defined at a later API level than minSdkVersion, even if targetSdkVersion is greater than or equal to the API level at which that method was first made available. To remove this error, the compiler directive

@TargetApi(nn)

tells the compiler that the code within the scope of that directive (which will precede either a method or a class) has been written to test for an API level of at least nn prior to calling any method that depends upon having at least that API level. For example, the following code defines a method that can be called from code within an app that has a minSdkVersion of less than 11 and a targetSdkVersion of 11 or higher:

@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();
    }
}

You might also want to declare a higher targetSdkVersion if you had tested at that higher level and everything worked, even if you were not using any features from an API level higher than your minSdkVersion. This would be just to avoid the overhead of accessing compatibility code intended to adapt from the target level down to the min level, since you would have confirmed (through testing) that no such adaptation was required.

An example of a UI feature that depends upon the declared targetSdkVersion would be the three-vertical-dot menu button that appears on the status bar of apps having a targetSdkVersion less than 11, when those apps are running under API 11 and higher. If your app has a targetSdkVersion of 10 or below, it is assumed that your app's interface depends upon the existence of a dedicated menu button, and so the three-dot button appears to take the place of the earlier dedicated hardware and/or onscreen versions of that button (e.g., as seen in Gingerbread) when the OS has a higher API level for which a dedicated menu button on the device is no longer assumed. However, if you set your app's targetSdkVersion to 11 or higher, it is assumed that you have taken advantage of features introduced at that level that replace the dedicated menu button (e.g., the Action Bar), or that you have otherwise circumvented the need to have a system menu button; consequently, the three-vertical-dot menu "compatibility button" disappears. In that case, if the user can't find a menu button, she can't press it, and that, in turn, means that your activity's onCreateOptionsMenu(menu) override might never get invoked, which, again in turn, means that a significant part of your app's functionality could be deprived of its user interface. Unless, of course, you have implemented the Action Bar or some other alternative means for the user to access these features.

minSdkVersion, by contrast, states a requirement that a device's OS version have at least that API level in order to run your app. This affects which devices are able to see and download your app when it is on the Google Play app store (and possibly other app stores, as well). It's a way of stating that your app relies upon OS (API or other) features that were established at that level, and does not have an acceptable way to deal with the absence of those features.

An example of using minSdkVersion to ensure the presence of a feature that is not API-related would be to set minSdkVersion to 8 in order to ensure that your app will run only on a JIT-enabled version of the Dalvik interpreter (since JIT was introduced to the Android interpreter at API level 8). Since performance for a JIT-enabled interpreter can be as much as five times that of one lacking that feature, if your app makes heavy use of the processor then you might want to require API level 8 or above in order to ensure adequate performance.


Thanks for instructions for using TargetApi directive.
@Carl Does it mean that I can always set targetSdkVersion to any version higher than my minSdkVersion(especially to gain those UI enhancements) without need for any testing (per se) as long as I restrict my codebase to use only API's available in my minSdkVersion?
Olowookere Emmanuel: If I understand you correctly, then no, it does not mean that. As my answer states, "if you are using any features that became obsolete at or prior to level xx, compatibility code will not be automatically applied by OS versions at higher API levels." So if your code uses a feature that became available at, say, API level 8, and that feature became obsolete at level 10, then if you raise your targetSdkVersion to anything above 10, there will be no compatibility code available to adjust your uses of that feature to the new OS level.
(Continuing): Whereas, if you leave your targetSdkVersion at level 8, then, while you will not be able to use features introduced at higher levels, there will be compatibility code applied to allow your uses of level 8 features to work when run on higher OS levels.
(Continuing): Think of it this way: Suppose that you wrote some code when the highest Android level available was 8, and you set your targetSdkVersion to 8 (because that was the highest level at the time). Now, some new releases of Android come out, and some of the level 8 features you used become unavailable. Users who still have your old APK should not experience errors, should they? So, to ensure that they don't, compatibility code is automatically applied to adjust your old API calls to do something reasonable when they are invoked while a user is running a newer version of the OS.
김준호

A concept can be better delivered with examples, always. I had trouble in comprehending these concept until I dig into Android framework source code, and do some experiments, even after reading all documents in Android developer sites & related stackoverflow threads. I'm gonna share two examples that helped me a lot to fully understand these concepts.

A DatePickerDialog will look different based on level that you put in AndroidManifest.xml file's targetSDKversion(<uses-sdk android:targetSdkVersion="INTEGER_VALUE"/>). If you set the value 10 or lower, your DatePickerDialog will look like left. On the other hand, if you set the value 11 or higher, a DatePickerDialog will look like right, with the very same code.

https://i.stack.imgur.com/GCGec.png

The code that I used to create this sample is super-simple. MainActivity.java looks :

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();       
    }
}

And activity_main.xml looks :

<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>

That's it. That's really every code that I need to test this.

And this change in look is crystal clear when you see the Android framework source code. It goes like :

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);
}

As you can see, the framework gets current targetSDKversion and set different theme. This kind of code snippet(getApplicationInfo().targetSdkVersion >= SOME_VERSION) can be found here and there in Android framework.

Another example is about WebView class. Webview class's public methods should be called on main thread, and if not, runtime system throws a RuntimeException, when you set targetSDKversion 18 or higher. This behavior can be clearly delivered with its source code. It's just written like that.

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

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

The Android doc says, "As Android evolves with each new version, some behaviors and even appearances might change." So, we've looked behavior and appearance change, and how that change is accomplished.

In summary, the Android doc says "This attribute(targetSdkVersion) informs the system that you have tested against the target version and the system should not enable any compatibility behaviors to maintain your app's forward-compatibility with the target version.". This is really clear with WebView case. It was OK until JELLY_BEAN_MR2 released to call WebView class's public method on not-main thread. It is nonsense if Android framework throws a RuntimeException on JELLY_BEAN_MR2 devices. It just should not enable newly introduced behaviors for its interest, which cause fatal result. So, what we have to do is to check whether everything is OK on certain targetSDKversions. We get benefit like appearance enhancement with setting higher targetSDKversion, but it comes with responsibility.

EDIT : disclaimer. The DatePickerDialog constructor that set different themes based on current targetSDKversion(that I showed above) actually has been changed in later commit. Nevertheless I used that example, because logic has not been changed, and those code snippet clearly shows targetSDKversion concept.


"We get benefit like appearance enhancement with setting higher targetSDKversion, but it comes with responsibility." If they had mentioned this line in docs, I wouldn't be looking for it.
@김준호 I habe two questions: 1.)In the datepicker example above, if you had set targetSdkVersion to 10 or lower and run the app on a device running the latest Android(e.g. API 22) will the datepicker still show like the old one on the left picture? 2.) Does it mean that I can always set targetSdkVersion to any version higher than my minSdkVersion (e.g. to gain those UI enhancements like that crispy datepicker from higher APIs) without need for any testing (per se) as long as I restrict my codebase to use only APIs available in my minSdkVersion?
@Olowookere 1) Yes. Just run for it. 2) You can set targetSDKVersion any version you like if it's higher than minSDKVersion. But you still need to test it whether it works okay on targeted version. It doesn't matter you stick to minSDKVersion api or not. Think of DatePicker example.
Think of a case you set min version 14 & target sdk version to 16, and you only used apis for 14 or lower. Say you used TextView which is introduces in api level 1. What would happen?
@김준호 Thanks. But for your second answer I am confused. If my code uses only API in minSdkVersion and I target higher SDK, why do I need to test? Thinking of DatePicker example, the high targetSdkVersion only improved the look of the DatePicker widget and nothing breaks because I didn't use any code in API higher than minSdkVersion. I only want higher targetSdkVersion because I want the new look and feel of widgets, not that I want to use new features introduced at higher API
D
Darpan

For those who want a summary,

android:minSdkVersion

is minimum version till your application supports. If your device has lower version of android , app will not install.

while,

android:targetSdkVersion

is the API level till which your app is designed to run. Means, your phone's system don't need to use any compatibility behaviours to maintain forward compatibility because you have tested against till this API.

Your app will still run on Android versions higher than given targetSdkVersion but android compatibility behaviour will kick in.

Freebie -

android:maxSdkVersion

if your device's API version is higher, app will not install. Ie. this is the max API till which you allow your app to install.

ie. for MinSDK -4, maxSDK - 8, targetSDK - 8 My app will work on minimum 1.6 but I also have used features that are supported only in 2.2 which will be visible if it is installed on a 2.2 device. Also, for maxSDK - 8, this app will not install on phones using API > 8.

At the time of writing this answer, Android documentation was not doing a great job at explaining it. Now it is very well explained. Check it here


'is maximum version from where you app has inherited features.' : this is wrong. It's the minimum version from where your app has inherited features - ie the first version that includes the required features utilised by your app.
English is tricky language. Read my example given in the answer. I assume that I am making sense there. :)
I'm not being pedantic and English is the support language in this group. Tricky or not saying its the "maximum version where the app has supported features" is not only wrong : its totally 180 degrees wrong. It is the FIRST or minimum version which supports all the intended features of your application without using fallback compatibility modes/libraries.
W
WindRider

If you get some compile errors for example:

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

You get compile error:

Field requires API level 11 (current min is 10): android.graphics.BitmapFactory$Options#inBitmap

Since version 17 of Android Development Tools (ADT) there is one new and very useful annotation @TargetApi that can fix this very easily. Add it before the method that is enclosing the problematic declaration:

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

No compile errors now and it will run !

EDIT: This will result in runtime error on API level lower than 11. On 11 or higher it will run without problems. So you must be sure you call this method on an execution path guarded by version check. TargetApi just allows you to compile it but you run it on your own risk.


I am confused about this. What happen if you run your app later in a system with sdk 10?
It will exectue options.inBitmap statement and app should work fine.
b
benka

android:minSdkVersion and android:targetSdkVersion both are Integer value we need to declare in android manifest file but both are having different properties.

android:minSdkVersion: This is minimum required API level to run an android app. If we will install the same app on lower API version the parser error will be appear, and application not support problem will appear.

android:targetSdkVersion: Target sdk version is to set the Target API level of app. if this attribute not declared in manifest, minSdk version will be your TargetSdk Version. This is always true that "app support installation on all higher version of API we declared as TargetSdk Version". To make app limited target we need to declare maxSdkVersion in our manifest file...


T
Thracian

If you are making apps that require dangerous permissions and set targetSDK to 23 or above you should be careful. If you do not check permissions on runtime you will get a SecurityException and if you are using code inside a try block, for example open camera, it can be hard to detect error if you do not check logcat.


A
Aditya Sawant

Target sdk is the version you want to target, and min sdk is the minimum one.