1. 程式人生 > >Android 開發之API相容問題

Android 開發之API相容問題

問題背景

鑑於ANDROID SDK 更新較快,很多新的特性和API在低版本中的可能沒有。所以開發過程中儘量要保持對新功能介面的相容。

一般開發過程中APP都會有一個最低版本的配置,例如如果要相容到android 2.2系統,則可以設定minSdkVersion=8,這就表明能向下相容到android 2.2版本,即APP能在android2.2版本上的手機也能正常執行,即使可能某些新特性的功能支援失效,但至少保證不會出現崩潰的問題,而避免此問題的方式就要求開發者在程式碼中做好相容和適配。

 

相容原則

一般選擇APP的最低支援版本原則是儘量向下保持相容,但也不是說越向下越好,主要的考慮因素有以下幾點:

1.      各個低版本手機的市場佔有率,比如2013年android 2.2的手機還佔用一定的市場份額,但到現在為止基本上該份額可以忽略不計了(目前android 最高的版本已達到android 5.1了)

2.      APP的針對使用者群體,比如是高階的使用者群體,屌絲使用者群體,還是中低端使用者群體,根據不同的使用者群體可以綜合出來決定對最低版本的支援。

基於SDK高低開發優缺點

基於低版本的SDK開發

優點就是你可以支援的手機使用者會更多,基本上各個版本的使用者都可以用你的應用。

但缺點也是非常明顯,特別是對開發者來說,需要做好每一個新特性功能的適配和開發,隨著版本越來越高,這對開發者後期的維護會越來越困難,越來越多。

基於高版本的SDK開發

如果你用最新的版本的SDK, 優點就是你可以使用最新的功能的api,而且編譯也不會出現任何問題。

但是缺點就是你需要時刻對你呼叫的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