开发者

How to use BluetoothHeadset class via reflection

开发者 https://www.devze.com 2023-04-12 17:26 出处:网络
I want to use methods of BluetoothHeadset class in Android 2.0+. Here is my code: Class bluetoothHeadsetClass = Class.forName(\"android.bluetooth.BluetoothHeadset\");

I want to use methods of BluetoothHeadset class in Android 2.0+. Here is my code:

    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,开发者_JAVA技巧 null);

When executing this code i'm always getting the log message:

10-12 13:29:48.360: WARN/BluetoothHeadset(3379): Proxy not attached to service

I have also tried to wait some seconds before invoking my method, but it's still the same. Thanks for help!!!


Here is how I did it using reflection. I haven't checked if this code works for a while now, so it might well be not:

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


Also tried invoking this by reflection. Ultimately gave up and used a broadcastReceiver instead.

Declare the following intent-filter

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

and in your Receiver in onReceive check for:

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

and save the int as a static variable. Access it anytime you want to know if BT audio is connected(1) / disconnected(0). Not pretty, but gets the job done.

Also check out: https://github.com/android/platform_frameworks_base/blob/gingerbread/core/java/android/bluetooth/BluetoothHeadset.java

0

精彩评论

暂无评论...
验证码 换一张
取 消