Как правильно использовать отражение для доступа к скрытым методам в Telephony Manager - PullRequest
2 голосов
/ 21 февраля 2012

Я не уверен, что у меня проблемы с самим Reflection или с методом, который я пытаюсь получить.

Я бы хотел вызвать функцию setLine1Number из класса:

com.android.internal.telephony.gsm.GSMPhone

Чтобы мой номер был правильно вставлен в мой телефон, поскольку он не обязательно должен быть на моей SIM-карте.Поэтому я хочу иметь возможность вызывать функцию getLine1Number и возвращать тот же номер, который я установил.

Отражение представляется единственным способом использования этой функции, поскольку ее нет в общедоступном API.

Я написал это, но продолжаю получать исключение недопустимого аргумента.Вот мой код:

String className = "com.android.internal.telephony.gsm.GSMPhone";
Class classToInvestigate = Class.forName(className);

Object arglist[] = new Object[3];
arglist[0] = new String("Phone Number");
arglist[1] = new String ("16035552412"); // Not a real phone number
arglist[2] = null;

Class[] paramTypes = new Class[3];
paramTypes[0] = String.class;
paramTypes[1] = String.class;
paramTypes[2] = Message.class;
Method setLine1Number = classToInvestigate.getMethod("setLine1Number", paramTypes);
setLine1Number.setAccessible(true);

Object TestReturn = setLine1Number.invoke(classToInvestigate, arglist); // Problem is here. Not sure how to properly do this. 

Теперь я хотел бы позвонить

TelephonyManager telephonyManager = (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE);
String PhoneNumber2 =  telephonyManager.getLine1Number();

и получить возвращенный номер, который я ввел.Но, как я сказал, исключение незаконного аргумента, и я не уверен, как именно это решить.Любая помощь приветствуется.Я все еще новичок в размышлениях, так что это может быть простой проблемой.

Вот журнал ошибок:

Error Log


Что-то еще, что я забыл упомянуть, это то, что я использовал следующий код, чтобы проверить, что этот методдействительно существует в файле класса:

        Method[] checkMethod = classToInvestigate.getDeclaredMethods();

        Test = new String[checkMethod.length];
        int i = 0;
        for(Method m : checkMethod)  
        {  
            // Found a method m  
            Test[i] = m.getName();
            i++;
        }  

И метод setLine1Number был возвращен в массиве.Так что я уверен, что он есть, и я могу как-то его использовать.

Ответы [ 7 ]

1 голос
/ 21 февраля 2012

Вы должны создать экземпляр GSMPhone (classToInvestigate). Вот начало:

Class commandsInterface = Class.forName("com.android.internal.telephony.CommandsInterface");
Class phoneNotifier = Class.forName("com.android.internal.telephony.PhoneNotifier");
Constructor constructor = classToInvestigate.getConstructor(Context.class, commandsInterface, phoneNotifier);

// This creation of newInstance will have to be modified depending on NullPointerExceptions.
// Will probably have to pass in context, as well as instantiate CommandsInterface and PhoneNotifier in a similar fashion and then inject them as well.
Object newInstance = constructor.newInstance(context, null, null);

setLine1Number.invoke(newInstance, arglist);
1 голос
/ 21 февраля 2012

Вам нужен экземпляр класса, с которым вы хотите работать - объект того типа, который уже был создан.

Вы передаете это setLine1Number.invoke()

Например, если бы мы имели дело с классом Integer, вы бы сказали:

Integer i = new Integer(5);
...
Object TestReturn = someIntegerMethod.invoke(i, arglist);
0 голосов
/ 15 января 2014

1) Я предлагаю использовать «com.android.internal.telephony.Phone» вместо «.... gsm.GSMPhone»

2), попробуйте это в начале (и используйте mPhone при вызовеваш метод setLine1Number): NB: ommit try / catch, если вы хотите, но настройте свой вызывающий метод так, чтобы он все выбрасывал ...

private static final String CLASS_PHONEFACTORY = "com.android.internal.telephony.PhoneFactory";
private static final String METHOD_GETDEFAULTPHONE = "getDefaultPhone";

private Class<?> cPhoneFactory;
private Class<?> cPhone;
private Method mGetDefaultPhone;

private Object mPhone;

...

    try {
        cPhoneFactory = Class.forName(CLASS_PHONEFACTORY);
    } catch (ClassNotFoundException e) {
        cPhoneFactory = null; 
    }
    try {
        cPhone = Class.forName(CLASS_PHONE);
    } catch (ClassNotFoundException e) {
        cPhone = null;
    }

    try {
        mGetDefaultPhone = cPhoneFactory == null ? null : cPhoneFactory.getMethod(METHOD_GETDEFAULTPHONE,(Class[])null);
    }
    catch (NoSuchMethodException e) {
        mGetDefaultPhone = null;
    }

    try {
        mPhone = mGetDefaultPhone == null ? null : mGetDefaultPhone.invoke(null,(Object[])null);
    } catch (Exception e) {
        mPhone = null;
    }
0 голосов
/ 14 сентября 2012

пожалуйста, попробуйте следующий код.

String className = "com.android.internal.telephony.gsm.GSMPhone";
Class classToInvestigate = Class.forName(className);
Object gsmObj = classToInvestigate.newInstance();

Object arglist[] = new Object[3];
arglist[0] = new String("Phone Number");
arglist[1] = new String ("16035552412"); // Not a real phone number
arglist[2] = null;

Class[] paramTypes = new Class[3];
paramTypes[0] = String.class;
paramTypes[1] = String.class;
paramTypes[2] = Message.class;

Method setLine1Number = classToInvestigate.getMethod("setLine1Number", paramTypes);
boolean accessible = setLine1Number.isAccessible();
setLine1Number.setAccessible(true);

Object TestReturn = setLine1Number.invoke(gsmObj, arglist);
0 голосов
/ 21 февраля 2012

Если вы хотите установить недоступные поля или вызвать недоступные методы, вы можете установить их доступными, если хотите. См .:

https://github.com/ko5tik/andject/blob/master/src/main/java/de/pribluda/android/andject/ViewInjector.java

(строки 34-37)

0 голосов
/ 21 февраля 2012

в вызове invoke вам нужно передать экземпляр класса GSMPhone, а не classToInvestigate

Я не знаком ни с одним API Android, поэтому я не уверен, как вы можете получитьпример этого.

РЕДАКТИРОВАТЬ: глядя на GSMPhone он вызывает открытый метод SIMRecords может быть, вы можете получить экземпляр этого класса и вместо этого вызвать этот метод?

0 голосов
/ 21 февраля 2012

Вам необходимо передать объект того типа, для которого вы хотите вызвать метод, а не объект класса.

...