Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> 關於Android編程 >> Android如何適配雙卡

Android如何適配雙卡

編輯:關於Android編程

這裡僅以獲取sim卡的IMSI接口(getSubscriberId)和發短信接口(sendTextMessage)為例來詳細講解一下Android5.0-6.0雙卡適配的策略,其他方面的雙卡適配方案跟4.4以前相比並無特別大的區別,之前我們已有專家對此進行過詳細的總結,這裡就不重復說明了。


從Android5.0開始,加入了對雙卡的管理:

首先從數據庫方面來看,其設計思路跟以前某平台是一樣的,加入一個siminfo數據表到telephony.db來管理雙卡的信息。數據表URL:content://telephony/siminfo

 

\


所有插入過的SIM卡的相關信息都會存儲在這個表裡,再看看表裡的字段,這裡截圖只截了前面的幾個比較關鍵的字段

 

\


從截圖中可以看到我用紅框所框的字段,這兩個是尤為關鍵的字段,也是對我們在功能開發的極其關鍵的兩個字段。下面簡單說一下這兩個字段的含義:

_id是表的主鍵,代表sim卡數據的索引值,從1開始,每次新插入的一張sim卡,數據表都會插入一行新數據,該行數據的_id值每次遞增1(1,2,3,4,5……n這樣遞增),而不是更換一張卡更新一下對應卡槽的數據行的sim卡數據。

 

sim_id代表當前卡所在的卡槽值,只有0,1,-1三個值,0代表當前卡插在卡槽1當中(主卡槽),1代表當前卡插在卡槽2當中(副卡槽),-1代表曾經手機插入過此卡,現在已經移除。

其次從加入的API來看,Google加入了一系列管理雙卡信息的類,其主要框架如下圖所示:

 

\

這些API中除了SubscriptionManager之外主要都是供手機系統內部管理雙卡信息使用,對上層功能開發的用途並不大,這裡只供參考,不做詳細講解。

而SubscriptionManager這個類提供了一個關鍵的方法給上層開發來查詢使用,這裡只對它的這個關鍵方法進行一下簡單分析。

 

方法名是:getSubId,獲取指定卡槽sim卡的subId,對應的就是前面所講的數據表中的_id值。為什麼說這個方法對上層開發來說非常關鍵,咱們先來看一下5.0-6.0的前面提到的要適配的兩個接口是怎麼設計的,大家就知道它為什麼關鍵了,在這裡先賣個關子。

Android5.0開始,不單加入了上面這些一系列管理雙卡信息的API,也加入了獲取各sim卡信息狀態以及調用不同sim卡發短信的接口。

 

大家都知道平時咱們開發的發短信功能大多數是調用SmsManager類提供的sendTextMessage方法來發短信的,但是對於雙卡手機來講,按照之前常規的方式,只能是通過默認卡發出短信,那該怎麼辦呢?先來看一段代碼截圖:

\


這段代碼的截圖是SDK5.1中的SmsManager代碼片段,英文注釋就不詳細翻譯了,相信英文大神無處不在,我就不獻丑了,大家自己翻譯一下就好。

 

大家看到了什麼?沒錯:

 

@param subId an SMS subscription id, typically accessed using
{@link android.telephony.SubscriptionManager}

@return the instance of the SmsManager associated with subId

 

這兩行關鍵注釋,進一步提煉一下,subId,subId,subId啊啊啊,關鍵詞重復三遍。

 

到這裡大家是不是豁然開朗,一目了然前面所賣的關子的原因:通過subId可以獲取到對應sim卡的SmsManager實例,而subId正是通過SubscriptionManager的getSubId方法來獲取的,有了對應sim卡的SmsManager實例之後,按照以前的方法通過調用該實例的sendTextMessage方法就可以實現通過不同卡發短信的需求了。

以上是雙卡發短信適配的常規方式,先說到這裡,但並沒有完。

下面再說一下獲取IMSI的適配方案:

 

理解了發短信的方案之後,下面這個方案也很好理解,直接看代碼:

\


