編輯:關於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 ArrayList mPhones;
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畫分割線
android gridview畫分割線,如圖:1。先上圖:2.具體實現代碼:public class LineGridView extends GridView {
Android實習札記(8)---ViewPager+Fragment實例詳解
Android實習札記(8)---ViewPager+Fragment實例講解 在札記(5)中我們就說過要弄一個模仿微信頁面切換的東東,就是V
《Android源碼設計模式解析與實戰》讀書筆記(十九)
第十九章、組合模式 組合模式也稱為部分-整體模式,結構型設計模式之一。1.定義將對象組合成樹形結構以表示“部分-整體”的層次結構,使得用戶對單個對
DatePicker
DatePicker實戰效果圖:依賴導入compile 'cn.aigestudio.datepicker:DatePicker:2.2.0'DatePi