美文网首页
2020-04-13

2020-04-13

作者: Zengming | 来源:发表于2020-04-13 16:36 被阅读0次
    package com.example.test;
    
    import android.app.Activity;
    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.BluetoothGattService;
    import android.bluetooth.BluetoothManager;
    import android.bluetooth.BluetoothProfile;
    import android.content.BroadcastReceiver;
    import android.content.Context;
    import android.content.Intent;
    import android.content.IntentFilter;
    import android.os.Handler;
    import android.util.Log;
    import android.widget.Toast;
    
    import java.util.ArrayList;
    import java.util.List;
    import java.util.UUID;
    
    /**
     * Author: ming.zeng
     * Date: 9/4/2020 下午 6:28
     * Desc: 蓝牙工具类
     */
    public class BLEUtils {
    
        public static final String TAG = "BLEUtils";
    
        public static final String SERVICE_UUID = "00001204-0000-1000-8000-00805f9b34fb";
        public static final String CHARACTER_UUID = "00001204-0000-1000-8000-00805f9b34fb";
    
        private BluetoothManager manager;
        private BluetoothAdapter mBluetoothAdapter;
    
        //打开蓝牙的请求码
        public static final int REQUEST_ENABLE_BLUETOOTH = 10010;
    
        //是否正在扫描蓝牙设备
        private boolean mScanning = false;
        //设置扫描时长
        private static final long SCAN_PERIOD = 10000;
    
        //蓝牙扫描的返回
        private BluetoothAdapter.LeScanCallback leScanCallback;
        //蓝牙设别的list
        private List<BluetoothDevice> bluetoothDeviceList = new ArrayList<BluetoothDevice>();
    
        private Handler mHandler = new Handler();
    
        private LeScanListener leScanListener;
    
        //蓝牙当前连接的设备
        private BluetoothDevice mBluetoothDevice;
        private BluetoothGattCharacteristic characteristic;
        private BluetoothGatt mBluetoothGatt;
    
        private BLEUtils() {
    
        }
    
        private static class BLEUtilsHelper {
            static BLEUtils instance = new BLEUtils();
        }
    
        public static BLEUtils getInstance() {
            return BLEUtilsHelper.instance;
        }
    
        public void init(Activity activity) {
            manager = (BluetoothManager) activity.getSystemService(Context.BLUETOOTH_SERVICE);
            if (manager != null) {
                mBluetoothAdapter = manager.getAdapter();
    
                //蓝牙搜索的回调
                leScanCallback = new BluetoothAdapter.LeScanCallback() {
                    @Override
                    public void onLeScan(BluetoothDevice device, int rssi, byte[] scanRecord) {
                        if (device.getName() != null) {
                            if (!bluetoothDeviceList.contains(device)) {//去下重
                                bluetoothDeviceList.add(device);
                            }
                            if (null != leScanListener) {
                                //返回所有列表
                                leScanListener.leScanCallBack(bluetoothDeviceList);
                            }
    
                            Log.e(TAG, "scan--" + device.getName());
                        }
                    }
                };
    
                //判断蓝牙是否正常开启
                if ((mBluetoothAdapter == null) || !mBluetoothAdapter.isEnabled()) {
                    //打开蓝牙
                    Intent enableIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
                    activity.startActivityForResult(enableIntent, REQUEST_ENABLE_BLUETOOTH);
                } else {
                    scanLeDevice(true);
                }
            }
        }
    
        /**
         * 开始(true)或结束(false)蓝牙扫描
         *
         * @param enable
         */
        private void scanLeDevice(final boolean enable) {
            if (enable && !mScanning) {
                // 预先定义停止蓝牙扫描的时间(因为蓝牙扫描需要消耗较多的电量)
                mHandler.postDelayed(new Runnable() {
                    @Override
                    public void run() {
                        mScanning = false;
                        mBluetoothAdapter.stopLeScan(leScanCallback);
                    }
                }, SCAN_PERIOD);
    
                mScanning = true;
                // 定义一个回调接口供扫描结束处理
                mBluetoothAdapter.startLeScan(leScanCallback);
            } else {
                mScanning = false;
                mBluetoothAdapter.stopLeScan(leScanCallback);
            }
        }
    
        /**
         * 开始搜索蓝牙设备
         *
         * @param leScanListener 搜索蓝牙设备的回调(返回设备列表)
         */
        public void startScanLeDevice(final LeScanListener leScanListener) {
            bluetoothDeviceList.clear();
            this.leScanListener = leScanListener;
            scanLeDevice(true);
        }
    
        /**
         * 停止搜索设备
         */
        public void stopScanLeDevice() {
            if (leScanCallback == null)
                return;
            scanLeDevice(false);
        }
    
        /**
         * 搜索蓝牙的回调
         */
        public interface LeScanListener {
            void leScanCallBack(List<BluetoothDevice> bluetoothDeviceList);
        }
    
        /**
         * 得到BluetoothGatt
         *
         * @param device                设备
         * @param autoConnect           是否自动链接
         * @param bluetoothGattCallback 回调
         */
        public BluetoothGatt getConnectGatt(Context context, BluetoothDevice device, boolean autoConnect,
                                            BluetoothGattCallback bluetoothGattCallback) {
            this.mBluetoothDevice = device;
            return device.connectGatt(context, autoConnect, bluetoothGattCallback);
        }
    
        public void getConnectGatt(Context context, BluetoothDevice bluetoothDevice) {
            mBluetoothDevice = bluetoothDevice;
            if (bluetoothDevice != null) {
                //第二个参数 是否重连
                mBluetoothGatt = bluetoothDevice.connectGatt(context, false, bluetoothGattCallback);
            }
        }
    
        /**
         * 蓝牙连接成功回调
         */
        private BluetoothGattCallback bluetoothGattCallback = new BluetoothGattCallback() {
            @Override
            public void onPhyUpdate(BluetoothGatt gatt, int txPhy, int rxPhy, int status) {
                super.onPhyUpdate(gatt, txPhy, rxPhy, status);
            }
    
            @Override
            public void onPhyRead(BluetoothGatt gatt, int txPhy, int rxPhy, int status) {
                super.onPhyRead(gatt, txPhy, rxPhy, status);
            }
    
            //不要执行耗时操作
            @Override
            public void onConnectionStateChange(BluetoothGatt gatt, int status, int newState) {
                super.onConnectionStateChange(gatt, status, newState);
                if (newState == BluetoothProfile.STATE_CONNECTED) {//连接成功
                    Log.e(TAG, "onConnectionStateChange 蓝牙连接");
                    //这里要执行以下方法,会在onServicesDiscovered这个方法中回调,如果在onServicesDiscovered方法中回调成功,设备才真正连接起来,正常通信
                    gatt.discoverServices();
                } else if (newState == BluetoothProfile.STATE_DISCONNECTED) {
                    Log.e(TAG, "onConnectionStateChange 蓝牙断连");
                    if (null != mBluetoothDevice) {
                        //关闭当前新的连接
                        gatt.close();
                        characteristic = null;
                    }
                }
            }
    
            @Override
            public void onServicesDiscovered(BluetoothGatt gatt, int status) {
                super.onServicesDiscovered(gatt, status);
                //回调之后,设备之间才真正通信连接起来
                if (status == BluetoothGatt.GATT_SUCCESS) {
                    Log.e(TAG, "onServicesDiscovered 蓝牙连接正常");
                    BluetoothGattService service = gatt.getService(UUID.fromString(SERVICE_UUID));//uuid从硬件工程师获取
                    characteristic = service.getCharacteristic(UUID.fromString(CHARACTER_UUID));
                    gatt.readCharacteristic(characteristic);//执行之后,会执行下面的onCharacteristicRead的回调方法
                    //设置通知,一般设备给手机发送数据,需要以下监听
                    setCharacteristicNotification(characteristic, true);
                    //耗时操作,如果有ui操作,需要用到handler
                } else {
                    Log.e(TAG, "onServicesDiscovered 蓝牙连接失败");
                }
            }
    
            //这个方法一般用不到
            @Override
            public void onCharacteristicRead(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic, int status) {
                super.onCharacteristicRead(gatt, characteristic, status);
                Log.e(TAG, "callback characteristic read status " + status
                        + " in thread " + Thread.currentThread());
                if (status == BluetoothGatt.GATT_SUCCESS) {
                    Log.e(TAG, "read value: " + characteristic.getValue());
                }
            }
    
            //这个方法是写入数据时的回调,可以和你写入的数据做对比
            @Override
            public void onCharacteristicWrite(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic, int status) {
                super.onCharacteristicWrite(gatt, characteristic, status);
    //            Log.e(TAG, "write value: " + FormatUtil.bytesToHexString(characteristic.getValue()));
            }
    
            //设备发出通知时会调用到该接口,蓝牙设备给手机发送数据,在这个方法接收
            @Override
            public void onCharacteristicChanged(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic) {
                super.onCharacteristicChanged(gatt, characteristic);
    //            Log.e(TAG, "接收:" + FormatUtil.bytesToHexString(characteristic.getValue()));//byte[]转为16进制字符串
    //            bleWriteReceiveCallback();
                byte[] bytes = characteristic.getValue();
                String str = new String(bytes);
                Log.e(TAG, "## readCharacteristic, 读取到: " + str);
            }
        };
    
        /**
         * 设置通知
         */
        public void setCharacteristicNotification(BluetoothGattCharacteristic characteristic, boolean enabled) {
            if (mBluetoothAdapter == null || mBluetoothGatt == null) {
                return;
            }
            mBluetoothGatt.setCharacteristicNotification(characteristic, enabled);
    //        BluetoothGattDescriptor descriptor = characteristic.getDescriptor(
    //                UUID.fromString(SampleGattAttributes.CLIENT_CHARACTERISTIC_CONFIG));
    //        descriptor.setValue(BluetoothGattDescriptor.ENABLE_NOTIFICATION_VALUE);
    //        mBluetoothGatt.writeDescriptor(descriptor);
        }
    
        /**
         * 写入命令
         */
        public void write(byte[] cmd) {
            if (characteristic != null) {
                // 发出数据
                characteristic.setValue(cmd);
                if (mBluetoothGatt.writeCharacteristic(characteristic)) {
                    Log.e(TAG, "写入成功");
                } else {
                    Log.e(TAG, "写入失败");
                }
            } else {
                Log.e(TAG, "write: 蓝牙未连接");
            }
        }
    
        /**
         * 断开蓝牙设备
         */
        public void bleDisConnectDevice(BluetoothDevice device) {
            if (mBluetoothGatt != null) {
                mBluetoothGatt.disconnect();
            }
        }
    
        /**
         * 释放资源
         */
        private void releaseResource() {
            Log.e(TAG, "断开蓝牙连接,释放资源");
            if (mBluetoothGatt != null) {
                mBluetoothGatt.disconnect();
                mBluetoothGatt.close();
            }
        }
    
        /**
         * 注册蓝牙监听广播
         */
        private void registerBleListenerReceiver(Context context) {
            IntentFilter intentFilter = new IntentFilter();
            intentFilter.addAction(BluetoothAdapter.ACTION_STATE_CHANGED);
            intentFilter.addAction(BluetoothDevice.ACTION_ACL_CONNECTED);
            intentFilter.addAction(BluetoothDevice.ACTION_ACL_DISCONNECTED);
            context.registerReceiver(bleListenerReceiver, intentFilter);
        }
    
        /**
         * 解除蓝牙监听广播
         */
        private void unregisterBleListenerReceiver(Context context) {
            context.unregisterReceiver(bleListenerReceiver);
        }
    
        /**
         * 蓝牙监听广播接受者
         */
        private BroadcastReceiver bleListenerReceiver = new BroadcastReceiver() {
            @Override
            public void onReceive(Context context, Intent intent) {
                String action = intent.getAction();
                //连接的设备信息
                BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
                Log.e(TAG, "蓝牙广播" + action);
    
                if (mBluetoothDevice != null && mBluetoothDevice.equals(device)) {
                    Log.e(TAG, "收到广播-->是当前连接的蓝牙设备");
    
                    if (BluetoothDevice.ACTION_ACL_CONNECTED.equals(action)) {
                        Log.e(TAG, "广播 蓝牙已经连接");
    
                    } else if (BluetoothDevice.ACTION_ACL_DISCONNECTED.equals(action)) {
                        Log.e(TAG, "广播 蓝牙断开连接");
                    }
                } else {
                    Log.e(TAG, "收到广播-->不是当前连接的蓝牙设备");
                }
    
                if (BluetoothAdapter.ACTION_STATE_CHANGED.equals(action)) {
                    int state = intent.getIntExtra(BluetoothAdapter.EXTRA_STATE, BluetoothAdapter.ERROR);
                    switch (state) {
                        case BluetoothAdapter.STATE_OFF:
                            Log.e(TAG, "STATE_OFF 手机蓝牙关闭");
                            bluetoothDeviceList.clear();
                            releaseResource();
                            break;
                        case BluetoothAdapter.STATE_TURNING_OFF:
                            Log.e(TAG, "STATE_TURNING_OFF 蓝牙正在关闭");
                            //停止蓝牙扫描
                            scanLeDevice(false);
                            break;
                        case BluetoothAdapter.STATE_ON:
                            Log.d(TAG, "STATE_ON 蓝牙开启");
                            //扫描蓝牙设备
                            scanLeDevice(true);
                            break;
                        case BluetoothAdapter.STATE_TURNING_ON:
                            Log.e(TAG, "STATE_TURNING_ON 蓝牙正在开启");
                            break;
                    }
                }
            }
        };
    }
    

    相关文章

      网友评论

          本文标题:2020-04-13

          本文链接:https://www.haomeiwen.com/subject/hwknmhtx.html