蓝牙搜索与SPP协议的连接网上例程很多,就不详细介绍了,官方例程BluetoothChat是很好的例子。不过并不是所有的蓝牙设备都支持SPP协议,连接A2dp和Headset协议能找到的例程不多,本文介绍的方法特别适合于蓝牙音箱和蓝牙耳机的连接。原理主要是利用反射原理得到系统api进行连接,先从配对取消配对框弹出说起:
/** * 配对设备 */ private void doPair(){ mBluetoothAdapter.cancelDiscovery(); if (D) Log.d(TAG, "开始配对"); //配对 if(mDevice.getBondState()!= BluetoothDevice.BOND_BONDED){ try { if (D) Log.d(TAG, "setPin 2 ..."); BluetoothMethod.setPin(mDevice.getClass(), mDevice,"0000"); if (D) Log.d(TAG, "createBond 2 ..."); BluetoothMethod.createBond(mDevice.getClass(), mDevice); } catch (Exception e) { connectfailed(); e.printStackTrace(); } }else{ setState(STATE_CONNECTING); } }
setPin()和createBond()在android系统源码/frameworks/base/core/java/android/bluetooth/BluetoothDevice.java
中能找到。利用反射调用的方法能把这方法得到,
/** * 与设备配对 参考源码:platform/packages/apps/Settings.git * /Settings/src/com/android/settings/bluetooth/CachedBluetoothDevice.java */ static public boolean createBond(Class btClass,BluetoothDevice btDevice) throws Exception { Method createBondMethod = btClass.getMethod("createBond"); Boolean returnValue = (Boolean) createBondMethod.invoke(btDevice); return returnValue.booleanValue(); }
static public boolean setPin(Class btClass, BluetoothDevice btDevice, String str) throws Exception { try { Method removeBondMethod = btClass.getDeclaredMethod("setPin",new Class[]{byte[].class}); Boolean returnValue = (Boolean) removeBondMethod.invoke(btDevice, new Object[] {str.getBytes()}); } catch (SecurityException e) { // throw new RuntimeException(e.getMessage()); e.printStackTrace(); } catch (IllegalArgumentException e) { // throw new RuntimeException(e.getMessage()); e.printStackTrace(); } catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); } return true; }
配对完就可以连接A2dp和Headset协议了,同样利用反射的方法可以得到这两个协议的连接以及断开连接的方法
//A2DP 与 HeadSet static public boolean connect(Class btClass,BluetoothProfile proxy,BluetoothDevice btDevice) throws Exception { Method connectMethod = btClass.getDeclaredMethod("connect", BluetoothDevice.class); connectMethod.setAccessible(true); Boolean returnValue = (Boolean) connectMethod.invoke(proxy,btDevice); return returnValue.booleanValue(); } static public boolean disconnect(Class btClass,BluetoothProfile proxy,BluetoothDevice btDevice) throws Exception { Method disconnectMethod = btClass.getDeclaredMethod("disconnect", BluetoothDevice.class); disconnectMethod.setAccessible(true); Boolean returnValue = (Boolean) disconnectMethod.invoke(proxy,btDevice); return returnValue.booleanValue(); }
/** * @Title:onBluetoothConnected * @Description:实现蓝牙连接A2dp与Headset服务 * @param: */ public void onBluetoothConnect(){ mBluetoothAdapter.getProfileProxy(this, mA2dpProfileListener, BluetoothProfile.A2DP); //new BluetoothA2DP(this).request(this, mBluetoothAdapter); mBluetoothAdapter.getProfileProxy(this, mHeadsetProfileListener, BluetoothProfile.HEADSET); //new BluetoothHeadSetProfile(this).request(this, mBluetoothAdapter); } /** * @Title:onBluetoothDisConnect * @Description:断开A2DP与Headset服务函数 */ public void onBluetoothDisConnect(BluetoothDevice device){ if(mBluetoothA2dp!=null){ try { BluetoothMethod.disconnect(mBluetoothA2dp.getClass(),mBluetoothA2dp, device); mBluetoothAdapter.closeProfileProxy(BluetoothProfile.A2DP, mBluetoothA2dp); } catch (Exception e) { // TODO Auto-generated catch block if (D) Log.d(TAG, "close A2dp failed!!!"); e.printStackTrace(); } } if(mBluetoothHeadset!=null){ try { BluetoothMethod.disconnect(mBluetoothHeadset.getClass(),mBluetoothHeadset, device); mBluetoothAdapter.closeProfileProxy(BluetoothProfile.HEADSET, mBluetoothHeadset); } catch (Exception e) { // TODO Auto-generated catch block if (D) Log.d(TAG, "close Headset failed!!!"); e.printStackTrace(); } } } /** * @Fields mA2dpProfileListener : A2dp服务监听器 */ private BluetoothProfile.ServiceListener mA2dpProfileListener = new BluetoothProfile.ServiceListener() { public void onServiceConnected(int profile, BluetoothProfile proxy) { if (profile == BluetoothProfile.A2DP) { mBluetoothA2dp = (BluetoothA2dp) proxy; if(mState == STATE_CONNECTING){ try { BluetoothMethod.connect(mBluetoothA2dp.getClass(),mBluetoothA2dp, mDevice); } catch (Exception e) { // TODO Auto-generated catch block if (D) Log.d(TAG, "connect to A2dp failed!!!"); mBluetoothAdapter.closeProfileProxy(BluetoothProfile.A2DP, mBluetoothA2dp); e.printStackTrace(); } } } } public void onServiceDisconnected(int profile) { if (profile == BluetoothProfile.A2DP) { mBluetoothA2dp = null; } } }; /** * @Fields mHeadsetProfileListener : BluetoothHeadset服务监听器 */ private BluetoothProfile.ServiceListener mHeadsetProfileListener = new BluetoothProfile.ServiceListener() { public void onServiceConnected(int profile, BluetoothProfile proxy) { if (profile == BluetoothProfile.HEADSET) { mBluetoothHeadset = (BluetoothHeadset) proxy; if(mState == STATE_CONNECTING){ try { BluetoothMethod.connect(mBluetoothHeadset.getClass(),mBluetoothHeadset, mDevice); } catch (Exception e) { // TODO Auto-generated catch block if (D) Log.d(TAG, "connect to Headset failed!!!"); mBluetoothAdapter.closeProfileProxy(BluetoothProfile.HEADSET, mBluetoothHeadset); e.printStackTrace(); } } } } public void onServiceDisconnected(int profile) { if (profile == BluetoothProfile.HEADSET) { mBluetoothHeadset = null; } } };