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
精彩评论