日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 运维知识 > Android >内容正文

Android

Android Telephony分析(六) ---- 接口扩展(实践篇)

發(fā)布時(shí)間:2025/3/15 Android 22 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Android Telephony分析(六) ---- 接口扩展(实践篇) 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

本文將結(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è)方法:

public void setValueToModem(int input,Message response) {//這個(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è)接口:

void setValueToModem(int value);
  • 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è)接口:

void setValueToModem(int input);
  • 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的方法:

/** @hide */public void setValueToModem(int input){try {//得到PhoneInterfaceManager的代理對(duì)象ITelephony telephony = getITelephony();if (telephony != null){telephony.setValueToModem(input);}} catch (RemoteException ex) {} catch (NullPointerException ex) {}}
  • 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()方法中增加

case RIL_REQUEST_SET_VALUE: ret = responseInts(p); break;
  • 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)中:

@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

還需要對(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è)接口:

public void notifySetValueDone(String result);
  • 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)中新增接口:

void onSetValueDone(String result);
  • 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
原文地址: http://blog.csdn.net/linyongan/article/details/52151651

總結(jié)

以上是生活随笔為你收集整理的Android Telephony分析(六) ---- 接口扩展(实践篇)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。