如何正确使用反射来访问 Telephony Manager 中的隐藏方法

发布于 2025-01-07 06:52:03 字数 1802 浏览 1 评论 0原文

我不确定反射本身是否有问题,或者我试图获取的方法是否有问题。

我想要做的是从类中调用函数 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在数组中返回。所以我相当有信心它就在那里并且我可以以某种方式使用它。

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.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(7

冷血 2025-01-14 06:52:03

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

您将其传递给 setLine1Number.invoke()

例如,如果我们正在处理 Integer 类,您会说:

Integer i = new Integer(5);
...
Object TestReturn = someIntegerMethod.invoke(i, arglist);

You need an instance of the class you wish to operate on - an object of that type that has already been created.

You pass that to setLine1Number.invoke()

For example, if we were dealing with the Integer class you'd say:

Integer i = new Integer(5);
...
Object TestReturn = someIntegerMethod.invoke(i, arglist);
蓝天白云 2025-01-14 06:52:03

您必须创建 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);

You must create an instance of GSMPhone (classToInvestigate). Here is a start:

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);
我不吻晚风 2025-01-14 06:52:03

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

You need to pass in an object of the type you want to call the method on, not the class object.

回首观望 2025-01-14 06:52:03

invoke 调用中,您需要传递 GSMPhone 类的实例,而不是 classToInvestigate

我不熟悉任何 android API,所以我不确定如何获得它的实例。

编辑:查看 GSMPhone 它调用 SIMRecords 的公共方法,也许您可​​以获取该类的实例并调用该方法?

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?

浪漫之都 2025-01-14 06:52:03

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

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

(第34-37行)

In case you like to set not accessible fields or call not accesible methods, you can set them to accessible if you like
See:

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

( lines 34-37 )

嗫嚅 2025-01-14 06:52:03

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

2) 从一开始就尝试这个(并在调用 setLine1Number 方法时使用 mPhone):
注意:如果您愿意,可以省略 try/catch,但设置您的调用方法以抛出所有内容......

private static final String CLASS_PHONEFACTORY = "com.android.internal.telephony.PhoneFactory";
私有静态最终字符串METHOD_GETDEFAULTPHONE =“getDefaultPhone”;

私人课程 cPhoneFactory;
私人课程电话;
私有方法 mGetDefaultPhone;

私有对象 mPhone;

...

<前><代码>尝试{
cPhoneFactory = Class.forName(CLASS_PHONEFACTORY);
} catch (ClassNotFoundException e) {
cPhoneFactory = null;
}
尝试 {
cPhone = Class.forName(CLASS_PHONE);
} catch (ClassNotFoundException e) {
cPhone = null;
}

尝试 {
mGetDefaultPhone = cPhoneFactory == null ? null : cPhoneFactory.getMethod(METHOD_GETDEFAULTPHONE,(Class[])null);
}
捕获(NoSuchMethodException e){
mGetDefaultPhone = null;
}

尝试 {
mPhone = mGetDefaultPhone == null ? null : mGetDefaultPhone.invoke(null,(Object[])null);
} catch (异常 e) {
手机=空;
}

1) I suggest using "com.android.internal.telephony.Phone" instead of "....gsm.GSMPhone"

2) try this one in the beginning (and use mPhone when invoking your setLine1Number method):
NB: ommit try/catch if you desire, but set your calling method to throw everything up...

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;
    }
帅冕 2025-01-14 06:52:03

请尝试以下代码。

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

please try the following code.

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);
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文