編輯:關於Android編程
本文主要講解Telephony中Phone相關的知識,主要想講明白三件事情:
Phone是什麼? Phone從哪裡來? Phone有什麼作用?Phone.java (frameworks\opt\telephony\src\java\com\android\internal\telephony)
public interface Phone { //包含了大量的register/unregister的方法。(監聽能力) void registerForXXX(Handler h, int what, Object obj); void unregisterForXXX(Handler h); //大量的get/set的方法。(讀取和修改的能力) //定義Telephony基礎功能的方法(如dial、acceptCall等) }
由上面類圖可以看出,PhoneBase是處於一個最重要最關鍵的位置,是所有關系的中心樞紐。
public abstract class PhoneBase extends Handler implements Phone {
PhoneBase只實現了Phone接口中部分的抽象方法,所以PhoneBase也還是抽象類,它本質上是Handler。
我們常常用到的GSMPhone、CDMAPhone等繼承於PhoneBase,並且實現了Phone接口中還未被PhoneBase實現的抽象方法,同樣,PhoneBase的子類也都是Handler。
至於PhoneProxy,它是一個代理對象:
public PhoneProxy(PhoneBase phone) { //得到PhoneBase對象 mActivePhone = phone; ...... } //舉個例子: @Override public String getPhoneName() { //直接調PhoneBase對象或者它子類的同名方法 return mActivePhone.getPhoneName(); }
代理的好處是安全,我在PhoneProxy中定義了哪幾個方法,你就只能調用那幾個方法,而不會給你得到PhoneBase或者其子類對象,進而操縱所有東西;還有就是對外接口一致,調用方式一致,不用區分是GSMPhone?還是CDMAPhone?或者是IMSPhone?
(備注:上面時序圖中的是谷歌原生的流程,跟高通的有點不一樣。)
Android中有三種PhoneFactZ喎?/kf/ware/vc/" target="_blank" class="keylink">vcnmjujxiciAvPg0KUGhvbmVGYWN0b3J5LmphdmEgJm1kYXNoOyZtZGFzaDsmbmRhc2g7Jmd0O9PD09q0tL2oR1NNUGhvbmWhokNETUFQaG9uZaGiQ0RNQUxURVBob25lttTP86O7PGJyIC8+DQpJbXNQaG9uZUZhY3RvcnkuamF2YSAmbWRhc2g7Jm1kYXNoOyZuZGFzaDsmZ3Q708PT2rS0vahJbXNQaG9uZbbUz/OjuzxiciAvPg0KU2lwUGhvbmVGYWN0b3J5LmphdmEgJm1kYXNoOyZtZGFzaDsmbmRhc2g7Jmd0O9PD09q0tL2oU2lwUGhvbmW21M/zoaM8YnIgLz4NCsbk1tCjrEdTTVBob25loaJDRE1BUGhvbmWhokNETUFMVEVQaG9uZbbUz/PKx9TaUGhvbmW9+LPMxvS2r9auuvO0tL2otcSjqLK91ugxfjejqaO7PGJyIC8+DQrWrrrzo6y1yLW9SW1zU2VydmljZcb0tq/Wrrrzo6y+zbvhtLS9qEltc1Bob25lo6iyvdboOH4xM6OpoaM8L3A+DQo8aDMgaWQ9"21-phone進程的啟動">2.1 Phone進程的啟動
在Android中進程名一般對應的是該APP的包名,所以我們可以在源碼中找package=”com.android.phone”。
接著你就會在/packages/services/Telephony/AndroidManifest.xml文件中看到:
再往下翻翻,你就會看到application的名字是PhoneApp,application是最早被創建的,所以PhoneApp.java就是Phone進程啟動的入口。
為了創建Phone對象,為了實現Phone接口中所有的抽象方法,有兩個問題需要考慮:
創建Phone對象前,需要先准備什麼? 創建Phone對象後,如何讓Phone對象正常工作?我們回過頭繼續看Phone接口:
public interface Phone { //包含了大量的register/unregister的方法。 void registerForXXX(Handler h, int what, Object obj); void unregisterForXXX(Handler h); //大量的get/set的方法。 //定義Telephony基礎功能的方法(如dial、acceptCall等) }
所以,Phone對象必須擁有的能力:與RIL交互的能力(為了實現Telephony基礎功能和大量的get/set的方法),通知上層APP的能力(監聽到事件之後,需要繼續上報該消息)。
如何擁有這兩種能力?最簡單的方法當然把擁有這兩種能力的對象傳遞進來!
看看PhoneBase參數最少的構造方法:
protected PhoneBase(String name, PhoneNotifier notifier, Context context, CommandsInterface ci) { this(name, notifier, context, ci, false); }
可以看出,創建GSMPhone、CDMAPhone、ImsPhone等PhoneBase子類對象時,需要先得到兩個比較重要的對象:DefaultPhoneNotifier(實現了PhoneNotifier接口中大量notify的方法)和RIL(實現了CommandsInterface,RILJ擁有跟Qcril、modem交互的能力)。
GSMPhone/CDMALTEPhone具體的創建過程:
在PhoneFactory.java的makeDefaultPhone方法中(時序圖中的步驟3)
public static void makeDefaultPhone(Context context) { ...... //創建DefaultPhoneNotifier對象。 sPhoneNotifier = new DefaultPhoneNotifier(); //根據待機模式計算出要創建Phone對象的數量 int numPhones = TelephonyManager.getDefault().getPhoneCount(); //創建networkMode、PhoneProxy、RIL的數組,用於存儲對應的對象 int[] networkModes = new int[numPhones]; sProxyPhones = new PhoneProxy[numPhones]; sCommandsInterfaces = new RIL[numPhones]; for (int i = 0; i < numPhones; i++) { // reads the system properties and makes commandsinterface // Get preferred network type. networkModes[i] = RILConstants.PREFERRED_NETWORK_MODE; Rlog.i(LOG_TAG, "Network Mode set to " + Integer.toString(networkModes[i])); //創建RIL,此時的i對應的是PhoneID。 sCommandsInterfaces[i] = new RIL(context, networkModes[i], cdmaSubscription, i); } ...... for (int i = 0; i < numPhones; i++) { PhoneBase phone = null; //先得到Phone的類型 int phoneType = TelephonyManager.getPhoneType(networkModes[i]); //根據不用的類型,創建不同的Phone對象 if (phoneType == PhoneConstants.PHONE_TYPE_GSM) { phone = new GSMPhone(context, sCommandsInterfaces[i], sPhoneNotifier, i); } else if (phoneType == PhoneConstants.PHONE_TYPE_CDMA) { phone = new CDMALTEPhone(context, sCommandsInterfaces[i], sPhoneNotifier, i); } Rlog.i(LOG_TAG, "Creating Phone with type = " + phoneType + " sub = " + i); //創建Phone對象後也要對應地創建一個PhoneProxy對象 sProxyPhones[i] = new PhoneProxy(phone); } ..... // Start monitoring after defaults have been made. // Default phone must be ready before ImsPhone is created // because ImsService might need it when it is being opened. for (int i = 0; i < numPhones; i++) { //在方法的最後,開始監聽ImsService //如果ImsService已啟動,進而執行創建ImsPhone對象 sProxyPhones[i].startMonitoringImsService(); } }
從Phone接口就可以看到,每一個Phone對象都擁有大量的register方法,所以每創建一個Phone對象之後,都用把Phone對象傳遞進CallManager.java的registerPhone()方法中。
PhoneGlobals.java的onCreate()方法中
public void onCreate() { if (mCM == null) { // Initialize the telephony framework //先創建Phone對象 PhoneFactory.makeDefaultPhones(this); mCM = CallManager.getInstance(); for (Phone phone : PhoneFactory.getPhones()) { //把新創建的Phone對象傳遞進來 mCM.registerPhone(phone); } } }
由CallManager來管理這些Phone對象並且為它們注冊監聽事件(步驟7和13)。
// list of registered phones, which are PhoneBase objs private final ArrayListmPhones; public boolean registerPhone(Phone phone) { Phone basePhone = getPhoneBase(phone); if (basePhone != null && !mPhones.contains(basePhone)) { if (DBG) { Rlog.d(LOG_TAG, "registerPhone(" + phone.getPhoneName() + " " + phone + ")"); } if (mPhones.isEmpty()) { mDefaultPhone = basePhone; } //管理Phone對象 mPhones.add(basePhone); mRingingCalls.add(basePhone.getRingingCall()); mBackgroundCalls.add(basePhone.getBackgroundCall()); mForegroundCalls.add(basePhone.getForegroundCall()); //為Phone對象注冊監聽事件 registerForPhoneStates(basePhone); return true; } return false; } private void registerForPhoneStates(Phone phone) { ...... phone.registerForDisconnect(handler, EVENT_DISCONNECT,mRegistrantidentifier); phone.registerForIncomingRing(handler, EVENT_INCOMING_RING,mRegistrantidentifier); ...... }
在第二小節已經講了Phone擁有跟RIl交互的能力和上報消息的能力,所以Phone的作用就是:
1.及時上報消息給APP(Call狀態變化、Service狀態變化、新來電等等)
void notifyPhoneStateChanged(){} void notifyNewRingingConnection(Connection c) {} void notifyDisconnect(Connection cn) {} void notifyUnknownConnection(Connection cn) {} void notifySuppServiceFailed(SuppService code) {} void notifyServiceStateChanged(ServiceState ss) {} void notifyLocationChanged() {} void notifyCallForwardingIndicator() {} ......
2.間接地為APP提供跟RIL交互的服務。
public void getCallWaiting(Message onComplete) {} public void setCallWaiting(boolean enable, Message onComplete) {} ......
好了,本文就暫時寫到這裡。
android gridview畫分割線,如圖:1。先上圖:2.具體實現代碼:public class LineGridView extends GridView {
Android實習札記(8)---ViewPager+Fragment實例講解 在札記(5)中我們就說過要弄一個模仿微信頁面切換的東東,就是V
第十九章、組合模式 組合模式也稱為部分-整體模式,結構型設計模式之一。1.定義將對象組合成樹形結構以表示“部分-整體”的層次結構,使得用戶對單個對
DatePicker實戰效果圖:依賴導入compile 'cn.aigestudio.datepicker:DatePicker:2.2.0'DatePi