In my custom view I'm using the method drawTextOnPath(...) which is not supported for hardware acceleration until 4.1.
So I wanted to add an if statement which checks the current Android version on runtime and turns the hardware acceleration on if this version is greater or equals to 4.1.
My problem is that I compile my project with Android 4.0 SDK (which is my minimum version), so I don't have the Build.VERSION_CODES for Android 4.1.
Should I compile my project with 4.1 although my minimum version is 4.0 ?
I wrote that up once: Android targeting system
Important parts:
When compiling a Java application with a Java 7 compiler, you can’t
use it with a Java 6 interpreter. The interpreter will tell you, that
it can’t interpret the produced byte-code, even thought you’re not
using any Java 7 language features. If you want to compile with the
latest compiler but make your byte-code runnable on older JVM
instances, you’ll need to tell the compiler to do so (using the
-target-flag).
In Android, you can declare what platform-versions you support in your
manifest-file, using the <uses-sdk>-element and it’s
android:minSdkVersion and android:targetSdkVersion-attributes. The
difference between those “targeting mechanics” is, that Android does
not care against which platform version the application was compiled.
If you declare your application to be compatible with API Level 4,
Android will happily install it, even if you compiled it against
Android 4.1 (API Level 16).
So in short:
If you want your application to work with the newest Android platform, build against it.
Use minSdkVersion to declare the lowest API Level which is supported by your application.
As your targetSdkVersion, use the API Level against which you compiled the application.
Use [Android] Lint to check for (possibly) unsupported API calls.
Use conditional execution and the #TargetApi-annotation to use newer APIs when available.
When you're building your application with the newest SDK, you'll have all the Build.VERSION_CODES available.
Yes, you have to compile against 4.1 if you use 4.1's features, even if you do so conditionally, otherwise compiler will not be able to build your app because it will consider all 4.1 features as invalid (non-existing).
Related
When using CMake to build for Android, does CMAKE_SYSTEM_VERSION correspond to the minimum api level or the target api level?
It's the version of the operating system for which CMake is to build. CMake sets it to the Android API level of the target platform. Usually, we set CMAKE_ANDROID_API instead of manipulating CMAKE_SYSTEM_VERSION directly.
Unfortunately, the NDK toolchain file, which is used by the Android gradle plugin we all use with Android Studio, uses an entirely different set of variables, and sets this to 1 to "Inhibit all of CMake's own NDK handling code". It expects ANDROID_PLATFORM instead.
At any rate, your question about minimum vs. target API level is very important. Unlike Android SDK, the NDK platform support is not backwards compatible. With Java, the best practice is to set the target API as high as possible (and also compile using the latest available SDK), and carefully use the APIs that may be unavailable on older devices.
With C++, we must work differently. Even the latest NDK r18 has 'platforms' going back to android-16, so that you could build your C++ code to run on this older system, too. In terms of Android SDK, this corresponds to minSdkVersion.
I am trying to make a basic Xamarin.forms (pcl) application (in Visual studio 2017) and i want to Target Lolipop (5.0.0, api level 21).
So i made a basic Xamarin solution and i adjusted the Android properties all to Android 5.0 lollipop
Compile using Android version "Android 5.0 (Lollipop)"
Minimum Android to target "Android 5.0 (API Level 21 - Lollipop)"
Target Android Version "Android 5.0 (API Level 21 - Lollipop)"
Unfortunately in my warning list i get the following
Severity Code Description Project File Line Suppression State
Warning The $(TargetFrameworkVersion) for Xamarin.Forms.Platform.dll (v7.0) is greater than the $(TargetFrameworkVersion) for your project (v5.0). You need to increase the $(TargetFrameworkVersion) for your project. Prolang.Android C:\Projects\Prolang\Prolang\Prolang.Android\Prolang.Android.csproj
If i google for this error most people say to indeed update your android project to use the latest Targetframework version. But in my case i really want to only be able to call Api calls that are available to level 21 aka Android 5.0 Lollipop. As in i want the compile time safety net that i only use Api Calls from Api level 21.
To me it seems like i have to downgrade my xamarin.Forms dll to a version that is made specifically for android lollipop since the one i use right now targets a higher version.
So should i downgrade my xamarin.forms dll to achieve this and get rid of the error? And if i downgrade to what version do i need to downgrade so i target Android 5.0 Lollipop? This information is all pretty unclear to me.
Xamarin.Forms is designed using the Android's support libraries so it will run on a wide range of APIs without any additional actions from the developer.
If you are using native APIs via Xamarin.Android (assumably via Forms' Dependency Service) then yes you would have to be aware of the API level of the method calls.
That said, since Xamarin.Forms uses the com.android.support.* libraries and you would have to have to a Forms versions that uses com.android.support:design:21.x.x and the associated Android build tools for API 21.
Now you can review the package dependancies and you will see that your choices are Forms' is 1.4
`1.4.0.6336-pre1` to `1.4.4.6449`
Note: v1.5.x moved to version 22 of the Android support libraries
IMHO using Forms's 1.4 would a bad mistake due to its age and the mountain of improvements and bugs fixes since 2015, you are so much better off:
Using the latest Forms version
Set the Framework version to latest (7.1)
Set the Target Android version to Android 5.0 (API Level 21)
Set the Minimum Android version to whatever you need...
Forgo the compile time API checks
Check runtime API issues via API-21 devices and emulators
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
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.
I have written a simple app for Android and when I first created the project I selected v2.2 for the build target. I have found out that my app does not work on v1.6, it runs for a few seconds then crashes.
So I guess I am using some commands that were not implemented in 1.6. So I need to find out what these commands are and find the 1.6 equivalent. Should not be too hard I guess.
My real question is; to make a 1.6v is the only way to do this to create a new project and set the build target to 1.6 then copy and paste the source code and re-compile? Or is there an easier way? ie can I take my existing 2.2 build and then tell it to compile to 1.6?
Many thanks for the help.
The rule is that you always build with the latest SDK, but use the android:minSdkVersion value of the <uses-sdk> attribute to indicate the lowest API level your app can support.
Note that this attribute is only a clue to the installer and the Market... setting it to 4 (for 1.6) won't mean your app can magically run on 1.6. It's up to you to devise nice fallbacks if more modern APIs are unavailable (or raise your minSdkVersion appropriately if the app cant function without them).
Assuming your app can run on 1.6 without 2.x APIs, then you need to be sure that your 2.x API usage is done from a class that won't get loaded on 2.x. Here's an example:
import android.view.Display;
// Class for wrapping APIs only available in
// API level 8 and up. (i.e. 2.2, a.k.a. Froyo)
class ApiLevel8Only {
public static int getDisplayRotation(Display display) {
return display.getRotation();
}
}
That getRotation() call will cause a force-close on 1.6. To avoid this you inspect the current version before your API-wrapping class is referenced:
if (Integer.parseInt(Build.VERSION.SDK) >= 8) {
ApiLevel8Only.getDisplayRotation(...);
}
Hope that makes sense.
All you have to do is set the minsdk value in your manifest. This sets 1.5 as your minsdk, and 1.6 as your target, for example:
<uses-sdk android:minSdkVersion="3" android:targetSdkVersion="4"/>.
Versioning your app.
android:minSdkVersion — The minimum version of the Android platform on which the application will run, specified by the platform's API Level identifier.
So you set this to the API # for 1.5 or 1.6 and you're app will run on those older versions of Android. But you MUST check for API calls to newer version of Android. You can't use 2.2 features in 1.5, etc.
So you can set your target to Android 2.2, and have your minsdk set to Android 1.5. You can then use Build.VERSION to determine what version of Android the user is using to avoid using newer API calls in older versions of Android.