I wanted to know the consequences of having targetSDK > buildTarget.
I recently observed that if I keep the buildTarget=16 and targetSDK=17 the tabs on my tablet (running 4.1.1, API Level 16) moves to the center of the actionBar. I was unable to rationalize the behavior. Can somebody shed some light on why this happened?
Nice question! I had a similar behavior some time ago, when buildTarget and targetSDK differed in the described way. It took me some time, to figure it out, but I will try to summarize my understanding.
You have to distinguish between three important values:
minSdkVersion:
This is the lowest available version, on which the app will (or should!) run. When installing an .apk onto Android, the value will be checked and if the Android version you're running on, is lower than the specified version, it won't install.
buildTarget:
That's the SDK on which the application's .apk will be compiled (and Eclipse will be target that value too, for checking for compilation errors). If the buildTarget is higher than the minSdkVersion, you will be able to install the app even if your Android version does not support all methods. By default, this is set to the latest version of Android available in your SDK. You can still build your app to support older versions, but setting the build target to the latest version allows you to enable new features and optimize your app for a great user experience on the latest devices.
You need to check if the methods you are using are present at runtime if running on a lower API level, otherwise the application might crash!
targetSdkVersion:
The targetSdkVersion specifies on which SDK platform your app should run fine. So, if you tested against API 17, you can add API 17 as targetSdkVersion. If using an Android version > targetSdkVersion, the Android system will enter into some kind of forward-compatibility mode to ensure support for the application. This compatibility behavior will be entered to ensure that your app continues to work the way you expect, as there might be some changes in behavior between never API levels (here are some of the most important changes). So, any application developed for a lower API level will be able to run on a higher version, as the old behavior (like obsolete values) might be "simulated" within the compatibility mode.
For example:
If you set targetSdkVersion to HONEYCOMB (API 11), the default theme will be changed to Theme_Holo (that's the dark holographic UI). Setting targetSdkVersion to a lower value will affect the system to stay on the default light theme, regardless which build API you will use!
In your case, there don't seem to be many noticeable changes between API 16 and 17, that should affect in a design change, but I guess, the higher targetSdkVersion will affect in some additional changes at compile time (like including additional classes, themes, values, ...), that will affect in a different behavior, just like in the theme example above.
I hope, that helped you a bit, to figure out the weird behavior. Here is some more related information to read in the Android Developer documentation.
PS: There is some kind of forward-backward-hell: The Android system is backward-compatible, so that the forward compatibility of Android applications is ensured. That means: If you update your Android version via OTA e.g., all old applications should stay running (so they will stay forward compatible).
The build target is for app development, the target SDK is for app compatibility.
The build target specifies which API you have access to while implementing the app. Like if you set the build taget to android API level 10 then as far as your code is concerned, there is no such thing as an ActionBar. The API you use during development is just a stub implementation of Android, this is way it has to be emulated or run on a real device. Therefore, the build target defines (to the compiler and your IDE) Android interface you are using. Once compiled, there should be no difference based on build target (the Android system doesn't see the build target, it's a compile-time flag). This is a strict contract between you and the android compiler (and your IDE) that defines which components in Android you are able to use in your application, as you will get compilation errors if you try to use something that is beyond the Android version set as your build target.
The target SDK is a contract you sign with the Android system, assuring it that your app is prepared to work properly from you minimum SDK up through to the target SDK (effective the maximum SDK, as the maximum SDK setting should generally be avoided). I believe there are a few things that don't get forward-compatibility, like some of the security changes (probably changes the come from beyond app development and are system-wide). This contract is an agreement that means you have performed measures to make sure that your app handles any changes in the Android API in that range, such that it provides behavior you expect in all situations. The other end of the contract is from the Android system, it agrees to use Android implementation that does not exceed your target SDK, even when on a device running a higher version of Android (this excludes the few changes that I mentioned previously).
The note on forward-compatibility implies that your build target should always at least match your target SDK. You are saying that you have tested your app to run at your target SDK, so why build it against a lower API level?
Real life example of build target and target SDK in action:
ActionBarSherlock provides backward-compatible ActionBar. Here are quotes from requirements to use the library at this time.
The library itself must be built against Android 4.0 (API level 14). Your project should be built using the latest version of the SDK as possible as long as it is 4.0 or newer.
Targetting API level 11 or newer is required as it will cause Android to automatically add the native action bar when run on newer devices. Since you will be compiling against new APIs but your app will likely be run on devices with older versions of Android extra care must be taken to either avoid using or properly check and call any methods that were introduced after your minimum SDK version.
The first paragraph shows that a build target that contains the 4.0 ActionBar API is required, as the library makes use of it and can't compile without it. The second paragraph shows that a target SDK that contains the 3.0 ActionBar API is required as the library uses the native ActionBar on such devices, but the Android system won't provide the ActionBar if your target SDK is lower than 3.0 since that tells it not to use anything newer than your target (like the 3.0 ActionBar).
Some references:
Build Target
Target SDK
Related
I am an experienced Android developer using Eclipse, but one thing still mystifies me. Namely SDK version specifications. In particular, I find several places where SDK versions are specified:
Project Properties: Android: Project Build Target
Manifest: minSdkVersion
Manifest: targetSdkVersion
Manifest: maxSdkVersion
Below are my guesses about usage (probably wrong):
Project Properties: Project Build Type
Ok, seems fairly straightforward. I believe this specifies the API "library" to use.
Manifest: minSdkVersion
My guess is that this is the minimum level (as specified above) for checking methods used. Ok, but seems redundant. Wouldn't the compiler just bark at me if I used an unsupported method?
Manifest: targetSdkVersion
Can't figure this one out. If I call only supported methods, what additionally does this setting do?
Manifest: maxSdkVersion
Even more mysterious. Why would you ever want to limit the max version? Aren't they backward compatible?
The official doc is rather sparse on the functionality of these settings. Can anybody give me some insight?
Android: Project Build Target
When you select a project build target version it means you are apk or classes will be compiled according to selected SDK. for ex - if you select project build target 16 and try to use annotation #JavaScriptInterface it will not find because this annotation is available in above that target.
Manifest: minSdkVersion
If you define minimum SDK version, an Android users who are using below the specified minimum SDK version can't use your app.
For more info from google Docs:
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.
Manifest: targetSdkVersion
The targetSdkVersion has nothing to do with how your app is compiled or what APIs you can utilize. The targetSdkVersion is supposed to indicate that you have tested your app on (presumably up to and including) the version you specify. This is more like a certification or sign off you are giving the Android OS as a hint to how it should handle your app in terms of OS features.
For example, as the documentation states:
For example, setting this value to "11" or higher allows the system to
apply a new default theme (Holo) to your app when running on Android
3.0 or higher...
The Android OS, at runtime, may change how your app is stylized or otherwise executed in the context of the OS based on this value. There are a few other known examples that are influenced by this value and that list is likely to only increase over time.
For all practical purposes, most apps are going to want to set targetSdkVersion to the latest released version of the API. This will ensure your app looks as good as possible on the most recent Android devices. If you do not specify the targetSdkVersion, it defaults to the minSdkVersion.
Manifest: maxSdkVersion
If you define maxSdkVersion users who are using an android phone running SDK version more than what you defined in maxSdkVersion can't use your app.
For more info from google Docs:
An application declaring maxSdkVersion="5" in its manifest is
published on Google Play. A user whose device is running Android 1.6
(API Level 4) downloads and installs the app. After a few weeks, the
user receives an over-the-air system update to Android 2.0 (API Level
5). After the update is installed, the system checks the application's
maxSdkVersion and successfully re-validates it. The application
functions as normal. However, sometime later, the device receives
another system update, this time to Android 2.0.1 (API Level 6). After
the update, the system can no longer re-validate the application
because the system's own API Level (6) is now higher than the maximum
supported by the application (5). The system prevents the application
from being visible to the user, in effect removing it from the device.
Project Properties: Project Build Type - Yes this will pick up the android.jar and also the build tools version.
Manifest: minSdkVersion - This is not just for the compilation purpose but also used by google play to filter the application.
Secondly, if you have any functionality which is not available below a certain version but required by your application.
Manifest: targetSdkVersion - As Android evolves with each new version, some behaviors and even appearances might change. However, if the API level of the platform is higher than the version declared by your app's targetSdkVersion, the system may enable compatibility behaviors to ensure that your app continues to work the way you expect. You can disable such compatibility behaviors by specifying targetSdkVersion to match the API level of the platform on which it's running. For example, setting this value to "11" or higher allows the system to apply a new default theme (Holo) to your app when running on Android 3.0 or higher and also disables screen compatibility mode when running on larger screens (because support for API level 11 implicitly supports larger screens).
Manifest: maxSdkVersion - not recommended. This will restrict your app onto any version higher that the specified maxSdkVersion.
In Android 1.5, 1.6, 2.0, and 2.0.1, the system checks the value of this attribute when installing an application and when re-validating the application after a system update.
However, future versions of Android (beyond Android 2.0.1) will no longer check or enforce the maxSdkVersion attribute during installation or re-validation
There is no need to set the attribute as means of blocking deployment of your application onto new versions of the Android platform as they are released. By design, new versions of the platform are fully backward-compatible. Your application should work properly on new versions, provided it uses only standard APIs and follows development best practices. Second, note that in some cases, declaring the attribute can result in your application being removed from users' devices after a system update to a higher API Level. Most devices on which your application is likely to be installed will receive periodic system updates over the air, so you should consider their effect on your application before setting this attribute.
https://developer.android.com/guide/topics/manifest/uses-sdk-element.html covers it all
I read that berlin is compatible with marshmallow, but i see that by default in the AndroidManifest.template.xml we have :
<uses-sdk android:minSdkVersion="%minSdkVersion%" android:targetSdkVersion="%targetSdkVersion%" />
i don't know where delphi took the variable to update %targetSdkVersion% but it's seam to be all the time 14 and i don't see any way to configure it
i would like to replace %targetSdkVersion% by 23 (marshmallow api level, to support the app permissions), but is it safe to do so or it's will introduce many other bug ?
FireMonkey was developed to work against a certain range of Android functionality. As you can see from the RAD Studio Platform Status page FireMonkey apps built with Delphi 10.1 Berlin have a lowest supported Android version of 4.0.3, which corresponds to Android API Level 15.
The minSdkVersion field is supposed to be set to the earliest Android version your apps will work with so in truth this should probably be set to 15 but actually is set to 14 (Android 4.0-4.0.2).
If you look back at an Android manifest file generated by Delphi XE7, which supported Android 2.3.3 (API Level 10) it specifies a min SDK version of 9 (Android 2.3-2.3.2), which is the version of Android that introduced the NativeActivity type underlying every Delphi FireMonkey Android app. Again, this seems a little bit out of kilter with what is documented as lowest supported version.
Anyway, minSdkVersion can be used by Google Play store to filter your app out of the listings for someone running a lower version of Android. It is also checked when you install an app on a device; Android won't let you install on a lower version of Android.
targetSdkVersion, on the other hand, indicates what version of Android your app has been tested with and works sensibly with. It can often be higher than minSdkVersion if your your app needs to use features introduced in Android versions later than minSdkVersion.
If you want to use a feature from API Level 23 then sure, you'll need to update that manifest part. Just remove the %targetSdkVersion% template from the Android manifest template file and replace it with the required version.
Problems that you might run into:
You'll either need to check the Android version and, if lower than your targetSdkVersion, not use those features that aren't available or set minSdkVersion to a suitably higher version to ensure the app can only run on devices that have the features you wish to use.
FireMonkey code not aware of differing behaviour in API Levels may
function adversely. In your case you may get issues because of the
different runtime permissions behaviour enabled in API Level 23.
Actually I can't currently think of any more issues, though a good amount of testing is recommended. You might have more to think about in a regular Android app using visual activities and so on, when different API levels may affect the theming or other UI elements. You can see the various things that change when you target target SDK versions on this Android documentation page.
By the way, the use of the SDK Manager in the Tools. Options... dialog is entirely irrelevant to the question of how to update the value in the generated manifest file. The only evident way to change it is to manually edit the Android manifest template file as per the documentation, and mentioned in a comment.
The only relevance of the SDK Manager is that the default Android SDK installation for Delphi 10.1 Berlin installs the Platform libraries for API Level 22. If you want to use a feature from API Level 23 you might think that updating those platform libraries might be necessary, but of course if you're doing the coding in Delphi then you're (presumably) actually just compiling against import definitions of the features in that higher API level, and so whether or not those features are contained in the android.jar file is of no consequence.**
** I'm happy to be proved wrong on this count, but I have never observed a connection between the manifest and what the SDK Manager is set up against.
Lets assume I am having a device A and my app is compiled two times: first time I set compileSDK=8, second time i set compileSDK=22.
When I am now calling a function from the Android system would it be possible that the system returns two different values or objects?
I think this is not possible as this depends on the system running on the device and the compile process against a compile SDK only does assert that it works - but one of my collegues states that this might be possible to have different outputs here. (Sorry for not having any examples here..)
Compile version simply tells your compiler which android classes and functions are available. e.g. If you attempt to use a method introduced in v11 and your compile version is 8, then you'll get a compilation error.
I suppose if there was a constant value that changed between 8 and 11, it could get compiled in differently to your app, but this is unlikely because the android developers would know the problems that would cause and it would break their principle of forward compatibility:
Because almost all changes to the framework API are additive, an Android application developed using any given version of the API (as specified by its API Level) is forward-compatible with later versions of the Android platform and higher API levels.
Even so, the advice from here is:
In general, you should compile your application against the lowest possible version of the platform that your application can support.
i.e. compile version = min sdk version
(Note, one exception would to this would be when you need API features from later API, but you intend to safely fall back by checking Build.VERSION. In that case you need a higher compile version than the minimum).
To address your statement:
I think this is not possible as this depends on the system running
It's important to note that devices with an API higher than the targetSdkVersion will attempt emulate down to the lower target API level:
As Android evolves with each new version, some behaviors and even appearances might change. However, if the API level of the platform is higher than the version declared by your app's targetSdkVersion, the system may enable compatibility behaviors to ensure that your app continues to work the way you expect.
Well, I think that is not well explained and right now I'm a little bit confused. From this link:
Compile With is the platform version against which you will compile
your app. By default, this is set to the latest version of Android
available in your SDK. (It should be Android 4.1 or greater; if you
don't have such a version available, you must install one using the
SDK Manager). You can still build your app to support older versions,
but setting the build target to the latest version allows you to
enable new features and optimize your app for a great user experience
on the latest devices.
From this one instead:
When you are developing your application, you will need to choose the
platform version against which you will compile the application. In
general, you should compile your application against the lowest
possible version of the platform that your application can support.
Now, as they are contradicting themselves, here I'll explain what I've understood: let's say that we compile with api 5. It means that if I run from 1 to 5, my application works but it doesn't for versions > 5. So:
Why I need to set the minSdkVersion if compileWith is set to 5?
What is targetSdkVersion?
The point is: if compileWith is set to the latest version, is it possible to use latest APIs and still have backward compatibility? I'm sure that I'm wrong and I'm missing something. Thank you.
Edit 1
Now I understand more but anyway I'm missing something: let's say that minSdk is 9 and target is 18 (my current sdk). It means that I cannot use anything specific to api 18 unless there's some support package for older versions, right? I'm thinking different: I would compile with the lowest version possible to get forward compatibility. I mean, if you compile a Windows application on Win2000, it will run till Windows 8 but I'm limited to Win2000 apis. If I compile with Windows 8, the backward compatibility should be checked on runtime and I can use Windows 8 apis on Win2000 only with "support packages" (it's an example, obviously). Right?
Edit 2
This is what I'm asking about Android (not about the JVM). Android is mixing forward with backward and I've mixed it more using the Windows example. FIY, It seems that Windows is backward compatible, as explained in the examples here. So, what about Android? It seems that the minSdk version should be tested from the developer, I mean: I should compile with latest version and test my application behaviour till the minimum api level that doesn't change it. So it seems that I need to test the backward compatibility by testing on every api level lower than the one with wich is compiled and they assure the forward compatibility. Right?
I think that I'm mixing forward and backward compatibility definitions. Everytime I read them they seem different.
from the Documentation you can read the following:
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.
and
android:targetSdkVersion
An integer designating the API Level that the application targets. If not set, the default value equals that given to minSdkVersion.
This attribute 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. The application is still able to run on older versions (down to minSdkVersion).
And to answer your last question, targeting the latest API will not allow you to execute any newer method or use any newer class on old phones, for that you need to use the support packages, with that you are able to obtain a close result to what you can do in newer APIs.
Hope this gives you a more clear idead of why you have those two values and the difference between them.
UPDATE:
Well about the example of something built for windows 2000 and working on windows 8, is not guarantee that it will work, that is why on windows you have the "run with compatibility" mode, and then you select according to what operating system you want to run it.
This is because maybe both OS (or APIs in this case) have the same method or option, they do it in a different ways or need other permissions. The same happens here, so the target SDK will be the reference frame against you tested and thus it will use that behavior if you run it on newer devides than the taget SDK.
For the APIs between the min and the target they will run as normally they do, and so you can always have a weird behavior and some patching might be need it, normally is most visible on the 2.x to 3.x jump.
UPDATE 2:
Well, let me try to explain it in a different way.
The minSDK will determine which methods and options you can use throughout the application, this means that if a method is only available after that API, you will not be able to use it and instead get an error message.
The targetSDK represents the lastest version of the API that you tested and so, if the phone has a newer API than the one you specified, it will try to behave as it was on the API version you specified, take for example this, in the section Important Behavior Changes:
This inexact batching behavior applies only to updated apps. If you've set the targetSdkVersion to "18" or lower, your alarms will continue behave as they have on previous versions when running on Android 4.4.
So, as you can see there, if you set the targetSDK to a previous API (before 19), it will behave as it use to, but if you target the newest API (at this moment API 19), then it will behave differently.
Hope i was clear enough, if not, please do not hesitate and ask.
I'm working on an application which uses ActionBarSherlock. As it's documentation points out:
[...] the library requires that both it and your project are
compiled with Android 4.0 or newer. The project also requires that
you are compiling with JDK 1.6 in both your editor and any build
systems that you may be using.
So, that means I'll compile my application (and the library) against Android 4.X but in my Manifest, I declare that I'm targeting (e.g.) API Level 9.
This all works fine and well but there is something that disturbs me. From the FAQ:
What API level should I target in my manifest when using the library?
Targetting API level 11 or newer is required as it will cause Android
to automatically add the native action bar when run on newer devices.
Since you will be compiling against new APIs but your app will likely
be run on devices with older versions of Android extra care must be
taken to either avoid using or properly check and call any methods
that were introduced after your minimum SDK version.
That means, that I'll have to manually check every method call, so I don't use any that are not available in my targeted API Level (9 in my case)? This sounds wrong to me.
Is there a way to tell my IDE (IntelliJ), that I'm only using the API Level 9 (so I don't get any auto-completion for non-existing methods/classes and don't use them by accident) and then choose to compile it against another Android version?
Or can I use some automated checks (which run at compile time) to check for that?
The ADT's lint feature should take care of this by warning when API calls are being made for the wrong API version.
You should be compiling both ABS and your project with the latest SDK available (at present, 4.1). Your manifest should have a targetSdkVersion as high as possible (ideally matching your compilation SDK) and your minSdkVersion should be set to the lowest version you support.
Lint is partially integrated with IntelliJ IDEA and is also available as a command line tool.
You temporarily set your target SDK to the various lower ones and debug with it. Your final build then is with the latest SDK.
Set a Build target similar to that you have mentioned in your manifest.
as always , you should set the targetSdk to the maximum available on both the manifest and the project.properties file (as recommended by google on one of their videos) , so that the ADT&SDK would be able to optimize the ADK accordingly.
set the minSdk to the one that you wish to support your app from , and let Lint to tell you if there are any problems in case you use too-new-features.