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