如何通过反射使用蓝牙耳机类

时间:2011-10-12 11:52:19

标签: android reflection bluetooth

我想在Android 2.0+中使用BluetoothHeadset类的方法。这是我的代码:

    Class bluetoothHeadsetClass = Class.forName("android.bluetooth.BluetoothHeadset");
    Constructor constructor = bluetoothHeadsetClass.getConstructors()[0];
    Object bluetoothHeadset = constructor.newInstance(this, null);
    Method getState = bluetoothHeadsetClass.getMethod("getState", null);
    Object retVal = getState.invoke(bluetoothHeadset, null);

执行此代码时,我总是收到日志消息:

  

10-12 13:29:48.360:WARN / BluetoothHeadset(3379):代理未连接到   服务

我还试着在调用我的方法之前等待几秒钟,但它仍然是一样的。 谢谢你的帮助!

2 个答案:

答案 0 :(得分:4)

以下是我使用反射的方法。我还没有检查这段代码现在是否有效,所以很可能不会:

class BluetoothHeadset                      
{
    private static final String TAG = Tags.getTag(BluetoothHeadset.class);  
    private static final String BLUETOOTH_HEADSET_CLASS_NAME = "android.bluetooth.IBluetoothHeadset";
    private static final String BLUETOOTH_HEADSET_STUB_CLASS_NAME = BLUETOOTH_HEADSET_CLASS_NAME+"$Stub";

    public static final String ACTION_BLUETOOTH_HEADSET_SERVICE = BLUETOOTH_HEADSET_CLASS_NAME; 
    public static final String ACTION_STATE_CHANGED = "android.bluetooth.headset.action.STATE_CHANGED";
    public static final String ACTION_AUDIO_STATE_CHANGED = "android.bluetooth.headset.action.AUDIO_STATE_CHANGED";
    public static final String EXTRA_AUDIO_STATE = "android.bluetooth.headset.extra.AUDIO_STATE";

     /** A SCO audio channel is not established */
    public static final int AUDIO_STATE_DISCONNECTED = 0;
    /** A SCO audio channel is established */
    public static final int AUDIO_STATE_CONNECTED = 1;

    private static final String AS_INTERFACE_METHOD_NAME = "asInterface";
    private static final String IS_CONNECTED_METHOD_NAME = "isConnected";   

    final Object m_service; 
    private BluetoothHeadset(Object service)
    {
        m_service = service;
    }

    static public BluetoothHeadset getBluetoothHeadset(IBinder service)
    {
        if (service == null) 
        {
            return null;
        }

        Object proxy = null;
        try
        {
            Class<?> clazz = Class.forName(BLUETOOTH_HEADSET_STUB_CLASS_NAME);
            Method asInterfaceMethod = clazz.getMethod(AS_INTERFACE_METHOD_NAME, IBinder.class);
            proxy = asInterfaceMethod.invoke(null, service);            
        }
        catch(ClassNotFoundException ex)
        {
            String msg = String.format("Was not able to find %s class.", 
                                        BLUETOOTH_HEADSET_STUB_CLASS_NAME); 
            Log.e(TAG, msg, ex);
        }
        catch(NoSuchMethodException ex)
        {
            String msg = String.format("Was not able to find %s method in %s class.", 
                                        AS_INTERFACE_METHOD_NAME, 
                                        BLUETOOTH_HEADSET_STUB_CLASS_NAME);
            Log.e(TAG, msg, ex);
        }       
        catch(InvocationTargetException ex)
        {
            String msg = String.format("Was not able to invoke %s method in %s class.", 
                                        AS_INTERFACE_METHOD_NAME, 
                                        BLUETOOTH_HEADSET_STUB_CLASS_NAME);
            Log.e(TAG, msg, ex);
        }
        catch(IllegalAccessException ex)
        {
            String msg = String.format("Illegal access while invoking %s method in %s class.", 
                                        AS_INTERFACE_METHOD_NAME, 
                                        BLUETOOTH_HEADSET_STUB_CLASS_NAME);
            Log.e(TAG, msg, ex);
        }

        if(proxy == null) return null;      
        return new BluetoothHeadset(proxy);
    }

    public Boolean isDeviceConnected(BluetoothDevice device)
    {
        //invoke: boolean isConnected(BluetoothDevice device);
        try
        {
            Class<?> clazz = m_service.getClass();
            Method isConnectedMethod = clazz.getMethod(IS_CONNECTED_METHOD_NAME, BluetoothDevice.class);
            Object result = isConnectedMethod.invoke(m_service, device);

            return (Boolean)result;
        }
        catch(NoSuchMethodException ex)
        {
            String msg = String.format("Failed to find %s method in class %s.", 
                                        IS_CONNECTED_METHOD_NAME, m_service.getClass().getName());
            Log.e(TAG, msg, ex);
        }
        catch(InvocationTargetException ex)
        {
            String msg = String.format("Failed to invoke %s method in class %s.", 
                                        IS_CONNECTED_METHOD_NAME, m_service.getClass().getName());
            Log.e(TAG, msg, ex);
        }   
        catch(IllegalAccessException ex)
        {
            String msg = String.format("Illegal access when invoking %s method in class %s.", 
                                        IS_CONNECTED_METHOD_NAME, m_service.getClass().getName());          
            Log.e(TAG, msg, ex);
        }
        catch(Exception ex)
        {
            Log.e(TAG, "Unknown exception was thrown.", ex);
        }

        return null;
    }   
}

答案 1 :(得分:0)

还尝试通过反射来调用它。 最终放弃并使用了broadcastReceiver。

声明以下intent-filter

        <intent-filter >
            <action android:name="android.bluetooth.headset.action.AUDIO_STATE_CHANGED" />
        </intent-filter>

并在接收者的onReceive中检查:

if ("android.bluetooth.headset.action.AUDIO_STATE_CHANGED".equals(intent.getAction())) {
  headsetAudioState = intent.getIntExtra("android.bluetooth.headset.extra.AUDIO_STATE", -2);
}

并将int保存为静态变量。如果您想知道BT音频是否已连接(1)/断开连接(0),请随时访问它。不漂亮,但完成工作。

同时退房: https://github.com/android/platform_frameworks_base/blob/gingerbread/core/java/android/bluetooth/BluetoothHeadset.java