Organize a bluetooth open source library

The company is going to do a Bluetooth project. The demand for Bluetooth is to connect medical devices with Bluetooth. After the data is measured by the device, it will be sent to the mobile phone/tablet through Bluetooth. The time is limited, so I found a Bluetooth open source library on GitHub, and it works well.

Address: https://github.com/Jasonchenlijian/FastBle/wiki

Since there are only library files and calling codes, so I wrote a Bluetooth tool library myself, which contains various calling methods of Bluetooth

package com.dhy.health.blefast;

import android.app.Activity;
import android.app.Application;
import android.bluetooth.BluetoothGatt;
import android.bluetooth.BluetoothGattCharacteristic;
import android.bluetooth.BluetoothGattService;
import android.content.Context;

import com.clj.fastble.BleManager;
import com.clj.fastble.callback.BleGattCallback;
import com.clj.fastble.callback.BleIndicateCallback;
import com.clj.fastble.callback.BleMtuChangedCallback;
import com.clj.fastble.callback.BleNotifyCallback;
import com.clj.fastble.callback.BleReadCallback;
import com.clj.fastble.callback.BleRssiCallback;
import com.clj.fastble.callback.BleScanAndConnectCallback;
import com.clj.fastble.callback.BleScanCallback;
import com.clj.fastble.callback.BleWriteCallback;
import com.clj.fastble.data.BleDevice;
import com.clj.fastble.exception.BleException;
import com.clj.fastble.scan.BleScanRuleConfig;

import java.util.List;
import java.util.UUID;

/**
 * Created by Forrest.
 * User: Administrator:ZYJ
 * Date: 2020/11/25
 * Description:蓝牙管理工具类
 */
public class BLEFastUtils {

    private OnScanListener scanlistener;
    private OnConnectListener connectListener;
    private OnDataChangeListener dataChangeListener;

    public void setOnDataChangeCallBack(OnScanListener scanlistener,OnConnectListener connectListener,OnDataChangeListener dataChangeListener) {
        this.scanlistener = scanlistener;
        this.connectListener = connectListener;
        this.dataChangeListener = dataChangeListener;
    }
    //扫描蓝牙返回接口
    public interface OnScanListener{
        void onScanStarted(boolean success);//蓝牙搜索中
        void onScanning(BleDevice bleDevice);
        void onScanFinished(List<BleDevice> scanResultList);
    }

    //连接蓝牙返回接口
    public interface OnConnectListener{
        void onStartConnect();
        void onConnectFail(BleDevice bleDevice, BleException exception);
        void onConnectSuccess(BleDevice bleDevice, BluetoothGatt gatt, int status);
        void onDisConnected(boolean isActiveDisConnected, BleDevice bleDevice, BluetoothGatt gatt, int status);
    }

    //数据返回接口
    public interface OnDataChangeListener {
        void onNotifySuccess();
        void onNotifyFailure(BleException exception);
        void onCharacteristicChanged(byte[] data);
    }

    /**
     * 初始化和全局配置,写在application里面
     */
    public void Initialization() {
        //初始化
//        BleManager.getInstance().init(application);
        //扫描全局配置
        BleManager.getInstance()
                .enableLog(true)//默认打开库中的运行日志,如果不喜欢可以关闭
                .setReConnectCount(1, 5000)//设置连接时重连次数和重连间隔(毫秒),默认为0次不重连
                .setSplitWriteNum(20)//设置分包发送的时候,每一包的数据长度,默认20个字节
                .setConnectOverTime(10000)//设置连接超时时间(毫秒),默认10秒
                .setOperateTimeout(5000);//设置readRssi、setMtu、write、read、notify、indicate的超时时间(毫秒),默认5秒
    }

    /**
     * 扫描配置
     * - 在扫描设备之前,可以配置扫描规则,筛选出与程序匹配的设备
     * - 不配置的话均为默认参数
     * - 在2.1.2版本及之前,必须先配置过滤规则再扫描;在2.1.3版本之后可以无需配置,开启默认过滤规则的扫描。
     */
    public void initScanRule(UUID[] service_uuid, String ble_name, String mac, boolean isAutoConnect) {
        BleScanRuleConfig scanRuleConfig = new BleScanRuleConfig.Builder()
                .setServiceUuids(service_uuid)      // 只扫描指定的服务的设备,可选
                .setDeviceName(true, ble_name)         // 只扫描指定广播名的设备,可选
//                .setDeviceMac(mac)                  // 只扫描指定mac的设备,可选
//                .setAutoConnect(isAutoConnect)      // 连接时的autoConnect参数,可选,默认false
                .setScanTimeOut(10000)              // 扫描超时时间,可选,默认10秒;小于等于0表示不限制扫描时间
                .build();
        BleManager.getInstance().initScanRule(scanRuleConfig);
    }

