为什么ITelephony.aidl有效?

时间:2013-09-24 08:55:27

标签: android performance android-intent aidl telephonymanager

我看到一些SO帖子讨论了如何以程序方式结束电话,例如this one。是的,人们专注于结果,但没有人真正解释为什么会起作用的原因?

我尝试了代码,效果很好。但是我想了解更多关于底下发生的事情的细节?为什么通过创建 ITelephony.aidl ,在我们的项目中公开了android隐藏的内部ITelephony接口?我们如何创建 ITelephony.aidl &自动生成的java(/gen/ITelephony.java)链接到 android的ITelephony接口?是否只是因为名称匹配(包名称和援助文件名)?

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(); 

2 个答案:

答案 0 :(得分:78)

实际上,不需要在项目中添加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完成的,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的Java代码与返回的ITelephony对象的实际类定义匹配,就可以使用生成的ITelephony访问对象的方法和字段。 。如果类定义不匹配,VM将抛出适当的异常。

我希望这能回答你的问题。我不确定你对此有多了解,所以也许我提到了你已经知道的东西。如果是这样,抱歉。如果不清楚,请说明您不理解的内容。

答案 1 :(得分:0)

实际上,没有必要将ITelephony.aidl添加到您的项目中,这只是一种方便。您也可以这样做: correct answer