Ответ 1
На самом деле, добавление 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-рефлексии для доступа к закрытым (т.е. не публично документированным) методам. Вы можете выяснить, какие методы существуют, и что они делают, читая исходный код с открытым исходным кодом (то есть: общедоступный). Когда вы узнаете, что там и что он делает, вы можете использовать отражение, чтобы добраться до него, даже если оно "скрыто".
Класс TelephonyManager
реализуется с использованием удаленного сервиса. Если вы хотите запросить TelephonyManager
что-то сделать для вас, вы вызываете метод на TelephonyManager
(который публично задокументированная часть) и внутренне он делает вызов службе удаленной телефонной связи, чтобы фактически выполнить эту работу. Это делается с помощью AIDL, который является своего рода "удаленным вызовом процедуры". Удаленная служба может выполнять действия, которые не публиковались публично через класс TelephonyManager
. Что вы здесь делаете, это получить клиентский интерфейс "удаленного вызова процедур", используя getITelephony()
. Это возвращает объект типа ITelephony
. Этот класс имеет метод с именем endCall()
. Когда у нас есть объект типа ITelephony
, мы можем получить его объект класса, а затем получить метод 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 выдаст соответствующее исключение.
Надеюсь, это ответит на ваш вопрос. Я не был точно уверен, как много вы уже знали об этом, так что, возможно, я упомянул то, что вы уже знаете. Если так, извините. Если это не ясно, укажите, что именно вы не понимаете.