Android Telephony分析(六) ---- 接口扩展(实践篇)
本文將結合前面五篇文章所講解的知識,綜合起來,實現一個接口擴展的功能。?
 如果還沒有閱讀過前面五篇文章的內容,請先閱讀:?
 《Android Telephony分析(一) — Phone詳解 》?
 《Android Telephony分析(二) — RegistrantList詳解 》?
 《Android Telephony分析(三) — RILJ詳解 》?
 《Android Telephony分析(四) — TelephonyManager詳解 》?
 《Android Telephony分析(五) — TelephonyRegistry詳解 》
至于接口擴展,也就是新增一個接口給APP調用,從APP至RIL,大體流程如下:
APPAPPTelephonyManagerTelephonyManagerPhonePhoneRILRIL發送Requestmodem處理返回結果返回結果本文來自http://blog.csdn.net/linyongan?,禁止轉載。
1. 發送請求的實現
1.1 擴展BaseCommands接口
擴展BaseCommands接口主要為了在RIL.java 中實現向modem發送請求的方法。?
 RILJ的繼承關系如下:?
 
 所以要在RILJ中新增一個向modem發送Request的方法,需要擴展BaseCommands,再在RIL.java重寫該方法。?
 在BaseCommands.java (frameworks\opt\telephony\src\java\com\Android\internal\telephony)添加一個方法:
