前段时间项目中用到了bluetoothle 方面的开发,项目结束后总结一下,开发的流程与一些思路;
主要步骤

一:注册蓝牙所需权限

二:Android 6.0 以上权限获取定位权限

三:开启蓝牙

四:注册一个专门处理蓝牙连接的服务

五:activity接收回调

一:注册蓝牙所需权限, 注意一定要注册定位定位权限,Android6.0搜索周围的蓝牙设备,需要位置权限ACCESS_COARSE_LOCATION和ACCESS_FINE_LOCATION 其中的一个,并且将手机的位置服务(定位 GPS)打开。
蓝牙连接和通讯需要获取相关的蓝牙权限BLUETOOTH和BLUETOOTH_ADMIN。
蓝牙权限是normal级权限,只需要在Manifest里面声明即可,不需要判断和处理(测试即使禁用了也不影响蓝牙连接)。

 <uses-permission android:name="android.permission.BLUETOOTH_PRIVILEGED" /><uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" /><uses-permission android:name="android.permission.BLUETOOTH_ADMIN" /><uses-permission android:name="android.permission.BLUETOOTH" /><uses-feature android:name="android.hardware.bluetooth_le" android:required="true" /><uses-feature android:name="android.bluetooth.le" android:required="true" />

二:Android 6.0 以上权限获取定位权限
位置权限是dangerous级权限,除了需要在Manifest里申请之外,还需要在代码中进行动态申请。
ACCESS_COARSE_LOCATION通过WiFi或移动基站获取粗略定位(误差在30~1500米),ACCESS_FINE_LOCATION为GPS精确定位(精度10米以内)。