    /**
     * 开始扫描
     * - 扫描及过滤过程是在工作线程中进行,所以不会影响主线程的UI操作,最终每一个回调结果都会回到主线程。
     */
    public void startScan() {
        BleManager.getInstance().scan(new BleScanCallback() {
            @Override
            public void onScanStarted(boolean success) {
                // 开始扫描(主线程)
                scanlistener.onScanStarted(success);
            }

            @Override
            public void onScanning(BleDevice bleDevice) {
                // 扫描到一个符合扫描规则的BLE设备(主线程)
                scanlistener.onScanning(bleDevice);
            }

            @Override
            public void onScanFinished(List<BleDevice> scanResultList) {
                // 扫描结束,列出所有扫描到的符合扫描规则的BLE设备(主线程)
                scanlistener.onScanFinished(scanResultList);
            }
        });
    }

    /**
     * 通过扫描到的BleDevice对象进行连接。
     * - 在某些型号手机上,connectGatt必须在主线程才能有效。非常建议把连接过程放在主线程。
     * - 连接失败后重连:框架中包含连接失败后的重连机制,可以配置重连次数和时间间隔。当然也可以自行在`onConnectFail`回调方法中延时调用`connect`方法。
     * - 连接断开后重连:可以在`onDisConnected`回调方法中再次调用`connect`方法。
     * - 为保证重连成功率,建议断开后间隔一段时间之后进行重连。
     * - 某些机型上连接失败后会短暂地无法扫描到设备,可以通过设备对象或设备mac直连,而不经过扫描。
     */
    public void connectDevice(BleDevice bleDevice) {
        BleManager.getInstance().connect(bleDevice, new BleGattCallback() {
            @Override
            public void onStartConnect() {
                // 开始连接
                connectListener.onStartConnect();
            }

            @Override
            public void onConnectFail(BleDevice bleDevice, BleException exception) {
                // 连接失败
                connectListener.onConnectFail(bleDevice,exception);
            }

            @Override
            public void onConnectSuccess(BleDevice bleDevice, BluetoothGatt gatt, int status) {
                // 连接成功,BleDevice即为所连接的BLE设备
                connectListener.onConnectSuccess(bleDevice,gatt,status);
            }

            @Override
            public void onDisConnected(boolean isActiveDisConnected, BleDevice bleDevice, BluetoothGatt gatt, int status) {
                // 连接中断,isActiveDisConnected表示是否是主动调用了断开连接方法
                connectListener.onDisConnected(isActiveDisConnected,bleDevice,gatt,status);
            }
        });
    }

    /**
     * 通过Mac连接蓝牙
     * Tips:
     * - 此方法可以不经过扫描,尝试直接连接周围复合该Mac的BLE设备。
     * - 在很多使用场景,我建议APP保存用户惯用设备的Mac,然后使用该方法进行连接可以大大提高连接效率。
     */
    public void connectMac(String mac) {
        BleManager.getInstance().connect(mac, new BleGattCallback() {
            @Override
            public void onStartConnect() {
                // 开始连接
            }

            @Override
            public void onConnectFail(BleDevice bleDevice, BleException exception) {
                // 连接失败
            }

            @Override
            public void onConnectSuccess(BleDevice bleDevice, BluetoothGatt gatt, int status) {
                // 连接成功,BleDevice即为所连接的BLE设备
            }

            @Override
            public void onDisConnected(boolean isActiveDisConnected, BleDevice bleDevice, BluetoothGatt gatt, int status) {
                // 连接中断,isActiveDisConnected表示是否是主动调用了断开连接方法
            }
        });
    }

