Android 開發之API兼容問題

問題背景

鑑於ANDROID SDK 更新較快,不少新的特性和API在低版本中的可能沒有。因此開發過程當中儘可能要保持對新功能接口的兼容。html

通常開發過程當中APP都會有一個最低版本的配置,例如若是要兼容到android 2.2系統,則能夠設置minSdkVersion=8,這就代表能向下兼容到android 2.2版本,即APP能在android2.2版本上的手機也能正常運行,即便可能某些新特性的功能支持失效,但至少保證不會出現崩潰的問題,而避免此問題的方式就要求開發者在代碼中作好兼容和適配。java

 

兼容原則

通常選擇APP的最低支持版本原則是儘可能向下保持兼容,但也不是說越向下越好,主要的考慮因素有如下幾點:android

1.      各個低版本手機的市場佔有率,好比2013年android 2.2的手機還佔用必定的市場份額,但到如今爲止基本上該份額能夠忽略不計了(目前android 最高的版本已達到android 5.1了)api

2.      APP的針對用戶羣體,好比是高端的用戶羣體,屌絲用戶羣體,仍是中低端用戶羣體,根據不一樣的用戶羣體能夠綜合出來決定對最低版本的支持。ide

基於SDK高低開發優缺點

基於低版本的SDK開發ui

優勢就是你能夠支持的手機用戶會更多,基本上各個版本的用戶均可以用你的應用。spa

但缺點也是很是明顯,特別是對開發者來講,須要作好每個新特性功能的適配和開發,隨着版本愈來愈高,這對開發者後期的維護會愈來愈困難,愈來愈多。.net

基於高版本的SDK開發orm

若是你用最新的版本的SDK, 優勢就是你可使用最新的功能的api,並且編譯也不會出現任何問題。htm

可是缺點就是你須要時刻對你調用的api保持向下兼容性,由於頗有可能你現有調用的某個api在低版本中根本就不存在。這時候你須要考慮低版本系統的用戶的運行問題了。

 

 

實戰分析

如某個工程配置中的最低版本是android2.2,也就是正常來講開發過程當中須要基於android SDK爲8來作工程開發。但若是你沒有基於adroid  2.2 SDK版本開發,而是支持了一個更高的版本,好比android 4.0 SDK開發,那麼不少高版本的功能特性(2.3—4.0)在4.0如下的手機中運行就能夠存在問題,通常的結果就是直接crash。

下面是基於android2.2 SDK 開發環境編譯的最新的工程,其中就有一些直接編譯運行不過的錯誤。下面能夠看幾個實例:

SampleActivity.java有一處這樣寫的:

      if (savedInstanceState !=null) {

         mOrderId =savedInstanceState.getString(EXTRA_ORDER_ID);

         mPaySuccess =savedInstanceState.getString(EXTRA_PAY_SUCCESS,"");

      }

代碼中使用Bundle對象在新版本中才提供的方法而沒有加兼容處理,以下官方文檔中解釋,該方法在android 3.1後纔有。

public String getString (String key, String defaultValue) Added in API level 12

若是在低於android 3.0下機器運行和編譯該代碼,若是不作任何處理,會直接編譯通不過。

 

解決方法:

1.       用android提供的註解 @TargetApi(11)+ 版本號控制作兼容

若是是基於高版本的SDK開發,則新的api確定會有該方法,若是想讓編譯的版本在低版本中也能運行,則須要考慮到版本兼容的問題,能夠用以下的方式:

/***

     * 該api版本兼容獲取指定參數

     *

     * @param savedInstanceState

     * @return

     */

   @TargetApi(12)

   privateString 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.       用反射的方式調用高版本中的新功能接口進行調用。

若是是基於低版本SDK開發,那麼新版本中的新接口確定會編譯不過,這時候能夠考慮反射的方式先去查找是否存在這個方法,若是有就表明用戶的手機支持該調用方法,若是沒有則採用低版本的處理方式。

 

   /***

     * 經過放射的方式來獲取Bundle中的

     * getString(String key,String value)方法

     *

     * @return

     */

   privateStringgetPaySucessInvoke(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.       分離代碼,分別在不一樣的SDK上編譯運行,最後ClassLoader動態加載高版本中的相關類接口

此方法應用場景如2,能夠將高版本的api接口封裝後在高版本的SDK中編譯運行jar包,供舊版本的工程中動態加載。

SDK相關對應表

Platform Version

API Level

VERSION_CODE

Notes

Android 5.1

22

LOLLIPOP_MR1

Platform Highlights

Android 5.0

21

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

相關文章
相關標籤/搜索