Android实现主动连接蓝牙耳机
在Android程序中可以实现自动扫描蓝牙、配对蓝牙、建立数据通道。
可以入下面方法获取蓝牙设备支持的类型:
BluetoothDevice device; Arrays.toString(device.getUuids());
我的蓝牙音箱支持的类型有:
0000111e-0000-1000-8000-00805f9b34fb:Handsfree 0000110b-0000-1000-8000-00805f9b34fb:AudioSink 0000110e-0000-1000-8000-00805f9b34fb:AVRemoteControl 00001203-0000-1000-8000-00805f9b34fb:GenericFileTransfer
这篇文字只讨论如何与蓝牙耳机(蓝牙音箱)连接。
所以下面操作要同时操作A2DP和HFP,两个都连接成功,才算连接成功;
一、A2DP的操作可以分三步:
1、扫描蓝牙设备:
注册并监听广播:
BluetoothAdapter.ACTION_DISCOVERY_STARTED BluetoothDevice.ACTION_FOUND BluetoothAdapter.ACTION_DISCOVERY_FINISHED
启动扫描:
BluetoothAdapter.getDefaultAdapter().startDiscovery();
对扫描的结果按类型进行筛选,只保留我们需要的蓝牙耳机:
if(device.getBluetoothClass().getDeviceClass() == BluetoothClass.Device.AUDIO_VIDEO_WEARABLE_HEADSET || device.getBluetoothClass().getDeviceClass() == BluetoothClass.Device.AUDIO_VIDEO_HANDSFREE){ //蓝牙耳机 }
2、配对指定的蓝牙设备:
这个跟配对普通蓝牙一样,方法如下:
public static boolean createBond(BluetoothDevice btDevice){ boolean result = false; try{ Method m = btDevice.getClass().getDeclaredMethod("createBond",new Class[]{}); m.setAccessible(true); Boolean originalResult = (Boolean) m.invoke(btDevice); result = originalResult.booleanValue(); }catch(Exception ex){ } return result; }
等配对完成之后就是要建立数据连接;
3、建立数据连接:
ifyouSDKbetween11and16.calla2dp.connectSink(btDevice)ora2dp.connect(btDevice)
private static IBluetoothA2dp getIBluetoothA2dp() { IBluetoothA2dp ibta = null; try { final Class serviceManager = Class.forName("android.os.ServiceManager"); final Method getService = serviceManager.getDeclaredMethod("getService", String.class); final IBinder iBinder = (IBinder) getService.invoke(null, "bluetooth_a2dp"); final Class iBluetoothA2dp = Class.forName("android.bluetooth.IBluetoothA2dp"); final Class[] declaredClasses = iBluetoothA2dp.getDeclaredClasses(); final Class c = declaredClasses[0]; final Method asInterface = c.getDeclaredMethod("asInterface", IBinder.class); asInterface.setAccessible(true); ibta = (IBluetoothA2dp) asInterface.invoke(null, iBinder); } catch (final Exception e) { Log.e("Error " + e.getMessage()); } return ibta; }
参考:http://stackoverflow.com/questions/8467178/working-around-a2dp-and-hfp-limitations-of-android-pre-honeycomb
如果API大于16需要用如下的方法:
private void initA2dpService(){ // Intent i = getExplicitIntent(mContext,new Intent(IBluetoothA2dp.class.getName()));//5.0以上系统需要显示intent //详细参考http://blog.csdn.net/l2show/article/details/47421961 Intent i = new Intent(IBluetoothA2dp.class.getName()); boolean success = mContext.bindService(i, mConnection, Context.BIND_AUTO_CREATE); if (success) { } else { } } public ServiceConnection mConnection = new ServiceConnection() { @Override public void onServiceConnected(ComponentName name, IBinder service) { try { mA2dpService = IBluetoothA2dp.Stub.asInterface(service); } catch (Exception e) { e.printStackTrace(); } } @Override public void onServiceDisconnected(ComponentName name) { // TODO Auto-generated method stub } }; public Intent getExplicitIntent(Context context, Intent implicitIntent) { // Retrieve all services that can match the given intent PackageManager pm = context.getPackageManager(); List<ResolveInfo> resolveInfo = pm.queryIntentServices(implicitIntent, 0); // Make sure only one match was found if (resolveInfo == null || resolveInfo.size() != 1) { return null; } // Get component info and create ComponentName ResolveInfo serviceInfo = resolveInfo.get(0); String packageName = serviceInfo.serviceInfo.packageName; String className = serviceInfo.serviceInfo.name; ComponentName component = new ComponentName(packageName, className); // Create a new intent. Use the old one for extras and such reuse Intent explicitIntent = new Intent(implicitIntent); // Set the component to be explicit explicitIntent.setComponent(component); return explicitIntent; }
建立连接:mA2dpService.connect(device);
断开连接:mA2dpService.disconnect(device);
参考:http://stackoverflow.com/questions/14705167/how-connect-paired-bluetooth-a2dp-device-on-android-4-2-using-reflection
http://blog.csdn.net/qs_csu/article/details/45114251
二、HFP操作:
下面只针对4.0及以上版本;
1、初始化:
private void initOrCloseBtCheck(boolean init){ if(init){ mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter(); mBluetoothAdapter.getProfileProxy(mContext, new ServiceListener() { public void onServiceConnected(int profile, BluetoothProfile proxy) { if (profile == BluetoothProfile.HEADSET) { mBluetoothHeadset = (BluetoothHeadset) proxy; } } public void onServiceDisconnected(int profile) { if (profile == BluetoothProfile.HEADSET) { mBluetoothHeadset = null; } } },BluetoothProfile.HEADSET); }else{ mBluetoothAdapter.closeProfileProxy(BluetoothProfile.HEADSET,mBluetoothHeadset); } }
建立连接:
Method m = mBluetoothHeadset.getClass().getDeclaredMethod("connect",BluetoothDevice.class); m.setAccessible(true); //连接Headset boolean successHeadset = (Boolean)m.invoke(mBluetoothHeadset, device);
断开连接:
Method m = mBluetoothHeadset.getClass().getDeclaredMethod("disconnect",BluetoothDevice.class); m.setAccessible(true); m.invoke(mBluetoothHeadset, device);
三、状态判断:
蓝牙耳机连接成功:
mA2dpService.getConnectionState(device) == BluetoothA2dp.STATE_DISCONNECTED && mBluetoothHeadset.getConnectionState(device) == BluetoothProfile.STATE_DISCONNECTED
断开成功:
(mA2dpService.getConnectionState(device) == BluetoothA2dp.STATE_CONNECTED || mA2dpService.getConnectionState(device) == BluetoothA2dp.STATE_PLAYING) && mBluetoothHeadset.getConnectionState(device) == BluetoothProfile.STATE_CONNECTED