Backwards compatibility is poor in Android, but an app app can be processed or run between versions. Backward compatibility is not good, different versions of the system its API version is different, naturally some interfaces are different, the new platform can not use the old API, the old platform can not use the new API.
For the app to be more compatible, we can use the high version of the SDK to develop the application, and in the program runtime (runtime) on the platform to run the application judgment, the old platform using the old API, and the new platform can use the new API, which can improve the software compatibility.
So how do you make such judgments when the software is running? Bottom of the answer:
There are a few words in the Android SDK Development documentation:
Check system version at runtime (checks to determine the version of the software at run time)
Android provides a unique code for each platform version in the Build
constants class. Use these codes within your apps to build conditions that ensure the code thatdepends on higher API levels are executed only When those APIs is available on the system.
Private voidSetupactionbar() { Make sure we ' re running on honeycomb or higher to use ActionBar APIs If (build. Version. Sdk_int >= build.. Honeycomb { Actionbar ActionBar = Getactionbar (); Span class= "PLN" > Actionbar.true }}
Note: When parsing XML resources, Android ignores XML attributes that aren ' t supported by the current device. So-can safely use XML attributes Thatare only supported by newer versions without worrying about older versions Breaki ng when theyencounter to that code. For example, if you set targetSdkVersion="11"
the, your apps includes the by ActionBar
Defaulton Android 3.0 and higher. To then add menu items to the action bar, you need to set in android:showAsAction="ifRoom"
your menu resource XML. It's safe to do this in a cross-version XML file, because the older versions of Android simply ignore the showAsAction
attribute Need a separate version in res/menu-v11/
).
As you can see from above, Android provides us with a constant class build, most notably the two internal class version and Version_codes in Build,
Version represents the current system version information, which includes the SDK version information for member Sdk_int representation;
For Version_codes described in the SDK development documentation, enumeration of the currently known SDK version codes. These is the values that can is found in SDK
. Version numbers increment monotonically with each official platform release.
Its members are some version number constants from the earliest version to the currently running system.
In our own development of the application process, we often use the following code form to determine whether to run the new API or the old API:
If(Build. VERSION. >=Build. Version_codes. Honeycomb) {} else {//code block containing the old API}
OK, everybody knows the principle! Baidu needs to be a lot of examples, here is not provided.
Android 10 (2.2.3/2.2.4) and the following version is not fragment, from one (3.0.x) has, this is the new features, and so many more.
Do not understand the main "backwards compatibility" specifically refers to what aspect, as I understand it:
In order to enable the old version of the SDK to use the new version of features and functionality, the official will give an additional jar package, or fragment, if I developed the app must be able to run on 2.3 of the system, but also to use fragment how to do? The introduction of the Android.support.v4.jar package is now available, which is the official compatibility solution.
It can be found that as the SDK version continues to upgrade, the official given the jar package is more and more, android.support.v7.jar,v13 ...
If you want to learn more about what's new in some versions of the upgrade, welcome to Android 5.0 Behavior changes, and of course, if you're interested, you can also find a history version of the upgrade record, not much to say here ...
Android version replacement, new version brings new features, new methods.
The new approach brings a lot of convenience, but it can't run on a lower version of the system, and if the compatibility is not handled properly, the app will be crash on the lower version of the system.
This article shows a specific example of how to handle compatibility issues when using the High API level approach.
Example: gets the total space size of the partition on which this path resides, based on the given path.
Referenced in the wirelessly file store usage reference:
To obtain the file system usage, in the API level 9 and above the system, you can directly invoke File
the relevant methods of the object, the following need to calculate their own
General implementation
For this requirement, API level 9 and above File.getTotalSpace()
can be called, but File
this method does not exist for system objects below API Level 8.
As in the following ways:
/** * Returns the total size in bytes of the partition containing this path. * Returns 0 if this path does not exist. * * @param path * @return -1 means path is null, 0 means path is not exist. */public static long getTotalSpace(File path) { if (path == null) { return -1; } return path.getTotalSpace();}
Processing cannot be compiled by
If minSdkVersion
set to 8, then the build will report the following error:
Call requires API level 9 (current min is 8)
In order to compile can pass, can add @SuppressLint("NewApi")
or @TargeApi(9)
.
@TargeApi($API_LEVEL)
the API level required to explicitly indicate the method, but not @SuppressLint("NewApi")
;
But this only can be compiled through, to the API Level8 system run, will be thrown java.lang.NoSuchMethodError
.
The right approach
In order to run without error, you need:
- Determine the runtime version, this method is not called in the low-version system
In order to ensure the integrity of the function, we need to provide the low-version function
As follows:
/** * Returns The total size in bytes of the partition containing this path. * Returns 0 If this path does not exist. * * @param path * @return-1 means path is null and 0 means path is not exist. */@TargetApi (build.version_codes. Gingerbread)//using @TargeApi instead of @SuppressLint ("Newapi") @SuppressWarnings ("deprecation") public static long G Ettotalspace (File path) {if (path = = null) {return-1; } if (Build.VERSION.SDK_INT >= build.version_codes. Gingerbread) {return path.gettotalspace (); }//Implements Gettotalspace () in API lower than gingerbread else {if (!path.exists ()) {return 0; } else {final StatFs stats = new StatFs (Path.getpath ()); Using deprecated method In low API level system,//Add @SuppressWarnings ("description") to suppress the WA Rning return (Long) stats.getblocksize () * (long) stats.getblockcount (); } }}
Summarize
Using a method higher than minSdkVersion
the API level requires:
- Use to
@TargeApi($API_LEVEL)
make can be compiled through, not recommended @SuppressLint("NewApi")
;
- Run-time judgment API level; This method is called only in an API level system that is high enough to have this method;
- Ensure functional integrity and ensure that low API versions provide functionality through other methods.
Android Developer API compatibility issue background
Given that the Android SDK is updated faster, many new features and APIs may not be available in the lower version. Therefore, the development process as far as possible to maintain the compatibility of the new function interface.
In the general development process, the app will have a minimum version of the configuration, for example, if you want to be compatible with the Android 2.2 system, you can set the Minsdkversion=8, which indicates backward compatibility to the Android 2.2 version, That is, the app can operate on the android2.2 version of the phone, even if the functionality of some of the new features can be disabled, but at least guaranteed that there will be no crashes, and the way to avoid this problem requires the developer to be compatible and adaptable in the code.
Compatibility principles
The minimum supported version of the General app selection principle is to keep it as compatible as possible, but not to say that the more downward the better, the main considerations are the following:
1. The market share of each low-version handset, such as the 2013 Android 2.2 mobile phone also occupies a certain market share, but so far basically this share can be ignored (currently the highest Android version has reached Android 5.1)
2. App targeting user groups, such as high-end user groups, Dick wire user groups, or low-end user groups, according to different user groups can be integrated to determine the minimum version of support.
Advantages and disadvantages based on SDK development
SDK development based on the lower version
The advantage is that you can support more mobile users, basically all versions of the user can use your app.
But the disadvantage is also very obvious, especially for developers, need to do a good job of each new feature of the adaptation and development, as the version becomes more and more high, this will be more and more difficult for developers to maintain later, more and more.
SDK development based on the high version
If you use the latest version of the SDK, the advantage is that you can use the latest features of the API, and the compilation will not have any problems.
But the downside is that you need to stay backward-compatible with the APIs you call, because it's likely that one of your existing calls doesn't exist at all in the lower version. At this point you need to consider the operation of the users of the low-version system.
Real-Combat analysis
As the minimum version of a project configuration is android2.2, it is normal for the development process to be based on the Android SDK for 8来 Engineering development. But if you do not develop based on the Adroid 2.2 SDK version, but instead support a higher version, such as the Android 4.0 SDK development, then many of the high-version features (2.3- 4.0) in the mobile phone under 4.0 can have problems, the general result is direct crash.
Here are some of the most recent projects compiled based on the android2.2 SDK development environment, with some errors that are directly compiled and run. Here are a few examples to look at:
Sampleactivity.java has a place like this:
if (savedinstancestate! =null) {
Morderid =savedinstancestate.getstring (extra_order_id);
Mpaysuccess =savedinstancestate.getstring (extra_pay_success, "");
}
The code uses the method provided by the bundle object in the new version without a compatible processing, as explained in the official documentation below, which is available after Android 3.1.
public string getString (string key, String defaultvalue) Added in API level 12
If the code is run and compiled below Android 3.0, it will be compiled without any processing.
Workaround:
1. Compatible with Android-provided annotations @TargetApi (11) + Version number control
If you are developing a version-based SDK, the new API will definitely have this approach, and if you want the compiled version to work in a lower version, you need to consider version compatibility issues as follows:
/***
* The API version is compatible to get the specified parameters
*
* @param savedinstancestate
* @return
*/
@TargetApi (12)
Private String getpaysucess (Bundle savedinstancestate) {
if (Build.version. sdk_int >= 12) {
mpaysuccess = savedinstancestate.getstring (extra_pay_success, "");
} Else {
mpaysuccess = savedinstancestate.getstring (extra_pay_success);
if (mpaysuccess = =null) {
Mpaysuccess = "";
}
}
returnmpaysuccess;
}
2. Invoke the new feature interface in the high version in a reflected manner.
If it is based on a low-version SDK development, then the new version of the new interface will certainly be compiled, however, it is possible to consider the reflection of the way to find out whether this method, if there is on behalf of the user's phone support the calling method, if not the use of the lower version of the processing mode.
/***
* By means of radiation to get the bundle
* GetString (String key,string value) method
*
* @return
*/
Private StringGetpaysucessinvoke (Bundle savedinstancestate) {
Try {
class<?> C = Class. forname ("Android.os.bundle");
Method mgetstring2params =c.getdeclaredmethod ("getString", String. Class, String. class);
if (Mgetstring2params! =null) {
Mpaysuccess = (String) mgetstring2params.invoke (null,extra_pay_success, "");
} Else {
mpaysuccess = savedinstancestate.getstring (extra_pay_success);
if (mpaysuccess = =null) {
Mpaysuccess = "";
}
}
} catch (Exception e) {
TODO: Handle exception
}
returnmpaysuccess;
}
3. Separate the code, compile and run on different SDK, and finally classloader the related class interface in the dynamic load high version.
This method applies scenarios such as 2, which can be encapsulated in a later version of the API and run the jar package in a later version of the SDK for dynamic loading in the older version of the project.
SDK related tables
Platform Version |
API level |
Version_code |
Notes |
Android 5.1 |
22 |
Lollipop_mr1 |
Platform Highlights |
Android 5.0 |
21st |
LOLLIPOP |
Android 4.4W |
20 |
Kitkat_watch |
KitKat for wearables only |
Android 4.4 |
19 |
KITKAT |
Platform Highlights |
Android 4.3 |
18 |
Jelly_bean_mr2 |
Platform Highlights |
Android 4.2, 4.2.2 |
17 |
Jelly_bean_mr1 |
Platform Highlights |
Android 4.1, 4.1.1 |
16 |
Jelly_bean |
Platform Highlights |
Android 4.0.3, 4.0.4 |
15 |
Ice_cream_sandwich_mr1 |
Platform Highlights |
Android 4.0, 4.0.1, 4.0.2 |
14 |
Ice_cream_sandwich |
Android 3.2 |
13 |
Honeycomb_mr2 |
Android 3.1.x |
12 |
Honeycomb_mr1 |
Platform Highlights |
Android 3.0.x |
11 |
Honeycomb |
Platform Highlights |
Android 2.3.4 Android 2.3.3 |
10 |
Gingerbread_mr1 |
Platform Highlights |
Android 2.3.2 Android 2.3.1 Android 2.3 |
9 |
Gingerbread |
Android 2.2.x |
8 |
FROYO |
Platform Highlights |
Android 2.1.x |
7 |
Eclair_mr1 |
Platform Highlights |
Android 2.0.1 |
6 |
Eclair_0_1 |
Android 2.0 |
5 |
Eclair |
Android 1.6 |
4 |
Donut |
Platform Highlights |
Android 1.5 |
3 |
Cupcake |
Platform Highlights |
Android 1.1 |
2 |
Base_1_1 |
Android 1.0 |
1 |
BASE |
Reference:
Http://developer.android.com/reference/packages.html
Android apps are compatible with different versions