private void mayRequestLocation() {if (Build.VERSION.SDK_INT >= 23) {int checkCallPhonePermission = ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION);if (checkCallPhonePermission != PackageManager.PERMISSION_GRANTED) {//判断是否需要 向用户解释,为什么要申请该权限if (ActivityCompat.shouldShowRequestPermissionRationale(this, Manifest.permission.ACCESS_COARSE_LOCATION))Toast.makeText(this, R.string.ble_need_location, Toast.LENGTH_LONG).show();ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.ACCESS_COARSE_LOCATION}, 1);return;} else {}} else {}}

三:开启蓝牙

   Intent enableBtIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);startActivityForResult(enableBtIntent, REQUEST_ENABLE);

四:注册一个专门处理蓝牙连接的服务

<service android:name=".ble_server.BLEService" />

import android.app.Service;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothGatt;
import android.bluetooth.BluetoothGattCallback;
import android.bluetooth.BluetoothGattCharacteristic;
import android.bluetooth.BluetoothGattDescriptor;
import android.bluetooth.BluetoothGattServerCallback;
import android.bluetooth.BluetoothGattService;
import android.bluetooth.BluetoothManager;
import android.bluetooth.BluetoothProfile;
import android.bluetooth.le.BluetoothLeScanner;
import android.bluetooth.le.ScanCallback;
import android.bluetooth.le.ScanResult;
import android.content.Context;
import android.content.Intent;
import android.location.LocationManager;
import android.os.Binder;
import android.os.Build;
import android.os.Handler;
import android.os.IBinder;
import android.os.Looper;
import android.util.Log;import static android.bluetooth.BluetoothDevice.TRANSPORT_LE;public class BLEService extends Service {private final static String TAG = "BluetoothLeService";public final static String ACTION_GATT_CONNECTION_NOFIND ="com.example.bluetooth.le.ACTION_GATT_CONNECTION_NOFIND";//蓝牙未找到public final static String ACTION_GATT_CONNECTION_FAIL ="com.example.bluetooth.le.ACTION_GATT_CONNECTION_FAIL";//蓝牙连接错误public final static String ACTION_GATT_CONNECTED ="com.example.bluetooth.le.ACTION_GATT_CONNECTED";//蓝牙已连接public final static String ACTION_GATT_DISCONNECTED ="com.example.bluetooth.le.ACTION_GATT_DISCONNECTED";//蓝牙断开public final static String ACTION_GATT_SERVICES_DISCOVERED ="com.example.bluetooth.le.ACTION_GATT_SERVICES_DISCOVERED";//发现服务,发现可用服务方可判断该蓝牙可用;public final static String ACTION_DATA_AVAILABLE ="com.example.bluetooth.le.ACTION_DATA_AVAILABLE";//接收到Notify通知或者接收到对方发送的内容public final static String EXTRA_DATA ="com.example.bluetooth.le.EXTRA_DATA";//intent回调namepublic final static String ACTION_WRITE_SUCCESSFUL ="com.example.bluetooth.le.WRITE_SUCCESSFUL";//发送成功,但是感觉不太靠谱,就是测试发现返回发送成功,对方扔未收到,不过正常流程就是如此public final static String ACTION_WRITE_FAIL ="com.example.bluetooth.le.WRITE_FAIL";//发送失败public final static String ACTION_GATT_SERVICES_NO_DISCOVERED ="com.example.bluetooth.le.GATT_SERVICES_NO_DISCOVERED";//未发现可用服务public final static String SEND_DATA_TIMEOUT ="com.example.bluetooth.le.SEND_DATA_TIMEOUT";//发送超时public final static String SEND_DATA_FAIL ="com.example.bluetooth.le.SEND_DATA_FAIL";//发送失败public final static String SET_MTU_RESULT ="com.example.bluetooth.le.SET_MTU_RESULT";//MTU设置返回String ecServerId = "0000FFF0-0000-1000-8000-00805F9B34FB";//我们所需服务,此处需要注意,该值需要结合对方蓝牙设备厂商的规约使用String ecWriteCharacteristicId = "0000FFF2-0000-1000-8000-00805F9B34FB";//服务中可用的特征值,依赖于对蓝牙读写的特征值的值;String ecReadCharacteristicId = "0000FFF1-0000-1000-8000-00805F9B34FB";//服务中可用的特征值,依赖于对蓝牙读写的特征值的值;private BluetoothGattCharacteristic mNotifyCharacteristic;//Notify通知特征值,通常通过该特征值接收对方发送的指令,然后有部分会通过专门约定一个read读的特征值,具体要看真实应用场景private BluetoothGattCharacteristic mWriteCharacteristic;//写如特征值,用于发送指令public class LocalBinder extends Binder {public BLEService getService() {return BLEService.this;}}private final IBinder mBinder = new LocalBinder();@Overridepublic IBinder onBind(Intent intent) {return mBinder;}@Overridepublic boolean onUnbind(Intent intent) {offBLECallBack();if (bluetoothGatt != null) {bluetoothGatt.disconnect();}if (bluetoothGatt != null)bluetoothGatt.close();bluetoothGatt = null;Log.e(TAG, "关闭蓝牙服务");return super.onUnbind(intent);}
}BluetoothAdapter bluetoothAdapter = null;BluetoothGatt bluetoothGatt = null;BluetoothManager bluetoothManager;public int bluetoothInit() {//初始化蓝牙
//此处适用于蓝牙连接未断开,重新获取蓝牙,此处我用不上,但也做个记录,有需要的可以启用
//        bluetoothManager = (BluetoothManager) getSystemService(Context.BLUETOOTH_SERVICE);
//        for (BluetoothDevice device : bluetoothManager.getConnectedDevices(7)) {//            Log.e("Bluetoothle Connection", "ConnectedDevices:" + device.getName());
//            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {//                bluetoothGatt = device.connectGatt(BLEService.this, false, bluetoothGattCallback, TRANSPORT_LE);
//            } else {//                bluetoothGatt = device.connectGatt(BLEService.this, false, bluetoothGattCallback);
//            }
//        }if (bluetoothAdapter == null)bluetoothAdapter = BluetoothAdapter.getDefaultAdapter();if (bluetoothAdapter == null) {//设备不支持蓝牙return 1;}if (!isLocServiceEnable(this)) {//定位功能开关未开启return 2;}if (!getBluetoothAdapterState()) {openBluetoothAdapter();//bluetooth is offreturn 3;}if (bluetoothGatt != null) {bluetoothGatt.disconnect();}return 0;}boolean getBluetoothAdapterState() {if (bluetoothAdapter == null) return false;return bluetoothAdapter.isEnabled();}private boolean isLocServiceEnable(Context context) {LocationManager locationManager = (LocationManager) context.getSystemService(Context.LOCATION_SERVICE);boolean gps = locationManager.isProviderEnabled(LocationManager.GPS_PROVIDER);boolean network = locationManager.isProviderEnabled(LocationManager.NETWORK_PROVIDER);return gps || network;}void openBluetoothAdapter() {if (bluetoothAdapter != null) {bluetoothAdapter.enable();}}public boolean isConnect = false;//连接状态,找到读写服务才算正式连接成功;String BleName = "";CountDownTimerUtils mLeScanCountDown;//定时器工具类,此处就不贴代码,自行取我的文章中取public void connect(String BleName) {this.BleName = BleName;if (mLeScanCountDown != null) {mLeScanCountDown.cancel();}mLeScanCountDown = CountDownTimerUtils.getCountDownTimer();mLeScanCountDown.setMillisInFuture(1000 * 20).setFinishDelegate(new CountDownTimerUtils.FinishDelegate() {@Overridepublic void onFinish() {if (!isConnect) {//20秒内未连接成功 1:停止搜索 2:通知activity连接失败
//                            mBLEScanner.stopScan(mScanCallback);bluetoothAdapter.stopLeScan(mLeScanCallback);broadcastUpdate(ACTION_GATT_CONNECTION_NOFIND, null);offBLECallBack();}}}).start();isBLECallBack = true;//开启回调bluetoothManager = (BluetoothManager) getSystemService(Context.BLUETOOTH_SERVICE);for (BluetoothDevice device : bluetoothManager.getConnectedDevices(7)) {//此处为7,具体已经忘却了,但大抵就是搜索BluetoothLe设备Log.e(TAG, "ConnectedDevices:" + device.getName());if (device.getName().equals(BleName))if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {bluetoothGatt = device.connectGatt(BLEService.this, false, bluetoothGattCallback, TRANSPORT_LE);} else {bluetoothGatt = device.connectGatt(BLEService.this, false, bluetoothGattCallback);}}if (bluetoothGatt == null)bluetoothAdapter.startLeScan(mLeScanCallback);
//。      感觉这个方法搜索会慢一点,但也做个记录;
//        mBLEScanner = bluetoothAdapter.getBluetoothLeScanner();
//        mBLEScanner.startScan(mScanCallback);}BluetoothAdapter.LeScanCallback mLeScanCallback =new BluetoothAdapter.LeScanCallback() {@Overridepublic void onLeScan(final BluetoothDevice device, int rssi, byte[] scanRecord) {String deviceName = device.getName();Log.i(TAG, "Connection deviceName" + device.getName());//此处需要可以将搜索到的蓝牙回调给activity,我的项目中用不懂,需要自己去开发,逻辑也是跟其他回调一样;if (!Utils.isEmpty(device.getName()) && deviceName.equals(BleName)) {//根据蓝牙名称连接设备if (mLeScanCountDown != null) {//关闭超时,也可以在发现服务后关闭超时mLeScanCountDown.cancel();}bluetoothAdapter.stopLeScan(mLeScanCallback);Log.i(TAG, "停止搜索 搜索到匹配蓝牙 " + deviceName + " Address:" + device.getAddress());isBLECallBack = true;//开启通知/*** 其中TRANSPORT_LE参数是设置传输层模式* 传输层模式有三种TRANSPORT_AUTO 、TRANSPORT_BREDR 和TRANSPORT_LE。* 如果不传默认TRANSPORT_AUTO,6.0系统及以上需要使用TRANSPORT_LE这种传输模式,* 具体为啥,我也不知道,我猜是因为Android6.0及以上系统重新定义了蓝牙BLE的传输模式必须使用TRANSPORT_LE这种方式吧。*/if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {bluetoothGatt = device.connectGatt(BLEService.this, false, bluetoothGattCallback, TRANSPORT_LE);} else {bluetoothGatt = device.connectGatt(BLEService.this, false, bluetoothGattCallback);}}}};BluetoothLeScanner mBLEScanner;ScanCallback mScanCallback = new ScanCallback() {@Overridepublic void onScanResult(int callbackType, ScanResult result) {super.onScanResult(callbackType, result);BluetoothDevice device = result.getDevice();String deviceName = device.getName();Log.i("Bluetoothle Connection", "deviceName" + device.getName());if (!KHDataUtils.isEmpty(device.getName()) && deviceName.equals(BleName)) {//根据蓝牙名称连接设备if (mLeScanCountDown != null) {mLeScanCountDown.cancel();}mBLEScanner.stopScan(this);Log.i(TAG, "停止搜索 搜索到匹配蓝牙 " + (KHDataUtils.isEmpty(deviceName) ? "null name" : deviceName) + " Address:" + device.getAddress());isBLECallBack = true;//开启通知/*** 其中TRANSPORT_LE参数是设置传输层模式* 传输层模式有三种TRANSPORT_AUTO 、TRANSPORT_BREDR 和TRANSPORT_LE。* 如果不传默认TRANSPORT_AUTO,6.0系统及以上需要使用TRANSPORT_LE这种传输模式,* 具体为啥,我也不知道,我猜是因为Android6.0及以上系统重新定义了蓝牙BLE的传输模式必须使用TRANSPORT_LE这种方式吧。*/if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {bluetoothGatt = device.connectGatt(BLEService.this, false, bluetoothGattCallback, TRANSPORT_LE);} else {bluetoothGatt = device.connectGatt(BLEService.this, false, bluetoothGattCallback);}}}@Overridepublic void onBatchScanResults(List<ScanResult> results) {super.onBatchScanResults(results);}@Overridepublic void onScanFailed(int errorCode) {super.onScanFailed(errorCode);}};
BluetoothGattCallback bluetoothGattCallback = new BluetoothGattCallback() {@Overridepublic void onConnectionStateChange(BluetoothGatt gatt, int status, int newState) {super.onConnectionStateChange(gatt, status, newState);Log.e(TAG, "onConnectionStateChange status=" + status + "|" + "newState=" + newState);if (status != BluetoothGatt.GATT_SUCCESS) { //连接失败isConnect = false;broadcastUpdate(ACTION_GATT_CONNECTION_FAIL, null);}if (newState == BluetoothProfile.STATE_CONNECTED) { //连接成功Log.i(TAG, "已连接到GATT服务器,正在尝试启动服务发现"); broadcastUpdate(ACTION_GATT_CONNECTED, null);bluetoothGatt.discoverServices();// 尝试在成功连接后发现服务。}if (newState == BluetoothProfile.STATE_DISCONNECTED) { //连接断开isConnect = false;if (bluetoothGatt != null) {Log.e(TAG,"Bluetoothle Connection 关闭蓝牙连接");bluetoothGatt.close();bluetoothGatt = null;}broadcastUpdate(ACTION_GATT_DISCONNECTED, null);offBLECallBack();}}@Overridepublic void onServicesDiscovered(BluetoothGatt gatt, int status) {super.onServicesDiscovered(gatt, status);bluetoothGatt = gatt;List<BluetoothGattService> bluetoothGattServices = gatt.getServices();if (bluetoothGattServices != null) {for (BluetoothGattService item : bluetoothGattServices) {Log.e(TAG, "UUID=:" + item.getUuid().toString());}}BluetoothGattService service = gatt.getService(UUID.fromString(ecServerId));if (service == null) {Log.e("Bluetoothle service", "未找到定制服务");return;
//                isConnect = false;
//                broadcastUpdate(ACTION_GATT_SERVICES_NO_DISCOVERED, null);
//                offBLECallBack();
//                closeBLEConnection();}//找到服务,继续查找特征值mNotifyCharacteristic = service.getCharacteristic(UUID.fromString(ecReadCharacteristicId));mWriteCharacteristic = service.getCharacteristic(UUID.fromString(ecWriteCharacteristicId));if (mNotifyCharacteristic != null && mWriteCharacteristic != null) {isConnect = true;broadcastUpdate(ACTION_GATT_SERVICES_DISCOVERED, null);//使能NotifynotifyBLECharacteristicValueChange(ecServerId, ecReadCharacteristicId);//心跳监听,按需启用
//                new Handler(Looper.getMainLooper()).post(new Runnable() {//开始监听心跳
//                    @Override
//                    public void run() {//                        if (mHeartBeatTimeOut != null) {//清理上次的倒计时
//                            mHeartBeatTimeOut.cancel();
//                        } else {//                            //创建一个1分钟的倒计时,一分钟内未监听到蓝牙,主动断开
//                            mHeartBeatTimeOut = CountDownTimerUtils
//                                    .getCountDownTimer();
//                        }
//                        mHeartBeatTimeOut.setMillisInFuture(1000 * 60)
//                                .setFinishDelegate(new CountDownTimerUtils.FinishDelegate() {//                                    @Override
//                                    public void onFinish() {//                                        Log.i("心跳", "心跳超时,关闭蓝牙");
//                                        closeBLEConnection();
//                                    }
//                                }).start();
//                    }
//                });new Thread(() -> {try {Thread.sleep(200);setMtu(500);} catch (InterruptedException e) {e.printStackTrace();}}).start();//设置MTU需要隔一段时间后,否则会设置失败;}if (mWriteCharacteristic == null || mNotifyCharacteristic == null) //适配没有可用特征值{isConnect = false;broadcastUpdate(ACTION_GATT_CONNECTION_FAIL, null);offBLECallBack();closeBLEConnection();}}@Overridepublic void onCharacteristicChanged(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic) {super.onCharacteristicChanged(gatt, characteristic);byte[] bytes = characteristic.getValue();if (bytes != null) {Log.e("Bluetoothle receive", "读取成功[hex]:" + bytesToHexString(bytes));//initFrameAssembly(bytes);//对接收到的数据进行处理,如因mtu原因指令被分包,或者两包粘在一起}}//        @Override
//        public void onCharacteristicRead(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic, int status) {//            通过读取特征值接收指令消息,我用的是notify通知接收,所以屏蔽,可根据实际启用
//            super.onCharacteristicRead(gatt, characteristic, status);
//            byte[] bytes = characteristic.getValue();
//            if (bytes != null) {//                Log.e("bluetoothle receive", "读取成功[hex]:" + bytesToHexString(bytes));
//                initFrameAssembly(bytes);
//            }
//        }@Overridepublic void onCharacteristicWrite(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic, int status) {Log.e(TAG, "sendMsg success " + status);//感觉不够靠谱,所以没有使用super.onCharacteristicWrite(gatt, characteristic, status);if (status == BluetoothGatt.GATT_SUCCESS) {} else {}}@Overridepublic void onMtuChanged(BluetoothGatt gatt, int mtu, int status) {super.onMtuChanged(gatt, mtu, status);if (BluetoothGatt.GATT_SUCCESS == status) {Log.e("Bluetoothle Mtu", "onMtuChanged success MTU = " + mtu);if (mtu - 7 > sendSize)sendSize = mtu - 7;} else {Log.e("Bluetoothle Mtu", "onMtuChanged fail ");}broadcastUpdate(SET_MTU_RESULT, null);}};
/*** 读使能** @param serviceId* @param characteristicId* @return*/boolean notifyBLECharacteristicValueChange(String serviceId, String characteristicId) {BluetoothGattService service = bluetoothGatt.getService(UUID.fromString(serviceId));if (service == null) {return false;}BluetoothGattCharacteristic characteristicRead = service.getCharacteristic(UUID.fromString(characteristicId));boolean res = bluetoothGatt.setCharacteristicNotification(characteristicRead, true);if (!res) {return false;}for (BluetoothGattDescriptor dp : characteristicRead.getDescriptors()) {dp.setValue(BluetoothGattDescriptor.ENABLE_NOTIFICATION_VALUE);bluetoothGatt.writeDescriptor(dp);}return true;}public void writeData(byte[] data) {//实际下发指令消息的地方if (bluetoothGatt == null)return;BluetoothGattService service = bluetoothGatt.getService(UUID.fromString(ecServerId));if (service == null)return;BluetoothGattCharacteristic characteristicWrite = service.getCharacteristic(UUID.fromString(ecWriteCharacteristicId));if (characteristicWrite == null) {Log.d(TAG, "sendMsg: writeData " + "特征值为空 " + HexStrUtil.bytesToHexString(data));}characteristicWrite.setValue(data);if (bluetoothGatt.writeCharacteristic(characteristicWrite)) {Log.d(TAG, "sendMsg: writeData " + "下发帧数据: " + HexStrUtil.bytesToHexString(data));broadcastUpdate(ACTION_WRITE_SUCCESSFUL, data);} else {Log.e(TAG, "sendMsg: writeData " + "下发帧数据失败: " + HexStrUtil.bytesToHexString(data));broadcastUpdate(ACTION_WRITE_FAIL, data);}}int sendSize = 20;//分包长度大小,此值可以在设置MTU后根据MTU值设置;public void sendData(byte[] sendMsgBytes) {byte[] subpackage = null;int index = 0;for (int i = 0; i < sendMsgBytes.length; i++) {if (index == 0) {subpackage = new byte[sendMsgBytes.length - i < sendSize ? sendMsgBytes.length - i : sendSize];}subpackage[index] = sendMsgBytes[i];index = index + 1;if (index == sendSize || i + 1 == sendMsgBytes.length) {byte[] finalSubpackage = subpackage;try {Thread.sleep(20);} catch (InterruptedException e) {e.printStackTrace();}writeData(finalSubpackage);index = 0;}}}HashMap<String, CountDownTimerUtils> replyCountDownTimer;public void sendMsg(byte[] sendMsgBytes) {//此处时为了防止发送的指令没有返回相应的回复指令,不需要的可用replyMsg(byte[] sendMsgBytes)if (sendMsgBytes.length > sendSize) {sendData(sendMsgBytes);} else {writeData(sendMsgBytes);}if (replyCountDownTimer == null)replyCountDownTimer = new HashMap<>();int functionCode = FunctionCode.getReplyFunctionCode(sendMsgBytes[4] & 0xff);//根据下发指令的code获取回复指令的对应code;例如 发0x01 回复0x81 ,记得在收到指令消息后删掉对应的replyCountDownTimerif (functionCode == 0)return;CountDownTimerUtils mCountDown = CountDownTimerUtils.getCountDownTimer();mCountDown.setMillisInFuture(1000 * 5).setFinishDelegate(new CountDownTimerUtils.FinishDelegate() {@Overridepublic void onFinish() {broadcastUpdate(SEND_DATA_TIMEOUT, sendMsgBytes);}}).start();if (replyCountDownTimer.containsKey(functionCode + ""))replyCountDownTimer.get(functionCode + "").cancel();replyCountDownTimer.put(functionCode + "", mCountDown);}public void replyMsg(byte[] replyMsgBytes) {if (replyMsgBytes.length > sendSize) {sendData(replyMsgBytes);} else {writeData(replyMsgBytes);}}
void setMtu(int v) {if (bluetoothGatt != null && Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {bluetoothGatt.requestMtu(v);}}boolean isBLECallBack = false;//是否回调统一开关public void onBLECallBack() {Log.e(TAG, "Connection: offBLECallBack 接收监听回调");isBLECallBack = true;}public void offBLECallBack() {Log.e(TAG, "Connection: offBLECallBack 取消监听回调");isBLECallBack = false;}private void broadcastUpdate(final String action, byte[] data) {if (isBLECallBack) {final Intent intent = new Intent(action);if (data != null)intent.putExtra(EXTRA_DATA, data);sendBroadcast(intent);}}
String bytesToHexString(byte[] bytes) {if (bytes == null) return "";StringBuilder str = new StringBuilder();for (byte b : bytes) {str.append(String.format("%02X", b));//每个字节用空格隔开}return str.toString();}

五:activity中bindserver 并接收回调
bindserver

        startWaiting("蓝牙连接中");Intent gattServiceIntent = new Intent(this, BLEService.class);bindService(gattServiceIntent, mServiceConnection, BIND_AUTO_CREATE);if (mGattUpdateReceiver != null)registerReceiver(mGattUpdateReceiver, makeGattUpdateIntentFilter());initBleMenu();

在bindserver成功后初始化蓝牙

// Code to manage Service lifecycle.private final ServiceConnection mServiceConnection = new ServiceConnection() {@Overridepublic void onServiceConnected(ComponentName componentName, IBinder service) {mBLEService = ((BLEService.LocalBinder) service).getService();Connection();}@Overridepublic void onServiceDisconnected(ComponentName componentName) {mBLEService = null;}};void Connection() {startWaiting("蓝牙连接中");int res = mBLEService.bluetoothInit();if (res == 1) {KHToast.warning("该设备不支持蓝牙");finishEx();return;}if (res == 2) {KHToast.warning("定位功能未开启");finishEx();return;}if (res == 3) {KHToast.warning("蓝牙未开启");Intent enableBtIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);startActivityForResult(enableBtIntent, REQUEST_ENABLE);return;}mBLEService.connect("蓝牙名称");//我的项目是需要连接已知的蓝牙名称的设备,如果需要返回搜索到的蓝牙列表,需要在BLEService中通过BluetoothAdapter.LeScanCallback将名称返回,并创建一个arrayList;}

声明IntentFilter对象

    private static IntentFilter makeGattUpdateIntentFilter() {final IntentFilter intentFilter = new IntentFilter();intentFilter.addAction(BLEService.ACTION_GATT_CONNECTED);intentFilter.addAction(BLEService.ACTION_GATT_DISCONNECTED);intentFilter.addAction(BLEService.ACTION_GATT_SERVICES_DISCOVERED);intentFilter.addAction(BLEService.ACTION_DATA_AVAILABLE);intentFilter.addAction(BLEService.ACTION_WRITE_SUCCESSFUL);intentFilter.addAction(BLEService.ACTION_GATT_SERVICES_NO_DISCOVERED);intentFilter.addAction(BLEService.ACTION_GATT_CONNECTION_NOFIND);intentFilter.addAction(BLEService.SEND_DATA_TIMEOUT);intentFilter.addAction(BLEService.SET_MTU_RESULT);return intentFilter;}

接收回调

BLEService mBLEService;
private final BroadcastReceiver mGattUpdateReceiver = new BroadcastReceiver() {@Overridepublic void onReceive(Context context, Intent intent) {final String action = intent.getAction();if (BLEService.ACTION_GATT_SERVICES_NO_DISCOVERED.equals(action)) {Log.i("BluetoothLeService", " Connection 连接失败:特征码未找到 主动断开蓝牙");mBLEService.closeBLEConnection();} else if (BLEService.ACTION_GATT_SERVICES_NO_DISCOVERED.equals(action)) {Log.i("BluetoothLeService", "连接失败:服务未找到 主动断开蓝牙");mBLEService.closeBLEConnection();} else if (BLEService.ACTION_GATT_CONNECTION_NOFIND.equals(action)) {Log.i("BluetoothLeService","连接失败:蓝牙未找到");} else if (BLEService.ACTION_GATT_CONNECTED.equals(action)) {Log.i("BluetoothLeService","连接成功:无特征码");} else if (BLEService.ACTION_GATT_DISCONNECTED.equals(action)) {Log.i("BluetoothLeService","蓝牙断开连接");} else if (BLEService.ACTION_GATT_SERVICES_DISCOVERED.equals(action)) {Log.i("BluetoothLeService","连接成功");} else if (BLEService.SET_MTU_RESULT.equals(action)) {Log.i("BluetoothLeService","MTU设置成功");} else if (BLEService.ACTION_DATA_AVAILABLE.equals(action)) {//收到消息final byte[] receiveData = intent.getByteArrayExtra(BLEService.EXTRA_DATA);Log.i("BluetoothLeService","收到消息");} else if (BLEService.ACTION_WRITE_SUCCESSFUL.equals(action)) {Log.i("BluetoothLeService", "Write Finish");} else if (BLEService.SEND_DATA_TIMEOUT.equals(action)) {final byte[] retransmissionData = intent.getByteArrayExtra(BLEService.EXTRA_DATA);Log.v("BluetoothLeService", "回复超时 重新发送");int functionCode = retransmissionData[4] & 0xff;if (functionCode == LOGIN_APP2PILE) {loginNum = loginNum + 1;if (loginNum == 7) {loginNum = 0;mBLEService.closeBLEConnection();} else {mBLEService.sendMsg(retransmissionData);}} else {mBLEService.sendMsg(retransmissionData);}}}};

在有需要时候offBLECallBack取消监听回调

if (mBLEService != null) {mBLEService.offBLECallBack();
}

先总结至此,因为都是从项目中的代码摘出来的,可能存在一些错误,但步骤上应该是没有问题的;

未解决的问题:当BLEService unbind时会将已连接的蓝牙断开,偶尔会出现实际没断开的情况,坑爹的是:断开和未断开所经历的流程都是一样的,就是偶尔会出现,而且只有关闭蓝牙或用系统的杀死进程才会释放连接。因为对项目影响也不大,后续也就没有过于纠结于此,但在此还是希望有相关处理经验的大神能够分享一下原因和解决办法;

Android 蓝牙 bluetoothle 开发相关推荐

  1. Android 蓝牙通信开发

    Android 蓝牙通信开发 Receiver的设置 一.Receiver1(蓝牙状态的改变通过广播接收) 二.Receiver2(蓝牙搜索到设备.绑定设备(配对)通过广播接收) 服务端代码 客户端代 ...

  2. Android 蓝牙BLE开发详解

    Android 蓝牙BLE开发详解 由于年初接手了个有关蓝牙BLE的项目,开始了对蓝牙ble的学习,经过长时间的慢慢学习(学得太慢,太拖了),终于了解了该怎么写蓝牙BLE,现在就给大家分享一下. 一. ...

  3. Qt on Android 蓝牙通信开发

    版权声明:本文为MULTIBEANS ORG研发跟随文章,未经MLT ORG允许不得转载. 最近做项目,需要开发安卓应用,实现串口的收发,目测CH340G在安卓手机上非常麻烦,而且驱动都是Java版本 ...

  4. Android蓝牙BLE开发

    最近正在研究Android的蓝牙BLE开发学习,以下是自己做的个人总结 1.1何为BLE? 首先得说明什么是低功耗蓝牙BLE,BLE的全称为Bluetooth low energy(或称Blooth ...

  5. Android蓝牙手柄开发

    手柄相应的按键 摇杆监听(已连接状态) 通过google找到官方示例https://developer.android.com/training/game-controllers/controller ...

  6. Android 蓝牙Hid开发

    原文地址: https://blog.csdn.net/VNanyesheshou/article/details/61914974 Demo下载:http://www.demodashi.com/d ...

  7. Android蓝牙BLE开发(一)-基本原理

    公司有需求要做蓝牙BLE传输,经查阅后发现关于BLE开发的知识还真不多.对于BLE开发的同学来说,我的建议是先快速了解一下BLE的基本原理,磨刀不误砍柴工. 什么是BLE BLE全称Bluetooth ...

  8. android蓝牙通讯方法,Android蓝牙通信开发教程(详解版)

    Android 系统提供蓝牙 API 包 android.bluetooth,允许手机设备通过蓝牙与其他设备进行无线连接. Android 的蓝牙 API 可提供以下功能: 需要说明的是,Androi ...

  9. Android 蓝牙游戏开发(一)

    蓝牙4.0 据说是超低功耗,随之而来的是智能手表.手环.同屏对战塔防等.咱也了解了解相关的技术,做技术储备.今天需要总结的是蓝牙聊天的例子,例子来源于Android的官网.我们把关键的技术理一下. 关 ...

最新文章

  1. win2003辅助域服务器相关几个错误日志的解决办法
  2. 最先进的图像分类算法:FixEfficientNet-L2
  3. 关于贝叶斯统计的一点总结
  4. EOS净流入超3亿,比特币继续震荡盘整
  5. JQuery对checkbox的操作
  6. 利用ISCSI存储技术构建IP存储网络(安全篇)
  7. Redis的常用命令——String的常用命令
  8. shell中if 变量里包含字符串的判断
  9. CMake2:版本号配置与头文件生成
  10. Spark RDD使用详解4--Key-Value型Transformation算子
  11. python中字典和json的区别_详解python中的json和字典dict
  12. c语言函数可变长参数,一种使用变长参数为C程序构造灵活回调函数的方法
  13. 漏洞扫描与云服务器的安全防护
  14. 计算机考试祝福,考试前说的祝福语汇编35句 参加考试前的祝福语
  15. 拿下 ACM 金牌!
  16. Apache Hadoop大数据集群及相关生态组件安装
  17. Unity学习笔记:Tilemap的基础使用【By Chutianbo】
  18. 补天发动 3万多名白帽子找漏洞情报,这次有什么不一样
  19. 按月显示的万年历(含农历)网页代码
  20. python鸭子类型与协议理解

热门文章

  1. 就地执行Windows Server2022升级
  2. 曼格短视频源码包微信小程序
  3. 各种VBA excel 命令、属性、方法
  4. python一般安装哪个盘_python要安装在哪个盘
  5. 应用程序正常初始化失败(0xc150002)失败。请单击“确定”,终止应用程序
  6. c语言按键模式切换,二、Windows按键消息—键的先前状态、转换状态、位移状态...
  7. C库函数中一些常用的常量值
  8. 【Nvidia DeepStream5.0】Gst-nvtracker插件功能说明
  9. Spread.js 上下级关系
  10. Rey英文版主题-时尚与服装商城主题-WordPress响应式