最近做一个项目,主要是给蓝牙发送指令的,boss要求能够最快速度的搜索到蓝牙,并且发送数据.
刚开始也遇到很多133,各种断开连接的问题.android蓝牙搜索有两种方式,一种startLeScan,另一种startDiscovery.因为项目要讲究搜索蓝牙的速度,一开始我一直用的startDiscovery,,但是这个搜索的速度有的手机太慢了,有的手机会达到5-6秒,不能满足需求,后面又尝试了startLeScan,发现搜索速度很快,基本上1秒以内都能搜索到需要的蓝牙.但是startLeScan这个方法,搜索到的蓝牙有的机型会拿不到蓝牙的名称,因为项目是根据蓝牙名称来匹配的,这就很尴尬,拿不到名称就匹配不了,搜到了也没用.
因为考虑到startLeScan搜到的速度很快,但只是小部分机型拿不到设备名称,所有就尝试了新的方法.先用旧的方法搜索蓝牙,在1000ms以内搜不到想要的蓝牙设备名称,就用startDiscovery方法来搜索.
private BluetoothAdapter mBtAdapter;
public void judgeBluth() { if (mBtAdapter == null) mBtAdapter = BluetoothAdapter.getDefaultAdapter(); if (!mBtAdapter.isEnabled()) { Intent enableIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE); startActivity(enableIntent); }else{ checkGPSPermission(); } }
@Override public void GPSsure() { if(mBtAdapter==null){ CommonUtils.showToast(this,"设备上没有发现有蓝牙设备"); return; } if(!mBtAdapter.isEnabled()){//开启蓝牙设备 mBtAdapter.enable(); return; } if(MyUtils.newInstance().getBluetoothDevice()!=null){ connect(MyUtils.newInstance().getBluetoothDevice()); }else{ mBtAdapter.startLeScan(mLeScanCallback); mHandler.postDelayed(new Runnable() {//1000ms后没有搜索到,用新方法 @Override public void run() { if(!isGet){ mBtAdapter.stopLeScan(mLeScanCallback); IntentFilter mFilter = new IntentFilter(BluetoothDevice.ACTION_FOUND); registerReceiver(mReceiver, mFilter); // 注册搜索完时的receiver IntentFilter mFilter1 = new IntentFilter(BluetoothAdapter.ACTION_DISCOVERY_FINISHED); registerReceiver(mReceiver, mFilter1); isNew = true; mBtAdapter.startDiscovery(); } } },1000); } }
private volatile boolean isGet = false; private BluetoothAdapter.LeScanCallback mLeScanCallback = new BluetoothAdapter.LeScanCallback() { @Override public void onLeScan(final BluetoothDevice device, final int rssi, byte[] scanRecord) { if(isGet)return; if (device.getBondState() != BluetoothDevice.BOND_BONDED) { if((device.getName()!=null&&bean.getBluetooth().equals(device.getName()))||(MyUtils.newInstance().getMac()!=null&&device.getAddress().equals(MyUtils.newInstance().getMac()))){ isGet = true; mBtAdapter.stopLeScan(mLeScanCallback); mHandler.post(new Runnable() { @Override public void run() { connect(device); } }); SharedPreferencesUtil.addBluetoothMac(SuccessActivity.this,device.getAddress()); break; } } } } }; private boolean isNew = false; private BroadcastReceiver mReceiver = new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { if(isGet)return; String action = intent.getAction(); // 获得已经搜索到的蓝牙设备 if (action.equals(BluetoothDevice.ACTION_FOUND)) { BluetoothDevice device = intent .getParcelableExtra(BluetoothDevice.EXTRA_DEVICE); // 搜索到的不是已经绑定的蓝牙设备 if (device.getBondState() != BluetoothDevice.BOND_BONDED) { for (int i = 0; i < str.size(); i++) { UserBean bean = str.get(i); if((device.getName()!=null&&bean.getBluetooth().equals(device.getName()))||(MyUtils.newInstance().getMac()!=null&&device.getAddress().equals(MyUtils.newInstance().getMac()))){ isGet = true; handlerSendString("搜到蓝牙新",System.currentTimeMillis()); if(mBtAdapter.isDiscovering()){ mBtAdapter.cancelDiscovery(); } connect(device); } } } // 搜索完成 } else if (action.equals(BluetoothAdapter.ACTION_DISCOVERY_FINISHED)) { if(mBtAdapter==null)return; if(mBtAdapter.isDiscovering()){ mBtAdapter.cancelDiscovery();//关闭搜索 } if(!isGet){//未搜索到相关蓝牙 handlerSendString("未搜索到蓝牙",System.currentTimeMillis()); } } } }; public boolean refreshDeviceCache(BluetoothGatt mBluetoothGatt) { if (mBluetoothGatt != null) { try { Method localMethod = mBluetoothGatt.getClass().getMethod( "refresh", new Class[0]); if (localMethod != null) { boolean bool = ((Boolean) localMethod.invoke( mBluetoothGatt, new Object[0])).booleanValue(); return bool; } } catch (Exception localException) { } } return false;}
搜索到蓝牙后就开始连接蓝牙了,这里连接我刚开始写的时候,出现很多问题,这里就不一一说了,有的时候会出现开始连接之后就直接断开连接,有的时候又连接不上,有的时候又会发现不了服务,所以我在连接断开的情况下尝试了重新连接.
public volatile int isConnect = 0; private BluetoothGatt gatts; public void connect(final BluetoothDevice device){ if(isConnect ==1||isConnect==2||isConnect==3){//防止重复连接的情况 return; } if(gatts!=null){ isConnect = 0; gatts.close(); gatts = null; } handlerSendString("开始连接",System.currentTimeMillis()); gatts = device.connectGatt(this, false, new BluetoothGattCallback() { @Override public void onConnectionStateChange(BluetoothGatt gatt, int status, int newState) { if (newState == BluetoothGatt.STATE_CONNECTED) { gatt.discoverServices(); handlerSendString("连接成功",System.currentTimeMillis()); isConnect = 1; } else { handlerSendString("断开连接"+"--code:"+newState,System.currentTimeMillis()); refreshDeviceCache(gatt); gatt.close(); gatt=null; if(isConnect == 2||isConnect ==0){//未发现蓝牙服务,连接直接断开,没有写入数据,重新连接 mHandler.postDelayed(new Runnable() { @Override public void run() { connect(device); } },100); } isConnect = 0; } } @Override public void onServicesDiscovered(final BluetoothGatt gatt, int status) { isConnect = 2; handlerSendString("发现服务",System.currentTimeMillis()); List<BluetoothGattService> services = gatt.getServices(); boolean is = true; for (int i = services.size()-1; i >= 0; i--) { BluetoothGattService service = services.get(i); if(service.getUuid().toString().equals(MyUtils.service_uuid)){ List<BluetoothGattCharacteristic> characteristics = service.getCharacteristics(); BluetoothGattCharacteristic characteristic = characteristics.get(characteristics.size()-1); characteristic.setValue(MyUtils.a); gatt.setCharacteristicNotification(characteristic,false); handlerSendString("发送指令",System.currentTimeMillis()); gatt.writeCharacteristic(characteristic); is = false; break; } } if(is){ handlerSendString("未检测到蓝牙服务",System.currentTimeMillis()); gatt.disconnect(); } } @Override public void onCharacteristicWrite(final BluetoothGatt gatt, BluetoothGattCharacteristic characteristic, int status) { isConnect = 3; if(status == BluetoothGatt.GATT_SUCCESS){//写入成功 handlerSendString("写入成功",System.currentTimeMillis()); }else if (status == BluetoothGatt.GATT_FAILURE){ Log.e("onCharacteristicWrite中", "写入失败"); }else if (status == BluetoothGatt.GATT_WRITE_NOT_PERMITTED){ Log.e("onCharacteristicWrite中", "没权限"); } mHandler.postDelayed(new Runnable() { @Override public void run() { gatt.disconnect(); } },200); } }); }
@Override protected void onDestroy() { if(isNew)unregisterReceiver(mReceiver); super.onDestroy(); }
这些就是我这个项目的时候,尝试了多次的之后的代码,还有需要完善的地方希望有大神能多多指教.
最后总结了一下,android蓝牙连接需要定位的,有的机型如果没有请求定位权限的话,会出现找不到蓝牙,找不到服务的情况.
android蓝牙连接机型不一样,稳定性也不一样,连接的速度也不一样,弄的我焦头烂额的.