Related
I've noticed after the update to Android Studio 3 (but it could be happened also before and I didn't noticed) that some deprecated methods are not marked any more with a line-through. For example:
I'm on Ubuntu, Android Studio 3.0.1 just updated. I checked inspections in the settings, and it's all enabled. I also checked that the code style/formatting is correctly set-up for deprecations (but it had to be, given the last line of the example is correctly marked). It's not something project-related, since I tried on a freshly created project.
What can cause this?
I finally discovered that this is (strangely) the intended behaviour: https://issuetracker.google.com/65793314
What's your minSdkVersion? It's a feature that we now only show deprecated method calls as deprecated if they're deprecated for all the versions you're trying to target
So, getColor() and isAnimationCacheEnabled() are not marked in my example because I'm targeting API 15+, and instead they're deprecated as of API 23. I confirmed this raising my app's minSdkVersion to 23, and they are all marked now.
Anyway I find this behaviour confusing and unnecessary, like I said in the bug report. If someone read this and agrees, please leave a comment there.
I'm just wondering, if the latest Android SDK installed on a device contains code of all the previous versions as well?
So if I target API level 10 in my app and install it on a device with Lollipop, will it just take and use Gingerbread SDK exactly as it was 3 years ago?
Or is there just one codebase for all versions with a lot of checks and switches which is then run by some kind of compatibility mode picking the correct code and enabling methods of the version of SDK I target?
I read the article about android:targetSdkVersion specified in Manifest but still would like to know how this works internally.
Ok, I just surfed a bit around on the source code (which you can find here: https://github.com/android/platform_frameworks_base). I'm not an engineer of the Android framework, I was just curious about your question and here is what I found.
It does not contain all the different versions of source code. You can imagine that this would result in a nightmare if more and more versions become available. Foremost, you would have different (buggy) versions of the same method without fixing them just to keep them the same.
In the source code, you can find places like these: (see https://github.com/android/platform_frameworks_base/blob/59701b9ba5c453e327bc0e6873a9f6ff87a10391/core/java/com/android/internal/view/ActionBarPolicy.java#L55)
public boolean hasEmbeddedTabs() {
final int targetSdk = mContext.getApplicationInfo().targetSdkVersion;
if (targetSdk >= Build.VERSION_CODES.JELLY_BEAN) {
return mContext.getResources().getBoolean(R.bool.action_bar_embed_tabs);
}
// ...
return mContext.getResources().getBoolean(R.bool.action_bar_embed_tabs_pre_jb);
}
So the Android developers do the version check in the code where necessary. But these checks are not as necessary as you think (I guess). What's the reason for changing a method?
method is buggy: All they need to do is fix the bug. Tests will make sure that the general behavior of the method keeps the same
method is deprecated: The guys can not remove the method, all they can do is mark it as deprecated and hope for the best. Compilers will do the rest.
method behavior has to change: Well, I guess that is something they can not do easily. They can work around with version codes (which is pretty ugly and becomes a maintenance nightmare), or they just introduce a new API. That's the reason why you'll find a lot of APIs just doing the same
If you have write down a code with latest android sdk and install it in your device. It means actually you are using latest android.jar(you can see android.jar in your project) file while compiling/Executing code.
Now If you install your application in ginger bread device then android.jar(latest) has a backward compatibility(if required) to run code in Gingerbread device.and if you define target sdk version 10 and running app on Higher API level ,then it will run smooth except your compatibility behavior disable in respective device other than targeted devices.
I made the mistake of not taking into consideration of the API level of each method used in my code. So after coding 500 lines, I have no idea what is the highest Android API level I have used in my code.
Obviously, I hope I do not have to check through every single line of method for its API level so I am wondering is there an option in Eclipse to check the highest API level method which I had used.
Set your target SDK level to your minimum SDK, set your project build target to be the same API level, recompile and fix the errors as they show up.
Note that you will still have to handle API behavior changes like what happened with AsyncTask, but its a start.
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!
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.
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
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.
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.
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.
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
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.
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...
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.
Target sdk is the version you want to target, and min sdk is the minimum one.
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!
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.
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
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.
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.
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.
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
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.
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...
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.
Target sdk is the version you want to target, and min sdk is the minimum one.