使用Reflection访问Android中的Dtmf功能

时间:2012-06-01 08:24:35

标签: android reflection dtmf

大家。 我正在尝试使用Reflection将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)sendDtmf()方法确实存在于ClassManager类中,如果可以,我可以访问它吗?

任何建议都将受到强烈赞赏。

1 个答案:

答案 0 :(得分:0)

尝试一组不同的参数类型,我记不清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;
    }
}

Dunno他们在呼叫管理器中提供了哪些保护 - 或者如果您作为用户应用程序甚至能够成功调用此方法 - 但这个示例至少会让您尝试。