最近做一个项目,主要是给蓝牙发送指令的,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蓝牙连接机型不一样,稳定性也不一样,连接的速度也不一样,弄的我焦头烂额的.