2013-09-24 38 views
26

我看到一些SO帖子,討論瞭如何以編程方式結束電話,例如,this one。是的,人們關注的結果,但沒有人真正解釋原因爲什麼它的作品?爲什麼ITelephony.aidl有效?

我試過了代碼,它工作的很好。但我想知道更多關於下面發生了什麼的細節?爲什麼通過創建ITelephony.aidl,android隱藏的內部ITelephony接口暴露在我們的項目中?我們如何創建ITelephony.aidl &自動生成的java(/gen/ITelephony.java)鏈接到 android的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); 

//Why does the android internal ITelephony interface is exposed after created the ITelephony.aidl? 
com.android.internal.telephony.ITelephony telephonyService = (ITelephony) m.invoke(tm); 
telephonyService.endCall(); 

回答

72

其實,將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訪問對象的方法和字段。如果類定義不匹配,虛擬機將引發適當的異常。

我希望這能回答你的問題。我不確定你已經知道了多少,所以也許我提到了你已經知道的東西。如果是這樣,對此感到抱歉。如果不清楚,請指出您不明白的內容。

+1

謝謝它幫助我設計。做得好 – RobinSingh

+0

難道只是我還是這個不適合Android 4.2.2 – 130nk3r5

+1

太棒了,詳細的答案。謝謝。注意:我不相信Android 4.0.3之後的塊調用可以工作,因爲這個API已被刪除。 – raddevus