其實,將ITelephony.aidl
添加到您的項目是沒有必要的,這只是一個方便。你也可以同樣做這種方式:
TelephonyManager tm = (TelephonyManager) context
.getSystemService(Context.TELEPHONY_SERVICE);
Class c = Class.forName(tm.getClass().getName());
Method m = c.getDeclaredMethod("getITelephony");
m.setAccessible(true);
Object telephonyService = m.invoke(tm); // Get the internal ITelephony object
c = Class.forName(telephonyService.getClass().getName()); // Get its class
m = c.getDeclaredMethod("endCall"); // Get the "endCall()" method
m.setAccessible(true); // Make it accessible
m.invoke(telephonyService); // invoke endCall()
在幕後此使用Java反射的所有作品,訪問私(即:未公開記錄)的方法。您可以通過閱讀開放源代碼(即:公開可用的)Android源代碼來了解哪些方法以及它們的功能。一旦你知道那裏有什麼和它做了什麼,你可以使用反射來實現它,即使它是「隱藏的」。
TelephonyManager
類是使用遠程服務實現的。如果您想請求TelephonyManager
爲您做某些事情,請撥打TelephonyManager
(這是公開記錄的部分)的方法,並在內部撥打遠程電話服務的電話以實際完成工作。這是使用AIDL完成的,這是一種「遠程過程調用」。遠程服務可以通過TelephonyManager
課程公開暴露的內容。你在這裏做的是使用getITelephony()
獲得「遠程過程調用」接口的客戶端。這將返回ITelephony
類型的對象。這個類有一個名爲endCall()
的方法。一旦我們得到類型爲ITelephony
的對象,就可以獲得它的Class對象,然後從Class中獲取方法endCall()
。一旦我們有了這個方法,我們就可以訪問它,而不是通話。方法endCall()
位於遠程過程調用的客戶端。該方法現在向電話管理器服務(在遠程服務器上運行)發送一條消息,並要求它結束呼叫。
因爲用於ITelephony.aidl
的源代碼是公開的,你可以把源代碼在你的項目,你的IDE會產生ITelephony.java
(其中包含遠程過程調用的客戶端)從ITelephony.aidl
。然後您可以只需import
即可,您的IDE現在將知道ITelephony
類及其方法。這允許編譯器在編譯項目時生成正確的字節碼。當您在Android設備上運行此代碼時,您會調用Android框架以獲取ITelephony
對象,然後將其轉換爲com.android.internal.telephony.ITelephony
。從此,只要您對ITelephony
的Java代碼與返回的ITelephony
對象的實際類定義匹配,就可以使用生成的ITelephony.java
訪問對象的方法和字段。如果類定義不匹配,虛擬機將引發適當的異常。
我希望這能回答你的問題。我不確定你已經知道了多少,所以也許我提到了你已經知道的東西。如果是這樣,對此感到抱歉。如果不清楚,請指出您不明白的內容。
謝謝它幫助我設計。做得好 – RobinSingh
難道只是我還是這個不適合Android 4.2.2 – 130nk3r5
太棒了,詳細的答案。謝謝。注意:我不相信Android 4.0.3之後的塊調用可以工作,因爲這個API已被刪除。 – raddevus