反射以访问高级电话功能

20
我正在尝试使用反射来访问一些未发布的电信API功能。目前,我遇到了一个问题,即无法实例化serviceManager对象,该对象需要作为绑定器获取“phone”服务,然后我可以使用它来实例化电信对象,从而进行呼叫、结束呼叫等操作...
当前当我发起呼叫时...
serviceManagerObject = tempInterfaceMethod.invoke(null, new Object[] { new Binder() });

它返回了一个NullPointerException。我认为这与创建一个新的Binder有关,而不是发送适当的Binder(我不确定哪一个是适当的)。

public void placeReflectedCall() throws ClassNotFoundException,
        SecurityException, NoSuchMethodException, IllegalArgumentException,
        IllegalAccessException, InvocationTargetException,
        InstantiationException {
    String serviceManagerName = "android.os.IServiceManager";
    String serviceManagerNativeName = "android.os.ServiceManagerNative";
    String telephonyName = "com.android.internal.telephony.ITelephony";

    Class telephonyClass;
    Class telephonyStubClass;
    Class serviceManagerClass;
    Class serviceManagerStubClass;
    Class serviceManagerNativeClass;
    Class serviceManagerNativeStubClass;

    Method telephonyCall;
    Method telephonyEndCall;
    Method telephonyAnswerCall;
    Method getDefault;

    Method[] temps;
    Constructor[] serviceManagerConstructor;

    // Method getService;
    Object telephonyObject;
    Object serviceManagerObject;
    String number = "1111111111";

    telephonyClass = Class.forName(telephonyName);
    telephonyStubClass = telephonyClass.getClasses()[0];
    serviceManagerClass = Class.forName(serviceManagerName);
    serviceManagerNativeClass = Class.forName(serviceManagerNativeName);

    Method getService = // getDefaults[29];
    serviceManagerClass.getMethod("getService", String.class);

    Method tempInterfaceMethod = serviceManagerNativeClass.getMethod(
            "asInterface", IBinder.class);
    // this does not work
    serviceManagerObject = tempInterfaceMethod.invoke(null,
            new Object[] { new Binder() });

    IBinder retbinder = (IBinder) getService.invoke(serviceManagerObject,
            "phone");
    Method serviceMethod = telephonyStubClass.getMethod("asInterface",
            IBinder.class);
    telephonyObject = serviceMethod
            .invoke(null, new Object[] { retbinder });

    telephonyCall = telephonyClass.getMethod("call", String.class);
    telephonyEndCall = telephonyClass.getMethod("endCall");
    telephonyAnswerCall = telephonyClass.getMethod("answerRingingCall");

    telephonyCall.invoke(telephonyObject, number);

}

目前我在实例化serviceManager对象方面遇到了问题,这是你提供的有关错误或问题的唯一信息。你已经给出了代码。现在告诉我们它正在做什么或不做什么是意外的,并且你如何知道它没有正确地工作。 - Adam Davis
3个回答

5
通过以下方式:
Binder tmpBinder = new Binder();
tmpBinder.attachInterface(null, "fake");
serviceManagerObject = tempInterfaceMethod.invoke(null,  new Object[] { tmpBinder });

您将获得一个ServiceManagerProxy实例,然后下一行会发生问题。
telephonyCall.invoke(telephonyObject, number);

3

我有一个解决方案。将其更改为:

String serviceManagerName = "android.os.IServiceManager"; 

to:

String serviceManagerName = "android.os.ServiceManager"; 

2

没错,这是可能的!我花了24个小时进行调查和发现,并找到了一种“新鲜”的解决方案!

// "cheat" with Java reflection to gain access to
// TelephonyManager's ITelephony getter
Class c = Class.forName(tm.getClass().getName());
Method m = c.getDeclaredMethod("getITelephony");
m.setAccessible(true);
telephonyService = (ITelephony) m.invoke(tm);

任何想开发呼叫控制软件的人都可以访问此起点:
http://www.google.com/codesearch/p?hl=en#zvQ8rp58BUs/trunk/phone/src/i4nc4mp/myLock/phone/CallPrompt.java&q=itelephony%20package:http://mylockforandroid%5C.googlecode%5C.com&d=0

这是一个项目。并且有重要的评论(和信用)。

简而言之:复制aidl文件,将权限添加到清单中,复制粘贴用于电话管理的源代码。

更多信息:只有当您获取了root权限后才能发送AT命令。然后您可以杀死系统进程并发送命令,但您需要重新启动手机才能接收和发送电话。

我非常高兴!现在我的Shake2MuteCall将得到更新!


2
嗨,我是MyLock的开发者。我想告诉你,在2.3上它已经无法使用了,我们正在研究如何在假定超级用户根权限的情况下实现相同的结果。这种方法不是我想出来的,是我的朋友Tedd发现了它,并找到了将反射应用于ITelephony的方法。 - mylock
嗨@AlBeebe,上面的链接现在无法使用,你能否分享一下与电话管理相关的AIDL文件和源代码?这将对我有很大帮助。 - Mr. Sajid Shaikh

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接