也是在TelephonyManager類裡面新增了一個帶參數的getSubscriberId方法,大家應該早已發現,參數也是subId,沒錯就是它。再一次證明了SubscriptionManager的getSubId方法的關鍵性。

 

適配方案就是通過phone服務獲取TelephonyManager的實例,從而調用這個帶參數的getSubscriberId方法來獲取對應sim卡的IMSI,OK搞定。

 

說到這裡,既然getSubId方法這麼關鍵,咱們再返回來一睹SubscriptionManager的getSubId方法代碼的風采:

 

\


由代碼可見,getSubId方法也需要一個int類型的參數,通過參數名不難理解到,它需要的就是對應sim卡所在的卡槽值,也就是對應前面數據表中的sim_id,傳入的合法有效值為0和1,就可以獲取到對應的subId。到目前為止該方法還是一個隱藏方法,外部不能直接調用,如果需要使用,可以通過反射的方式調用。另外還有一點需要注意的是,該方法返回的是一個int數組,使用的時候取它的第一個值就OK了,其實它裡面也只有一個值,至於為什麼要以數組形式返回而不是直接返回int,我也不是非常清楚,並表示不理解,有興趣的朋友可以研究研究為什麼要這樣。

講到這裡,方案看上去貌似挺完美,但是真的是這樣嗎?甚至細心的朋友會懷疑:你這只是官方新增的標准API,稱不上適配吧?

 

沒錯,事情並沒有這麼簡單,這些只能算是5.0以後實現雙卡需求的一個標准解決方案,只能應對極其少數幾個有節操的大廠的ROM還可以,比如三星,做到現在發現5.0以後的三星ROM都很規矩(題外話)。

標准!標准!標准!有節操!有節操!有節操的大廠,那麼針對那些大多數沒節操的廠商該怎麼辦?

 

別急,方案還是有的,做到目前為止,發現會出現適配性問題的地方都是發生在SubscriptionManager和SmsManager身上,比如有的ROM沒有了SubscriptionManager類,有的改名了,有點改方法名了等等。

 

那麼怎麼應對subId這個問題?

 

仔細想想,前面我說過subId就是數據表中_id的值,其實SubscriptionManager底層的實現也是通過查詢這個表得到的。那麼我們就管你改成什麼了,果斷通過傳入卡槽值(sim_id)來查詢sim卡的_id值不就OK了麼。事實也證明此方案可行,具體代碼如下:

 

\

 

通過這個方法來獲取到subId值來提供給發短信和獲取IMSI接口使用,完美解決了以上存在是適配性問題。

然而SmsManager如果也被修改了怎麼辦,繼續看一下下面的代碼截圖:

 

\

通過這段代碼,我們聯想到是不是可以越過SmsManager,直接通過isms服務獲取ISms接口的實例,通過調用ISms接口的sendTextForSubscriber方法來實現雙卡發短信?答案是肯定的,我們看到方法的第一個參數是通過getSubscriptionId()方法獲取到的一個值,沒錯,它也是我們前面提到的subId,都可以通過我們查詢DB的方法來獲取。

好在做到現在,ISms接口的sendTextForSubscriber方法還沒有發現被修改的,相信也不會有廠商無節操到這種地步吧。估計他們也做不到。

最後補充一點,前面所用示例代碼都是通過Android5.1獲取的,其中5.0-6.0不同版本是有區別的:

1、getSubscriberId各版本的區別:
subId在5.0傳入的是long類型的參數,而5.1-6.0傳入的是int類型的參數。

2、sendTextForSubscriber各版本的區別:
subId在5.0傳入的是long類型的參數,而5.1-6.0傳入的是int類型的參數,並且6.0與5.1還有區別,就是方法參數列表末尾多出一個boolean類型的參數。

針對這幾個小差別很好辦,就是將查詢到的subId給轉換成對應的類型,6.0發短信方法的多傳的boolean類型的參數傳true值就OK了。
  1. 上一頁:
  2. 下一頁:
熱門文章
閱讀排行版
Copyright © Android教程網 All Rights Reserved