实际上,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()
。一旦我们有了 type 的对象ITelephony
,我们就可以得到它的 Class 对象,然后得到方法endCall()
从类。一旦我们有了方法,我们就可以访问它,然后调用它。该方法endCall()
位于远程过程调用的客户端。该方法现在向电话管理器服务(在远程服务器中运行)发送一条消息,并要求它结束呼叫。
由于源代码ITelephony.aidl
是公开的,您可以将源代码放在您的项目中,您的 IDE 将生成ITelephony.java
(包含远程过程调用的客户端)来自ITelephony.aidl
. 然后您就可以这样import
做,您的 IDE 现在将了解ITelephony
该类及其方法。这允许编译器在编译项目时生成正确的字节码。当您在 Android 设备上运行此代码时,您调用 Android 框架以获取ITelephony
对象,然后将其强制转换为com.android.internal.telephony.ITelephony
. 从那时起,ITelephony.java
只要您拥有的 Java 代码ITelephony
与返回的实际类定义匹配,您就可以使用生成的对象访问对象的方法和字段ITelephony
目的。如果类定义不匹配,VM 将抛出适当的异常。
我希望这回答了你的问题。我不确定你已经知道多少,所以也许我提到了你已经知道的东西。如果是这样,很抱歉。如果不清楚,请指出您到底不明白什么。