【问题标题】:Using Reflection to access Dtmf functionalties in Android在 Android 中使用反射访问 Dtmf 功能
【发布时间】:2012-06-01 08:24:35
【问题描述】:

每个人。 我正在尝试使用反射访问 android.internal.telephony.CallManager 中的 sendDtmf 方法,以将这些音调发送到 IVR 语音。

代码如下:

import java.lang.reflect.Method;

import android.content.Context;
import android.util.Log;


public class RefelectionFactory {

public boolean sendDtmf(char c, Context context) throws IllegalArgumentException {

    try{
      @SuppressWarnings("rawtypes")
      //Class Phone = cl.loadClass("com.android.internal.telephony.Phone");

        ClassLoader classLoader = context.getClassLoader();
        final Class<?> classCallManager = classLoader.loadClass("com.android.internal.telephony.CallManager");

      //Parameters Types
      @SuppressWarnings("rawtypes")
      Class[] paramTypes= new Class[1];
      paramTypes[0]= Context.class;

      //Method get = Phone.getMethod("sendDtmf",  paramTypes);
      Method get = classCallManager.getMethod("sendDtmf",  paramTypes);
      get.setAccessible(true);

      //Parameters
      Object[] params= new Object[1];
      params[0]= context;

      get.invoke(null, params);

    }catch( IllegalArgumentException iAE ){
        throw iAE;
    }catch( Exception e ){
        Log.e("ERRORE", "sendDtmf", e);
    }
    return true;
}


}

当我编译代码时,在 LogCat 中会抛出这个异常:

java.lang.NoSuchMethodException: sendDtmf [class android.content.Context]
java.lang.Class.getConstructorOrMethod(Class.java:460)
java.lang.Class.getMethod(Class.java:915)
it.digitalnatives.*****.ricarica.RefelectionFactory.sendDtmf(RefelectionFactory.java:39)
it.digitalnatives.*****.ricarica.MainRicarica$2.onClick(MainRicarica.java:541)
android.view.View.performClick(View.java:3511)
android.view.View$PerformClick.run(View.java:14105)
android.os.Handler.handleCallback(Handler.java:605)
android.os.Handler.dispatchMessage(Handler.java:92)
android.os.Looper.loop(Looper.java:137)
android.app.ActivityThread.main(ActivityThread.java:4424)
java.lang.reflect.Method.invokeNative(Native Method)
java.lang.reflect.Method.invoke(Method.java:511)
com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:784)
com.android.internal.os.ZygoteInit.main(ZygoteInit.java:551)
dalvik.system.NativeStart.main(Native Method)

我被这些东西困住了,我有一些要求。 1)这段代码正确吗? 2) classManager 类中确实存在 sendDtmf() 方法,如果存在,我可以访问吗?

我们将不胜感激任何建议。

【问题讨论】:

    标签: android reflection dtmf


    【解决方案1】:

    尝试一组不同的参数类型,我不记得sendDtmf 曾经使用过Context - ICS 和 2.3 版本都使用char,即CallManager#sendDtmf(char c)

    我会推荐:

    Class<?>[] paramTypes = new Class<?>[]{char.class};
    Method get = classCallManager.getMethod("sendDtmf",  paramTypes);
    

    编辑:现在举个例子。

    class Dtmf {
        private static final String CALL_MANAGER = "com.android.internal.telephony.CallManager";
        private static final String SEND_DTMF = "sendDtmf";
        private static final String GET_INSTANCE = "getInstance";
        private Method mSendDtmfMethod;
        private Object mCallManager;
        public Dtmf() {
            try {
                Class<?> callManagerClass = Class.forName(CALL_MANAGER);
                // Obtain an instance of CallManager
                Method getInstanceMethod = callManagerClass.getMethod(GET_INSTANCE);
                mCallManager = getInstanceMethod.invoke(null);
                // Get sendDtmf(char)
                Class<?>[] sendDtmfParamTypes = new Class<?>[]{char.class};
                mSendDtmfMethod = callManagerClass.getMethod(SEND_DTMF, sendDtmfParamTypes);
            } catch (ClassNotFoundException e) {
            } catch (NoSuchMethodException e) {
            } catch (IllegalArgumentException e) {
            } catch (IllegalAccessException e) {
            } catch (InvocationTargetException e) {
            }
        }
    
        public boolean sendDtmf(char ch) {
            boolean result = false;
            if (mCallManager != null && mSendDtmfMethod != null) {
                try {
                    Object res = mSendDtmfMethod.invoke(mCallManager, 
                            new Object[]{Character.valueOf(ch)});
    
                    if (res instanceof Boolean) {
                        result = ((Boolean) res).booleanValue(); 
                    }
                } catch (IllegalArgumentException e) {
                } catch (IllegalAccessException e) {
                } catch (InvocationTargetException e) {
                }
            }
            return result;
        }
    }
    

    不知道他们在呼叫管理器中设置了哪些保护措施——或者你作为用户应用程序是否能够成功调用此方法——但这个示例至少可以让你尝试一下。

    【讨论】:

    • 非常感谢!!我认为我们向前迈进了一步。现在我在方法 m.invoke(对象接收器,对象...args)上遇到另一个异常。 java.lang.IllegalArgumentException: expected receiver of type com.android.internal.telephony.CallManager, but got java.lang.Class&lt;com.android.internal.telephony.CallManager&gt;. 有什么线索吗?再次感谢。
    • 好吧,对于初学者,您需要传递一个Character 对象而不是上下文。您还需要在这里传递一个类的实例而不是nullget.invoke(null, params);
    • 抱歉,我没有向您粘贴引发该异常的实际代码。这是:String className = "com.android.internal.telephony.CallManager"; try { Class myClass = Class.forName(className); //Class[] paramTypes= new Class[1]; Class&lt;?&gt;[] paramTypes = new Class&lt;?&gt;[]{char.class}; Method m = myClass.getMethod("sendDtmf", paramTypes); m.setAccessible(true); m.invoke(myClass, '1'); } 。那是对的吗?谢谢!
    • 它总是返回 false .. 蚂蚁线索 ??
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2015-10-06
    • 1970-01-01
    • 1970-01-01
    • 2010-10-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多