2

I'm not sure if I'm having trouble with Reflection itself, or the method I'm trying to obtain.

What I'd like to do is call the function setLine1Number from the class:

com.android.internal.telephony.gsm.GSMPhone

So that I can have my number properly inserted into my phone as it is not required to be in my SIM. Therefore I want to be able to call the function getLine1Number and have it return the same number that I set.

Reflection appears the only way to be able to use this function as it is not in the public API.

I've written this, but keep getting an illegal argument exception. Here is my code:

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. 

Now at this point, I would like if I could call

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

and have it return the number that I've input. But as I said illegal argument exception, and I'm not sure exactly how to solve this. Any help appreciated. I am still new to reflection so this might be a simple issue.

Here is the error log:

Error Log


Something else I forgot to mention is that I've used the following code to check that this method really exists in the class file:

        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++;
        }  

And the method setLine1Number was returned in the array. So I'm fairly confident it is there and I can use it somehow.

4

7 回答 7

1

您需要一个您希望操作的类的实例——一个已经创建的该类型的对象。

你把它传给setLine1Number.invoke()

例如,如果我们正在处理这个Integer类,你会说:

Integer i = new Integer(5);
...
Object TestReturn = someIntegerMethod.invoke(i, arglist);
于 2012-02-20T23:36:25.377 回答
1

您必须创建一个 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);
于 2012-02-21T07:40:15.577 回答
0

您需要传入要调用该方法的类型的对象,而不是类对象。

于 2012-02-20T22:56:42.240 回答
0

in the invoke call you need to pass an instance of GSMPhone class not classToInvestigate

I'm not familiar with any android API so i'm not sure how you can obtain an instance of it.

EDIT: looking at GSMPhone it calls a public method of SIMRecords maybe you can obtain an instance of that class and call that method instead?

于 2012-02-20T23:11:31.253 回答
0

1)我建议使用“com.android.internal.telephony.Phone”而不是“....gsm.GSMPhone”

2)在开始时尝试这个(并在调用你的 setLine1Number 方法时使用 mPhone): 注意:如果你愿意,可以省略 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;
    }
于 2014-01-15T15:47:03.530 回答
0

如果您想设置不可访问的字段或调用不可访问的方法,您可以将它们设置为可访问,如果您喜欢请参阅:

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

(第 34-37 行)

于 2012-02-21T07:49:24.190 回答
-1

请尝试以下代码。

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);
于 2012-09-14T11:00:41.013 回答