为什么ITelephony.aidl的作品? [英] Why ITelephony.aidl works?

查看:240
本文介绍了为什么ITelephony.aidl的作品?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我看到它如何programmtically结束通话讨论,比如某些SO帖,这个。是的,人们注重结果,但没有人真正说明理由的为什么它的工作原理?

我试过code,效果很好。不过,我想了解下到底是怎么回事的详细信息?为什么要通过创建 ITelephony.aidl ,在Android隐藏的内部 ITelephony 接口在我们的项目中暴露的?如何创建我们自己的 ITelephony.aidl &放大器;自动生成的Java(/gen/ITelephony.java)链接 Android的 ITelephony 界面?仅在名称匹配(包名和放大器; AIDL文件名),因为它

  TelephonyManager TM =(TelephonyManager)上下文
                .getSystemService(Context.TELEPHONY_SERVICE);

C类=的Class.forName(tm.getClass()的getName());
方法米= c.getDeclaredMethod(getITelephony);
m.setAccessible(真正的);

//为什么android的内部ITelephony接口后创建的ITelephony.aidl暴露?
com.android.internal.telephony.ITelephony telephonyService =(ITelephony)m.invoke(商标);
telephonyService.endCall();
 

解决方案

其实,加入 ITelephony.aidl 到你的项目是没有必要的,它只是一个方便。你也可以同样做这种方式:

  TelephonyManager TM =(TelephonyManager)上下文
            .getSystemService(Context.TELEPHONY_SERVICE);
C类=的Class.forName(tm.getClass()的getName());
方法米= c.getDeclaredMethod(getITelephony);
m.setAccessible(真正的);
对象telephonyService = m.invoke(商标); //获取内部ITelephony对象
C =的Class.forName(telephonyService.getClass()的getName()); //获取同级车
米= c.getDeclaredMethod(结束呼叫); //获取结束呼叫()方法
m.setAccessible(真正的); //让它访问
m.invoke(telephonyService); //调用结束呼叫()
 

在幕后这一切都使用Java反射的作品来访问私有(即:不公开记录)的方法。你可以找出方法有哪些,以及他们做什么,通过阅读开源(即:公开的)Android源$ C ​​$ C。一旦你知道什么是存在的,它做什么,你可以使用反射来得到它,即使它是隐藏。

TelephonyManager 类是使用远程服务实现。如果您想请求的 TelephonyManager 来为你做些什么,你呼吁 TelephonyManager (这是公开的方法记录部分),并在内部它使调用远程电话服务,以实际做的工作。这是使用AIDL,这是一种远程过程调用的。远程服务可以做到通过 TelephonyManager 类未公开暴露的事物。你在做什么这里得到的客户端的远程过程调用使用界面 getITelephony()。这将返回类型的对象 ITelephony 。这个类有一个名为方法结束()。一旦我们有了键入 ITelephony 的对象,我们可以得到它的类的对象,然后您可以通过方法结束()班上。一旦我们有了方法,我们将其访问,比调用它。该方法结束()是在远程过程调用的客户端。该方法现在将消息发送到电话管理服务(这是在一个远程服务器上运行),并要求它结束通话。

由于源$ C ​​$ C为 ITelephony.aidl 是公开的,你可以把源$ C ​​$ C在你的项目,你的IDE会生成 ITelephony.java (其中包含远程过程调用的客户端)从 ITelephony.aidl 。然后,您可以只进口这一点,你的IDE现在知道了 ITelephony 类及其方法。这使编译器在编译项目时产生正确的字节级code。当您运行在Android设备上这个code,你打电话到Android框架,以获得 ITelephony 对象,然后将它转换为 com.android.internal.telephony.ITelephony 。从此,您可以通过访问该对象的方法和字段生成的 ITelephony.java 只要在Java code你有 ITelephony 匹配的返回 ITelephony 对象的实际类定义。如果类定义不匹配,虚拟机将抛出一个合适的异常。

我希望这回答了你的问题。我不完全知道有多少你已经知道这一点,所以也许我提到的东西,你已经知道了。如果是这样,我们对此深感抱歉。如果这是不明确的,请注明究竟你不明白。

I saw some SO posts which discussed about how to end a phone call programmtically, for example, this one. Yep, people focus on the result but no one actually explain the reason why it works?

I tried the code, it works well. But I would like to know more details about what is going on underneath? Why by creating the ITelephony.aidl , the android hidden internal ITelephony interface is exposed in our project? How does ourself created ITelephony.aidl & the automatically generated java (/gen/ITelephony.java) link to android's ITelephony interface? Is it only because of the name matching (package name & aidl file name)?

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

解决方案

Actually, adding ITelephony.aidl to your project isn't necessary, it is just a convenience. You could just as well do it this way:

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

Under the covers this all works using Java reflection to access private (ie: not publicly documented) methods. You can figure out what methods are there, and what they do, by reading the open-source (ie: publicly available) Android source code. Once you know what is there and what it does, you can use reflection to get to it, even though it is "hidden".

The TelephonyManager class is implemented using a remote service. If you want to request the TelephonyManager to do something for you, you call a method on the TelephonyManager (that's the publicly documented part) and internally it makes a call to the remote telephony service to actually do the work. This is done using AIDL, which is a kind of "remote procedure call". The remote service can do things that aren't exposed publicly via the TelephonyManager class. What you are doing here is getting the client-side of the "remote procedure call" interface using getITelephony(). This returns an object of type ITelephony. This class has a method named endCall(). Once we have the object of type ITelephony, we can get its Class object and then get the method endCall() from the Class. Once we have the method, we make it accessible and than call it. The method endCall() is in the client-side of the remote procedure call. The method now sends a message to the telephony manager service (which is running in a remote server) and asks it to end the call.

Since the source code for the ITelephony.aidl is publicly available, you can put the source code in your project and your IDE will generate ITelephony.java (which contains the client-side of the remote procedure call) from ITelephony.aidl. You can then just import that and your IDE will now know about the ITelephony class and its methods. This allows the compiler to generate the correct byte-code when compiling your project. When you run this code on an Android device, you call in to the Android framework to get the ITelephony object and then you cast it to com.android.internal.telephony.ITelephony. From then on, you can access the methods and fields of the object using the generated ITelephony.java as long as the Java code you have for ITelephony matches the actual class definition of the returned ITelephony object. If the class definitions don't match, the VM will throw an appropriate exception.

I hope this answers your question. I wasn't exactly sure how much you already knew about this, so maybe I mentioned stuff you already know. If so, sorry about that. If this isn't clear, please indicate what exactly you don't understand.

这篇关于为什么ITelephony.aidl的作品?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