由於系統API並沒有給我們提供Itelephony這個電話管理服務類的接口使用,所以我們就得通過非正常手段來得到這個服務接口.(通過源碼中的Itelephony.aidl來幫助我們生成電話管理服務接口,從而使我們能夠使用到系統操作電話的功能).
例如>>結束通話:
1> 拷貝連同包結構將用到的Itelephony.aidl文件到你的項目中
(由於其中引入了Android.telephony.NeighboringCellInfo.aidl, 所以將其也引入到你的項目中去)
要想掛斷電話必須具有<uses-permission android:name="android.permission.CALL_PHONE"/>權限
try{
//反射獲得系統服務的getService方法對象
Method method = Class.forName("android.os.ServiceManager")
.getMethod("getService", String.class);
//執行這個方法得到一個IBinder對象
IBinder binder = (IBinder) method.invoke(null, new Object[]{TELEPHONY_SERVICE});
//轉換為具體的服務類(ITelephony)接口對象
ITelephony telephony = ITelephony.Stub.asInterface(binder);
//結束通話
telephony.endCall();
//從上是通過 反射來做的, 下面正常的做法>> 按下面來做
// IBinder bindr = ServiceManager.getService(TELEPHONY_SERVICE);
// ITelephony telephony2 = ITelephony.Stub.asInterface(binder);
// telephony2.endCall();
}catch(Exception e){
e.printStackTrace();
}
下面來看看它是怎樣的一個機制來操作電話管理功能的.
首先我們要知道所有的服務類都是在與服務管理器交互.服務管理器把所有的服務都納入到它的管理范疇.而那些系統框架中的各個服務工具類底層都是與這個服務管理器大管家交互.
我是通過 ServiceManager這個系統框架提供服務管理器來得到Itelephony這個服務的Binder對象的
ServiceManager è系統框架上的所有服務都在後來運行著.要想得這些服務 就得通過 這個方法getService來獲得
public static IBinder getService(String name) {//取得服務的Ibinder對象
try {
IBinder service = sCache.get(name);//先從緩存上找到這個服務的IBinder
if (service != null) {
return service;
} else { //如果為空就通過服務管理器接口實現類的getService方法來得到你想要的服務
return getIServiceManager().getService(name);
}
} catch(RemoteException e) {
Log.e(TAG, "error in getService", e);
}
return null;
}
public static void addService(Stringname, IBinder service){//往服務管理器中追加一個服務
public static IBinder checkService(String name)…..//檢索已經存在的Service
public static String[] listServices() throwsRemoteException//列出當前以有的服務
下面來看看class ContextImplextends Context類
@Override
public Object getSystemService(String name) {
if (WINDOW_SERVICE.equals(name)) {
returnWindowManagerImpl.getDefault();
} else if (ACTIVITY_SERVICE.equals(name)) {
returngetActivityManager();
}else if (TELEPHONY_SERVICE.equals(name)) {
return getTelephonyManager();
…..以下略
private TelephonyManager getTelephonyManager() {
synchronized (mSync) {
if (mTelephonyManager == null) {
mTelephonyManager = new TelephonyManager(getOuterContext());
}
}
return mTelephonyManager;
}
以下是TelephonyManager類的構造方法
/** @hide */
public TelephonyManager(Context context) {
mContext = context;
mRegistry = ITelephonyRegistry.Stub.asInterface(ServiceManager.getService(
"telephony.registry"));
}
privateIPhoneSubInfo getSubscriberInfo() {
// get it each time because that process crashes a lot
returnIPhoneSubInfo.Stub.asInterface(ServiceManager.getService("iphonesubinfo"));
}
private ITelephony getITelephony() {
return ITelephony.Stub.asInterface(ServiceManager.getService(Context.TELEPHONY_SERVICE));
}
public void listen(PhoneStateListener listener, int events) {
String pkgForDebug = mContext != null ? mContext.getPackageName() : "<unknown>";
try {
Boolean notifyNow =(getITelephony() != null);
mRegistry.listen(pkgForDebug, listener.callback, events,notifyNow);
} catch(RemoteException ex) {
// system process dead
} catch(NullPointerException ex) {
// system process dead
}
}
在TelephonyManager類中只是通過服務管理器來得到不同的具體服務者進而提供電話的一些基本信息和注冊對電話狀態監聽的回調, 並沒有提供給可以掛斷電話的功能
那系統是怎樣掛斷電話呢…?
最後沒有找到有掛斷電話的功能方法,但是在ITelephony.aidl文件中找到了
/**
* End call or go to the Home screen
*
* @return whether it hung up
*/
booleanendCall();
我們知道AIDL文件是Android接口描述語言。Android系統中的進程之間不能共享內存,因此,需要提供一些機制在不同進程之間進行數據通信. 為使其他的應用程序也可以訪問本應用程序提供的服務,Android系統采用了遠程過程調用(Remote Procedure Call,RPC)方式來實現.這種以跨進程訪問的服務稱為AIDL(Android Interface Definition Language)服務.
這也就是說明我們可以通過此AIDL來訪問到Itelephony這個接口提供的endCall功能.
加載完成後通過ITelephony telephony2 = ITelephony.Stub.asInterface(binder);把Binder對象轉換成對應的服務端的代理對象,然後就通過這個Itelephony服務類在調用端的代理來完成掛斷電話的功能.