    /**
     * 扫描并连接
     * 扫描到首个符合扫描规则的设备后,便停止扫描,然后连接该设备。
     * Tips:
     * - 扫描及过滤过程是在工作线程中进行,所以不会影响主线程的UI操作,但每一个回调结果都会回到主线程。 连接操作会在主线中进行。
     */
    public void scanConnect(BleScanAndConnectCallback callback) {
        BleManager.getInstance().scanAndConnect(new BleScanAndConnectCallback() {
            @Override
            public void onScanStarted(boolean success) {
                // 开始扫描(主线程)
            }

            @Override
            public void onScanning(BleDevice bleDevice) {
                // 扫描到一个符合扫描规则的BLE设备(主线程)
            }

            @Override
            public void onScanFinished(BleDevice scanResult) {
                // 扫描结束,结果即为扫描到的第一个符合扫描规则的BLE设备,如果为空表示未搜索到(主线程)
            }

            @Override
            public void onStartConnect() {
                // 开始连接(主线程)
            }

            @Override
            public void onConnectFail(BleDevice bleDevice, BleException exception) {
                // 连接失败(主线程)
            }

            @Override
            public void onConnectSuccess(BleDevice bleDevice, BluetoothGatt gatt, int status) {
                // 连接成功,BleDevice即为所连接的BLE设备(主线程)
            }

            @Override
            public void onDisConnected(boolean isActiveDisConnected, BleDevice device, BluetoothGatt gatt, int status) {
                // 连接断开,isActiveDisConnected是主动断开还是被动断开(主线程)
            }
        });
    }

    /**
     * 扫描过程中,中止扫描操作
     * Tips:
     * - 调用该方法后,如果当前还处在扫描状态,会立即结束,并回调`onScanFinished`方法。
     */
    public void stopScan() {
        BleManager.getInstance().cancelScan();
    }

    /**
     * 订阅通知notify
     */
    public void notify(BleDevice bleDevice, String uuid_service, String uuid_characteristic_notify) {
        BleManager.getInstance().notify(
                bleDevice,
                uuid_service,
                uuid_characteristic_notify,
                new BleNotifyCallback() {
                    @Override
                    public void onNotifySuccess() {
                        // 打开通知操作成功
                        dataChangeListener.onNotifySuccess();
                    }

                    @Override
                    public void onNotifyFailure(BleException exception) {
                        // 打开通知操作失败
                        dataChangeListener.onNotifyFailure(exception);
                    }

                    @Override
                    public void onCharacteristicChanged(byte[] data) {
                        // 打开通知后,设备发过来的数据将在这里出现
                        dataChangeListener.onCharacteristicChanged(data);
                    }
                });
    }

    /**
     * 取消订阅通知notify,并移除数据接收的回调监听
     */
    public void stopNotify(BleDevice bleDevice, String uuid_service, String uuid_characteristic_notify) {
        BleManager.getInstance().stopNotify(bleDevice, uuid_service, uuid_characteristic_notify);
    }

    /**
     * 订阅通知indicate
     */
    public void indicate(BleDevice bleDevice, String uuid_service, String uuid_characteristic_indicate) {
        BleManager.getInstance().indicate(
                bleDevice,
                uuid_service,
                uuid_characteristic_indicate,
                new BleIndicateCallback() {
                    @Override
                    public void onIndicateSuccess() {
                        // 打开通知操作成功
                    }

                    @Override
                    public void onIndicateFailure(BleException exception) {
                        // 打开通知操作失败
                    }

                    @Override
                    public void onCharacteristicChanged(byte[] data) {
                        // 打开通知后,设备发过来的数据将在这里出现
                    }
                });
    }

    /**
     * 取消订阅通知indicate,并移除数据接收的回调监听
     */
    public void stopIndicate(BleDevice bleDevice, String uuid_service, String uuid_characteristic_indicate) {
        BleManager.getInstance().stopIndicate(bleDevice, uuid_service, uuid_characteristic_indicate);
    }

    /**
     * 向蓝牙写入数据
     * Tips:
     * - 在没有扩大MTU及扩大MTU无效的情况下,当遇到超过20字节的长数据需要发送的时候,需要进行分包。参数`boolean split`表示是否使用分包发送;无`boolean split`参数的`write`方法默认对超过20字节的数据进行分包发送。
     * - 关于`onWriteSuccess`回调方法: `current`表示当前发送第几包数据,`total`表示本次总共多少包数据,`justWrite`表示刚刚发送成功的数据包。
     * - 对于分包发送的辅助策略,可以选择发送上一包数据成功之后发送下一包,或直接发送下一包,参数`sendNextWhenLastSuccess`表示是否待收到`onWriteSuccess`之后再进行下一包的发送。默认true。
     * - 参数`intervalBetweenTwoPackage`表示延时多长时间发送下一包,单位ms,默认0。
     */
    public void write(BleDevice bleDevice, String uuid_service, String uuid_characteristic_write, byte[] data) {
        BleManager.getInstance().write(
                bleDevice,
                uuid_service,
                uuid_characteristic_write,
                data,
                new BleWriteCallback() {
                    @Override
                    public void onWriteSuccess(int current, int total, byte[] justWrite) {
                        // 发送数据到设备成功
                    }

                    @Override
                    public void onWriteFailure(BleException exception) {
                        // 发送数据到设备失败
                    }
                });
    }