- 1
- 2
- 3
- 1
- 2
- 3
在RILConstants.java (frameworks\base\telephony\java\com\android\internal\telephony)中新增一個主動請求的消息:
//200這個數字需要根據實際項目進行修改int RIL_REQUEST_SET_VALUE = 200;- 1
- 2
- 1
- 2
在RIL.java (frameworks\opt\telephony\src\java\com\android\internal\telephony)中新增發送請求的方法:
@Overridepublic void setValueToModem(int input,Message response) {//得到一個RILRequest對象RILRequest rr= RILRequest.obtain(RIL_REQUEST_SET_VALUE, response);//將APP傳遞過來的參數放到RILRequest對象中rr.mParcel.writeInt(input);//輸出關鍵logif (RILJ_LOGD) riljLog(rr.serialString() + "> " + requestToString(rr.mRequest)+ " " + input);send(rr);//for test//response.sendToTarget();}- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
至于RILC的擴展省略,調試為了這個接口是否可用,故意寫了?
 response.sendToTarget();這行代碼用于調試。
1.2 擴展PhoneInternalInterface接口
擴展PhoneInternalInterface接口主要為了封裝RILJ的方法,只要得到Phone的實例即可間接調用RILJ的方法。?
 Phone的繼承關系如下:?
 ?
 Phone.java是整個關系的中心樞紐,所以假如不用針對ImsPhone而走IMS流程的話,我們可以擴展PhoneInternalInterface接口,然后在Phone.java中具體實現即可。?
 先在PhoneInternalInterface.java (frameworks\opt\telephony\src\java\com\android\internal\telephony)中新增一個接口:
- 1
- 2
- 1
- 2
在Phone.java (frameworks\opt\telephony\src\java\com\android\internal\telephony)統一實現該接口,Phone所有子類都使用這個方法:
@Overridepublic void setValueToModem(int input){//對于回調事件的處理,第2小節再講Message resp = obtainMessage(EVENT_SET_VALUE_DONE,0,0);//直接調用RILJ中的方法mCi.setValueToModem(input,resp);}- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 1
- 2
- 3
- 4
- 5
- 6
- 7
1.3 擴展ITelephony接口
擴展ITelephony接口主要是為了進一步封裝Phone對象中的方法,讓那些不能直接得到Phone對象的類也可以間接地調用Phone對象中的方法。?
 先在ITelephony.aidl(frameworks\base\telephony\java\com\android\internal\telephony)中新增一個接口:
- 1
- 1
在PhoneInterfaceManager.java (packages\services\telephony\src\com\android\phone)中實現該接口:
@Overridepublic void setValueToModem(int input){try{//得到Phone對象Phone phone = PhoneFactory.getDefaultPhone();if(phone != null){phone.setValueToModem(input);}}catch(IllegalStateException e){}}- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
由于PhoneInterfaceManager運行在Phone進程中,所以還需進一步封裝,讓不運行在Phone進程中的類也可以調用。?
 在TelephonyManager.java (frameworks\base\telephony\java\android\telephony)中封裝Phone Service的方法:
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
從RILJ—>Phone—>PhoneInterfaceManager—>TelephonyManager,經過一層層的封裝,APP終于可以通過TelephonyManager來間接調用RILJ中的方法了。?
 整個過程的時序圖如下:?
 
2. 返回結果的實現
2.1 RILJ中的處理
在RILJ向modem發送請求之后,modem處理完會上報Solicited Response消息并且附帶著結果?
 所以我們需要在RIL.java (frameworks\opt\telephony\src\java\com\android\internal\telephony)的processSolicited()方法中增加
- 1
- 1
在requestToString方法中增加
case RIL_REQUEST_SET_VALUE: return "RIL_REQUEST_SET_VALUE";- 1
- 1
2.2 Phone中的處理
在《Android Telephony分析(三) — RILJ詳解 》的2.2.1小節中我們說過,接著會通過rr.mResult.sendToTarget();返回到創建Message對象的地方,也就是上面1.2小節說到的?
 在Phone.java (frameworks\opt\telephony\src\java\com\android\internal\telephony)中:
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 1
- 2
- 3
- 4
- 5
- 6
- 7
還需要對于回調事件進行處理,也就是先在Phone.java中定義EVENT_SET_VALUE_DONE消息:
//100這個數字需要根據實際項目進行修改protected static final int EVENT_SET_VALUE_DONE = 100;protected static final int EVENT_LAST =EVENT_SET_VALUE_DONE;- 1
- 2
- 3
- 4
- 1
- 2
- 3
- 4
接著在handleMessage()方法中增加對EVENT_SET_VALUE_DONE的處理:
case EVENT_SET_VALUE_DONE://取出返回結果ar = (AsyncResult)msg.obj;String result = null;//如果返回結果不為空且沒有異常if (ar != null && ar.exception == null) {result = "success";}else{result = "fail";}//其實最偷懶的方式是直接在這里發廣播通知APP,//但是為了結合我們學過的知識,我還是通過PhoneNotifier來實現mNotifier.notifySetValueDone(result);break;- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
2.3 擴展PhoneNotifier接口
擴展PhoneNotifier接口主要為了進一步上報消息并且附帶這結果。PhoneNotifier的常用子類是DefaultPhoneNotifier。?
 先在PhoneNotifier.java (frameworks\opt\telephony\src\java\com\android\internal\telephony)中新增一個接口:
- 1
- 1
接著在DefaultPhoneNotifier.java (frameworks\opt\telephony\src\java\com\android\internal\telephony)中實現該接口:
@Overridepublic void notifySetValueDone(String result){try {if (mRegistry != null) {//需要依賴TelephonyRegistry進一步上報通知mRegistry.notifySetValueDone(result);}} catch (RemoteException ex) {ex.printStackTrace();}}- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
2.4 擴展ITelephonyRegistry接口
先在ITelephonyRegistry.aidl(frameworks\base\telephony\java\com\android\internal\telephony)中新增接口:
void notifySetValueDone(String result);- 1
- 1
在TelephonyRegistry.java (frameworks\base\services\core\java\com\android\server)中實現該接口:
@Overridepublic void notifySetValueDone(String result){synchronized (mRecords) {for (Record r : mRecords) {//通知所有監聽了LISTEN_SET_VALUE_DONE的類if((r.matchPhoneStateListenerEvent(PhoneStateListener.LISTEN_SET_VALUE_DONE))){try {r.callback.onSetValueDone(result);} catch (RemoteException ex) {mRemoveList.add(r.binder);}}}handleRemoveListLocked();}}- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
2.5 擴展IPhoneStateListener接口
擴展IPhoneStateListener接口主要為了新增一個可以監聽的事件LISTEN_SET_VALUE_DONE。通過APP事先監聽,當有該事件上報的時候,就會通知到APP。?
 先IPhoneStateListener.aidl(frameworks/base/telephony/java/com/android/internal/telephony)中新增接口:
- 1
- 1
在PhoneStateListener.java (frameworks\base\telephony\java\android\telephony)中新增可監聽的事件,并且初步實現接口中的方法
/** @hide *///這個數字按項目實際需要修改public static final int LISTEN_SET_VALUE_DONE = 0x00800000;/** @hide*/public void onSetValueDone(String result){//由子類來重寫}- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
在IPhoneStateListener callback = new IPhoneStateListener.Stub()中新增:
public void onSetValueDone(String result){Message.obtain(mHandler, LISTEN_SET_VALUE_DONE, 0, 0, result).sendToTarget();}- 1
- 2
- 3
- 1
- 2
- 3
在handleMessage中新增:
case LISTEN_SET_VALUE_DONE://調用子類重寫的方法,也就是APP中的方法PhoneStateListener.this.onSetValueDone((String)msg.obj);break;- 1
- 2
- 3
- 4
- 1
- 2
- 3
- 4
到這里,從RILJ—>Phone—>DefaultPhoneNotifier—>TelephonyRegistry—>APP,消息和結果就上報到APP了。?
 整個過程的時序圖如下(步驟10~15):?
 
3. APP如何使用接口
在APP中可以這樣調用并調試接口:
//監聽事件TelephonyManager.getDefault().listen(new PhoneStateListener(){@Overridepublic void onSetValueDone(String result){//對結果進行處理}}, PhoneStateListener.LISTEN_SET_VALUE_DONE);//發送請求TelephonyManager.getDefault().setValueToModem(1);- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
總結
以上是生活随笔為你收集整理的Android Telephony分析(六) ---- 接口扩展(实践篇)的全部內容,希望文章能夠幫你解決所遇到的問題。
 
                            
                        - 上一篇: Android Telephony分析(
- 下一篇: Android Telephony分析(