    /**
     * 读取蓝牙数据
     */
    public void read(BleDevice bleDevice, String uuid_service, String uuid_characteristic_read, BleReadCallback callback) {
        BleManager.getInstance().read(
                bleDevice,
                uuid_service,
                uuid_characteristic_read,
                new BleReadCallback() {
                    @Override
                    public void onReadSuccess(byte[] data) {
                        // 读特征值数据成功
                    }

                    @Override
                    public void onReadFailure(BleException exception) {
                        // 读特征值数据失败
                    }
                });
    }

    /**
     * 获取设备的信号强度Rssi
     * 获取设备的信号强度,需要在设备连接之后进行。
     * 某些设备可能无法读取Rssi,不会回调onRssiSuccess(),而会因为超时而回调onRssiFailure()。
     */
    public void readRssi(BleDevice bleDevice) {
        BleManager.getInstance().readRssi(
                bleDevice,
                new BleRssiCallback() {

                    @Override
                    public void onRssiFailure(BleException exception) {
                        // 读取设备的信号强度失败
                    }

                    @Override
                    public void onRssiSuccess(int rssi) {
                        // 读取设备的信号强度成功
                    }
                });
    }

    /**
     * 设置最大传输单元MTU
     * Tips:
     * 设置MTU,需要在设备连接之后进行操作。
     * 默认每一个BLE设备都必须支持的MTU为23。
     * MTU为23,表示最多可以发送20个字节的数据。
     * 在Android 低版本(API-17 到 API-20)上,没有这个限制。所以只有在API21以上的设备,才会有拓展MTU这个需求。
     * 该方法的参数mtu,最小设置为23,最大设置为512。
     * 并不是每台设备都支持拓展MTU,需要通讯双方都支持才行,也就是说,需要设备硬件也支持拓展MTU该方法才会起效果。调用该方法后,可以通过onMtuChanged(int mtu)查看最终设置完后,设备的最大传输单元被拓展到多少。如果设备不支持,可能无论设置多少,最终的mtu还是23。
     * */
    public void setMtu(BleDevice bleDevice, int mtu, BleMtuChangedCallback callback) {

        BleManager.getInstance().setMtu(bleDevice, mtu, new BleMtuChangedCallback() {
            @Override
            public void onSetMTUFailure(BleException exception) {
                // 设置MTU失败
            }

            @Override
            public void onMtuChanged(int mtu) {
                // 设置MTU成功,并获得当前设备传输支持的MTU值
            }
        });
    }

    /**
     * 断开某个设备
     * */
    public void disconnect(BleDevice bleDevice){
        BleManager.getInstance().disconnect(bleDevice);
    }

    /**
     * 断开所有设备
     * */
    public void disconnectAllDevice(){
        BleManager.getInstance().disconnectAllDevice();
    }

    /**
     * 退出使用,清理资源
     * */
    public void destroy(){
        BleManager.getInstance().destroy();
    }

    /**
     * 判断某个设备是否已连接bleDevice
     * */
    public boolean isConnectedBleDevice(BleDevice bleDevice){
        return BleManager.getInstance().isConnected(bleDevice);
    }

    /**
     * 判断某个设备是否已连接mac
     * */
    public boolean isConnectedMac(String mac){
        return BleManager.getInstance().isConnected(mac);
    }

    /**
     * 判断某个设备的当前连接状态
     * */
    public int getConnectState(BleDevice bleDevice){
        return BleManager.getInstance().getConnectState(bleDevice);
    }

    /**
     * 获取所有已连接设备
     * */
    public List<BleDevice> getAllConnectedDevice(){
        return BleManager.getInstance().getAllConnectedDevice();
    }

    /**
     * 获取某个已连接设备的所有Service
     * */
    public List<BluetoothGattService> getBluetoothGattServices(BleDevice bleDevice){
        return BleManager.getInstance().getBluetoothGattServices(bleDevice);
    }

    /**
     *获取某个Service的所有Characteristic
     * */
    public List<BluetoothGattCharacteristic> getBluetoothGattCharacteristics(BluetoothGattService service){
        return BleManager.getInstance().getBluetoothGattCharacteristics(service);
    }

    /**
     * 获取某个已连接设备的BluetoothGatt
     * */
    public BluetoothGatt getBluetoothGatt(BleDevice bleDevice){
        return BleManager.getInstance().getBluetoothGatt(bleDevice);
    }
}

 call method

package com.dhy.health.blefast;

import androidx.appcompat.app.AppCompatActivity;
import androidx.core.app.ActivityCompat;

import android.Manifest;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothGatt;
import android.bluetooth.BluetoothGattService;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.Toast;

import com.clj.fastble.BleManager;
import com.clj.fastble.callback.BleGattCallback;
import com.clj.fastble.callback.BleNotifyCallback;
import com.clj.fastble.callback.BleScanCallback;
import com.clj.fastble.data.BleDevice;
import com.clj.fastble.exception.BleException;
import com.clj.fastble.scan.BleScanRuleConfig;

import org.json.JSONObject;

import java.io.UnsupportedEncodingException;
import java.math.BigDecimal;
import java.util.List;
import java.util.UUID;

public class MainActivity extends AppCompatActivity {
    private static final String TAG = "MainActivity";
    private BluetoothAdapter mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();

    private String blename = "Bene";
    private String service_uuid = "";
    private String char_uuid = "";
    private Button mSaomiao;
    private Button mTzsaomiao;
    private BLEFastUtils bleFastUtils;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
//蓝牙初始化配置
        BleManager.getInstance().init((Application) getApplicationContext());
        //扫描全局配置
        BleManager.getInstance()
                .enableLog(true)//默认打开库中的运行日志,如果不喜欢可以关闭
                .setReConnectCount(1, 5000)//设置连接时重连次数和重连间隔(毫秒),默认为0次不重连
                .setSplitWriteNum(20)//设置分包发送的时候,每一包的数据长度,默认20个字节
                .setConnectOverTime(10000)//设置连接超时时间(毫秒),默认10秒
                .setOperateTimeout(5000);//设置readRssi、setMtu、write、read、notify、indicate的超时时间(毫秒),默认5秒
        mSaomiao = findViewById(R.id.saomiao);
        mTzsaomiao=findViewById(R.id.tzsaomiao);
        mSaomiao.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                //扫描
                bleFastUtils.startScan();
            }
        });
        setPermissions();
        bleFastUtils = new BLEFastUtils();
        bleFastUtils.setOnDataChangeCallBack(
                // TODO 扫描返回接口
                new BLEFastUtils.OnScanListener() {
                    @Override
                    public void onScanStarted(boolean success) {
                        // 开始扫描(主线程)
                        Log.e("onScanStarted", "" + success);
                    }

                    @Override
                    public void onScanning(BleDevice bleDevice) {
                        Log.e("onScanning", "" + bleDevice.getName());
                        // 扫描到一个符合扫描规则的BLE设备(主线程)
                        if (bleDevice.getName() != null) {

                            if (bleDevice.getName().contains(blename)) {
                                Log.e("onScanStopScan", "停止扫描");
                                bleFastUtils.stopScan();
                            }
                        }
                    }

                    @Override
                    public void onScanFinished(List<BleDevice> scanResultList) {
                        // 扫描结束,列出所有扫描到的符合扫描规则的BLE设备(主线程)
                        for (int i = 0; i < scanResultList.size(); i++) {

                            if (scanResultList.get(i).getName() != null) {
                                Log.e("onScanFinished", "" + scanResultList.get(i).getName());
                                if (scanResultList.get(i).getName().contains(blename)) {
                                    Log.e("onScanFinished", "" + scanResultList.get(i).getMac());
                                    bleFastUtils.connectDevice(scanResultList.get(i));
                                    Log.e("onScanFinished2", "" + scanResultList.get(i).getMac());
                                }
                            }
                        }
                    }
                }
                //TODO 连接返回接口
                , new BLEFastUtils.OnConnectListener() {
                    @Override
                    public void onStartConnect() {
                        //开始连接
                        Log.e("onScan开始连接", "1");
                    }

                    @Override
                    public void onConnectFail(BleDevice bleDevice, BleException exception) {
                        // 连接失败
                        Log.e("onScan连接失败", "2");
                    }

                    @Override
                    public void onConnectSuccess(BleDevice bleDevice, BluetoothGatt gatt, int status) {
                        // 连接成功,BleDevice即为所连接的BLE设备
                        Log.e("onScan连接成功", "3" + gatt.getServices().get(0).getUuid());
                        for (BluetoothGattService s : gatt.getServices()) {
                            Log.e("onScan连接成功1", "31" + s.getUuid().toString());
                        }
                        bleFastUtils.notify(bleDevice, service_uuid, char_uuid);
                    }

                    @Override
                    public void onDisConnected(boolean isActiveDisConnected, BleDevice bleDevice, BluetoothGatt gatt, int status) {
                        // 连接中断,isActiveDisConnected表示是否是主动调用了断开连接方法
                        Log.e("onScan连接中断", "4");
                        gatt.close();
                    }
                }
                //TODO 数据传输返回接口
                , new BLEFastUtils.OnDataChangeListener() {
                    @Override
                    public void onNotifySuccess() {
                        // 打开通知操作成功
                        Log.e("onScan订阅成功", "1");
                    }

                    @Override
                    public void onNotifyFailure(BleException exception) {
                        // 打开通知操作失败
                        Log.e("onScan订阅失败", "2*" + exception.getCode() + exception.getDescription());
                    }

                    @Override
                    public void onCharacteristicChanged(final byte[] data) {
                        // 打开通知后,设备发过来的数据将在这里出现
                        Log.e("onScan接收数据", "3" + data);
                        if (data != null && data.length > 0) {
                            final StringBuilder stringBuilder = new StringBuilder(data.length);
                            for (byte byteChar : data)
                                stringBuilder.append(String.format("%02X ", byteChar));
                            Log.e(TAG, "new string -->" + new String(data) + "\n" + stringBuilder.toString());
                            displayData(new String(data) + "\n" + stringBuilder.toString());
                        }
                    }
                });
    }

    public void saomiao() {
        BleManager.getInstance().scan(new BleScanCallback() {
            @Override
            public void onScanStarted(boolean success) {
                // 开始扫描(主线程)
                Log.e("onScanStarted", "" + success);
            }

            @Override
            public void onScanning(BleDevice bleDevice) {
                // 扫描到一个符合扫描规则的BLE设备(主线程)
                if (bleDevice.getName() != null) {
                    Log.e("onScanning", "" + bleDevice.getName());
                    if (bleDevice.getName().contains(blename)) {
                        BleManager.getInstance().cancelScan();
                    }
                }
            }

            @Override
            public void onScanFinished(List<BleDevice> scanResultList) {
                // 扫描结束,列出所有扫描到的符合扫描规则的BLE设备(主线程)
                for (int i = 0; i < scanResultList.size(); i++) {

                    if (scanResultList.get(i).getName() != null) {
                        Log.e("onScanFinished", "" + scanResultList.get(i).getName());
                        if (scanResultList.get(i).getName().contains(blename)) {
                            Log.e("onScanFinished", "" + scanResultList.get(i).getMac());
                            setLianjie(scanResultList.get(i));
                            Log.e("onScanFinished2", "" + scanResultList.get(i).getMac());
                        }
                    }
                }
            }
        });
    }

    public void setLianjie(final BleDevice mac) {
        Log.e("onScan进入链接", "" + mac);
//        BleManager.getInstance().connect(mac, new BleGattCallback() {
//            @Override
//            public void onStartConnect() {
//                Log.e("onScan连接开始","");
//                // 开始连接
//            }
//
//            @Override
//            public void onConnectFail(BleDevice bleDevice, BleException exception) {
//                // 连接失败
//                Log.e("onScan连接失败","");
//            }
//
//            @Override
//            public void onConnectSuccess(BleDevice bleDevice, BluetoothGatt gatt, int status) {
//                // 连接成功,BleDevice即为所连接的BLE设备
//                Log.e("onScan连接成功","");
//            }
//
//            @Override
//            public void onDisConnected(boolean isActiveDisConnected, BleDevice bleDevice, BluetoothGatt gatt, int status) {
//                // 连接中断,isActiveDisConnected表示是否是主动调用了断开连接方法
//                Log.e("onScan连接中断","");
//            }
//        });

        BleManager.getInstance().connect(mac, new BleGattCallback() {
            @Override
            public void onStartConnect() {
                // 开始连接
                Log.e("onScan连接开始", "1");
            }

            @Override
            public void onConnectFail(BleDevice bleDevice, BleException exception) {
                // 连接失败
                Log.e("onScan连接失败", "2");
            }

            @Override
            public void onConnectSuccess(BleDevice bleDevice, BluetoothGatt gatt, int status) {
                // 连接成功,BleDevice即为所连接的BLE设备
                Log.e("onScan连接成功", "3");
                setDingyue(mac, service_uuid, char_uuid);
            }

            @Override
            public void onDisConnected(boolean isActiveDisConnected, BleDevice bleDevice, BluetoothGatt gatt, int status) {
                // 连接中断,isActiveDisConnected表示是否是主动调用了断开连接方法
                Log.e("onScan连接中断", "4");
            }
        });
    }


    //dingyue
    public void setDingyue(BleDevice bleDevice, String uuid_service, String uuid_characteristic_notify) {
        BleManager.getInstance().notify(
                bleDevice,
                uuid_service,
                uuid_characteristic_notify,
                new BleNotifyCallback() {
                    @Override
                    public void onNotifySuccess() {
                        // 打开通知操作成功
                        Log.e("onScan订阅成功", "1");
                    }

                    @Override
                    public void onNotifyFailure(BleException exception) {
                        // 打开通知操作失败
                        Log.e("onScan订阅失败", "2");
                    }

                    @Override
                    public void onCharacteristicChanged(byte[] data) {
                        // 打开通知后,设备发过来的数据将在这里出现
                        Log.e("onScan接收数据", "3" + data);
                        setJiexishuju(data);
                    }
                });
    }

    StringBuilder sb = new StringBuilder();

    public void setJiexishuju(final byte[] data) {
        try {
            int length = data.length;
            final String tmpValue = new String(data, "UTF-8");

            runOnUiThread(new Runnable() {
                @Override
                public void run() {
                    //拼接data
                    sb.append(Bytes2HexString(data));
                    Log.e("MainActivity", "sb=" + sb);
                    //如果sb没拼接到结束符就继续往下走,拼接到了就停止拼接,然后根据ODOA分割成若干部分
                    if (sb.toString().contains("0D0A0D0A0D0A")) {
                        String line = sb.toString();
                        String[] leu = line.split("0D0A");
                        for (int i = 0; i < leu.length; i++) {
                            System.out.println("1MainActivity" + i + "=" + leu[i]);//43484F4C3A3C3130306D672F644C
                            System.out.println("2MainActivity" + i + "=" + hexStringToString(leu[i]));//CHOL:<100mg/dL
                        }
                        sb = new StringBuilder();
                    }
                }
            });
        } catch (UnsupportedEncodingException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }

    /**
     * byte[] 转为16进制String
     *
     * @param b
     */
    public static String Bytes2HexString(byte[] b) {
        String ret = "";
        for (int i = 0; i < b.length; i++) {
            String hex = Integer.toHexString(b[i] & 0xFF);
            if (hex.length() == 1) {
                hex = '0' + hex;
            }
            ret += hex.toUpperCase();
        }
        return ret;
    }

    /**
     * 16进制转换成为string类型字符串
     *
     * @param s
     * @return
     */
    public static String hexStringToString(String s) {
        if (s == null || s.equals("")) {
            return null;
        }
        s = s.replace(" ", "");
        byte[] baKeyword = new byte[s.length() / 2];
        for (int i = 0; i < baKeyword.length; i++) {
            try {
                baKeyword[i] = (byte) (0xff & Integer.parseInt(s.substring(i * 2, i * 2 + 2), 16));
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        try {
            s = new String(baKeyword, "UTF-8");
            new String();
        } catch (Exception e1) {
            e1.printStackTrace();
        }
        return s;
    }

    /**
     * get measure result
     * "2.0" above protocol "03" package length:12
     * "1.0" protocol "03" package length:14
     *
     * @param data received package data
     */
    private void showContent(byte[] data) {
        if (null == data) return;
        byte index0 = data[0];
        if (index0 != 85) return;
        byte index2 = data[2];
        if (index2 == 3) {//Device upload results
            byte index3 = data[3];//Year
            byte index4 = data[4];//Month
            byte index5 = data[5];//Day
            byte index6 = data[6];//Hour
            byte index7 = data[7];//Minute
            byte[] valueArr = {data[10], data[9]};
            //10+9 Convert to decimal,And then  divide by 100,get the temperature
            String strValue = ZHexUtil.encodeHexStr(valueArr);
            int value = Integer.valueOf(strValue, 16);

            //跟体温计结果显示保持一致:丢弃小数点后第二位
            String valueStr = StringUtil.formatTo1ROUNDDOWN((double) value / 100);
//            tvTwNum.setText("" + valueStr);
            Log.e("onScan得到的数据是", "value --" + valueStr);
        } else if (index2 == 5) {
            //收到测量结束包
        }
    }

    private void displayData(String data) {
        if (data != null) {
            int index = data.indexOf("24 50 43 4C 41");
            if (index != -1) {
                // isShowData = true;
                String str = data.substring(data.indexOf("24 50 43 4C 41"));
                Log.e(TAG, "截取: " + str);
                String[] strArray = str.toString().split(" ");
                String data1 = strArray[strArray.length - 2];
                String data2 = strArray[strArray.length - 3];
                Log.e(TAG, "data1 = " + data1 + "\ndata2 = " + data2);
                String hexData = data1 + data2;
                Log.e(TAG, "hexData = " + hexData);
                float resultFloat = ((float) Integer.valueOf(hexData, 16)) / 18;
                BigDecimal b = new BigDecimal(resultFloat); // 四舍五入
                final float resultFloat2 = b.setScale(1, BigDecimal.ROUND_HALF_UP).floatValue();
                Log.i(TAG, "血糖值是 = " + resultFloat2);
                // mDataField.setText(String.valueOf(resultFloat2));
//                if (listener != null)
//                    listener.onBloodSugarData(resultFloat2 + "");//血糖
            }
            int index2 = data.indexOf("24 50 43 4C 51");
            if (index2 != -1) {
                // isShowData = true;
                String str = data.substring(data.indexOf("24 50 43 4C 51"));
                String[] strArray = str.toString().split(" ");
                String data1 = strArray[strArray.length - 2];
                String data2 = strArray[strArray.length - 3];
                String hexData = data1 + data2;
                float resultFloat = ((float) Integer.valueOf(hexData, 16)) / (float) 168.1;
                BigDecimal b = new BigDecimal(resultFloat); // 四舍五入
                final float resultFloat2 = b.setScale(2, BigDecimal.ROUND_HALF_UP).floatValue();
                Log.i(TAG, "尿酸值是 = " + resultFloat2);
                // mDataField.setText(String.valueOf(resultFloat2));
//                if (listener != null)
//                    listener.onUricAcidData(resultFloat2 + ""); //尿酸
            }
            int index3 = data.indexOf("24 50 43 4C 61");
            if (index3 != -1) {
                // isShowData = true;
                String str = data.substring(data.indexOf("24 50 43 4C 61"));
                String[] strArray = str.toString().split(" ");
                String data1 = strArray[strArray.length - 2];
                String data2 = strArray[strArray.length - 3];
                String hexData = data1 + data2;
                float resultFloat = ((float) Integer.valueOf(hexData, 16)) / (float) 38.66;
                BigDecimal b = new BigDecimal(resultFloat); // 四舍五入
                final float resultFloat2 = b.setScale(2, BigDecimal.ROUND_HALF_UP).floatValue();
                Log.i(TAG, "胆固醇值是 = " + resultFloat2);
                // mDataField.setText(String.valueOf(resultFloat2));
//                if (listener != null)
//                    listener.onCholesterolData(resultFloat2 + ""); //胆固醇
            }
        }
    }

    /**
     * set location permission, open bluetooth
     * 设置权限(定位权限),打开蓝牙
     */
    private void setPermissions() {
        if (ActivityCompat.checkSelfPermission(MainActivity.this, Manifest.permission.ACCESS_FINE_LOCATION)
                != PackageManager.PERMISSION_GRANTED) {//未开启定位权限
            //开启定位权限
            ActivityCompat.requestPermissions(MainActivity.this, new String[]{Manifest.permission.ACCESS_FINE_LOCATION}
                    , 0);
        } else {
            //申请蓝牙权限
            if (mBluetoothAdapter == null) {
                Toast.makeText(MainActivity.this, "" +
                        "this is not support bluetooth", Toast.LENGTH_LONG).show();
            } else if (!mBluetoothAdapter.isEnabled()) {
                //启动蓝牙
                Intent enableBtIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
                startActivityForResult(enableBtIntent, 1);
            }
        }
    }

    /**
     * 定位权限后的回调
     */
    @Override
    public void onRequestPermissionsResult(int requestCode, String permissions[], int[] grantResults) {
        switch (requestCode) {
            case 0:
                if (grantResults[0] == PackageManager.PERMISSION_GRANTED) {

                    //申请蓝牙权限
                    if (mBluetoothAdapter == null) {
                        Toast.makeText(MainActivity.this, "this is not support bluetooth", Toast.LENGTH_LONG).show();
                    } else if (!mBluetoothAdapter.isEnabled()) {

                        //启动蓝牙
                        Intent enableBtIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
                        startActivityForResult(enableBtIntent, 1);
                    }
                }
                break;
        }
    }
}

Don't forget to add bluetooth related permissions

I'm pushing another one, haven't tried this one yet

https://github.com/LuoPeiQin/Bluetooth

Guess you like

Origin blog.csdn.net/lanrenxiaowen/article/details/110188124