1,本文主要讲解蓝牙数据的搜索–链接–获取数据值–写入数据值;蓝牙Demo

一:搜索蓝牙设备名称
二:建立链接
三:读取传递过来的值
四:写入数据

蓝牙项目该配置的具体事件

<!-- 检测蓝牙状态 -->
    <uses-feature android:name="android.hardware.bluetooth_le" android:required="true"/>
    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
    <uses-permission android:name="android.permission.INTERNET"></uses-permission>
    <!-- 增加蓝牙所需要的权限 -->
    <uses-permission android:name="android.permission.BLUETOOTH" />
    <uses-permission android:name="android.permission.BLUETOOTH_ADMIN" />

结合自己最近的项目需求,和自身所学所得,代码基本上利用官方的sever服务和gatt链接,只是通过修改获得自己想要的结果,下面就简单介绍一下自己的理解。

一:扫描BLE设备activity

if (!mBluetoothAdapter.isEnabled()) {
            if (!mBluetoothAdapter.isEnabled()) {
                Intent enableBtIntent = new Intent(
                        BluetoothAdapter.ACTION_REQUEST_ENABLE);
                startActivityForResult(enableBtIntent, REQUEST_ENABLE_BT);
            }
        }
        // Initializes list view adapter.
        mLeDeviceListAdapter = new LeDeviceListAdapter(this);
        //添加到蓝牙设备
        devicelist.setAdapter(mLeDeviceListAdapter);

二:初始化获得一个bluetoothManager,并检测设备是否支持蓝牙

private void checkBluetooth() {
        // 检查当前手机是否支持ble 蓝牙,如果不支持退出程序
        if (!getPackageManager().hasSystemFeature(PackageManager.FEATURE_BLUETOOTH_LE)) {
            Toast.makeText(this, "没有提供蓝牙", Toast.LENGTH_SHORT).show();
            //finish();
        }
        // 初始化 Bluetooth adapter, 通过蓝牙管理器得到一个参考蓝牙适配器(API必须在以上android4.3或以上和版本)
        final BluetoothManager bluetoothManager = (BluetoothManager) getSystemService(Context.BLUETOOTH_SERVICE);
        mBluetoothAdapter = bluetoothManager.getAdapter();

        // 检查设备上是否支持蓝牙
        if (mBluetoothAdapter == null) {
            Toast.makeText(this, "设备不支持蓝牙", Toast.LENGTH_SHORT).show();
            //finish();
            return;
        }
    }

三:蓝牙控制的服务BluetoothLeService

在这个服务里面有一个很重要的回调函数BluetoothGattCallback(),蓝牙的数据读取和状态改变都会回调这个函数。
private final BluetoothGattCallback mGattCallback = new BluetoothGattCallback() {
        /**
         * 判断连接是否成功
         * @param gatt
         * @param status
         * @param newState
         */
        @Override
        public void onConnectionStateChange(BluetoothGatt gatt, int status, int newState) {
            String intentAction;
            if(status==BluetoothGatt.GATT_SUCCESS) {
                //连接成功的时候
                if (newState == BluetoothProfile.STATE_CONNECTED) {
                    //连接成功
                    intentAction = BroadCast.ACTION_GATT_CONNECTED;
                    //发送广播
                    broadcastUpdate(intentAction);
                    //打印连接服务
                    Log.i(TAG, "连接到GATT服务器");
                    //立即去执行发现服务
                    gatt.discoverServices();
                }

                //当断开连接的时候
                else if (newState == BluetoothProfile.STATE_DISCONNECTED) {
                    //断开连接
                    intentAction = BroadCast.ACTION_GATT_DISCONNECTED;
                    //打印断开连接
                    Log.i(TAG, "与GATT服务器断开连接");
                    //发送广播
                    broadcastUpdate(intentAction);
                }
            }
        }
        }

四,发现服务

/**
         * 发现服务
         * @param gatt
         * @param status
         */
        @Override
        public void onServicesDiscovered(BluetoothGatt gatt, int status) {
            //连接成功
            if(status==BluetoothGatt.GATT_SUCCESS){
                //发送发现服务的广播
                broadcastUpdate(BroadCast.ACTION_GATT_SERVICES_DISCOVERED);
                Log.i(TAG,"发现服务是可以的");
            }else {
                Log.w(TAG, "发现接收到的服务: " + status);//发现设备的时候 发送广播
            }
        }

五,数据读取和数据改变

/**
         * 数据读取
         * @param gatt
         * @param characteristic
         * @param status
         */
        @Override
        public void onCharacteristicRead(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic, int status) {
            Log.i("读取出来的值",gatt+" "+characteristic+" "+status);
            if (status == BluetoothGatt.GATT_SUCCESS) {
                //读取到里面的数据时候发送广播
                broadcastUpdate(BroadCast.ACTION_DATA_AVAILABLE, characteristic);
                Log.i(TAG,"");
            }
        }

        /**
         * 数据改变
         * @param gatt
         * @param characteristic
         */
        @Override
        public void onCharacteristicChanged(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic) {
            broadcastUpdate(BroadCast.ACTION_DATA_AVAILABLE, characteristic);
        }


        /**
         * 数据描述读取
         * @param gatt
         * @param descriptor
         * @param status
         */
        @Override
        public void onDescriptorRead(BluetoothGatt gatt, BluetoothGattDescriptor descriptor, int status) {
            if(status == BluetoothGatt.GATT_SUCCESS){
                BluetoothGattCharacteristic characteristic = descriptor.getCharacteristic();
                broadcastUpdate(BroadCast.ACTION_DATA_AVAILABLE, characteristic);
                Log.i(TAG,"success is data");
            }
        }

六,广播接受和发送数据,重点看如下:

/**
     * 发送广播数据处理
     * @param action
     * @param characteristic
     */
    private void broadcastUpdate(final String action,final BluetoothGattCharacteristic characteristic){
        final Intent intent = new Intent(action);
        // 当为温度值的时候 以及所有的数据处理
        if (characteristic.getUuid().equals(UUIDDataBase.UUID_HEALTH_THERMOMETER_SENSOR_LOCATION)) {
            String a = BWDataParser.getTempData(characteristic);
            intent.putExtra(BroadCast.EXTRA_DATA, a);
        }
        // 当为温度值的时候 以及所有的数据处理
        else if (characteristic.getUuid().equals(UUIDDataBase.UUID_HEALTH_THERMOMETER)) {
            String health_temp = BWDataParser.getTempData(characteristic);
            intent.putExtra(BroadCast.EXTRA_DATA_DISPLAY, health_temp);
        }
        else if (characteristic.getUuid().equals(UUIDDataBase.UUID_HEALTH_THERMOMETER_NAME)) {
            String aa = BWDataParser.getTempData(characteristic);
            intent.putExtra(BroadCast.EXTRA_DATA_DISPLAY_TEMPTWO, aa);
        }
        else if (characteristic.getUuid().equals(UUIDDataBase.UUID_HEALTH_TONGDAONAMEDATE)) {
            Log.i("===3333333333===",characteristic.toString());
            String tdname = BWDataParser.getTempData(characteristic);
            intent.putExtra(BroadCast.EXTRA_DATA_DISPLAY_TONGDAONAME, tdname);
        }
        sendBroadcast(intent);
    }

七,写入数据到蓝牙设备
还有几个重要的函数比如writeCharacteristic(BluetoothGattCharacteristic characteristic)函数,读取蓝牙中数据。

/**
     * 写入蓝牙数据的方法
     * @param charac
     * @param message
     * @return boolean
     */
    public static boolean writeCharacteristic(BluetoothGattCharacteristic charac,String message){
        //check mBluetoothGatt is available
        if (bluetoothGatt == null) {
            Log.e(TAG, "lost connection");
            return false;
        }
        if(charac!=null&&!message.equals(null)&&!message.equals("")){
            //int a = Integer.parseInt(message);
            byte []a = convertingTobyteArray(message);
            charac.setValue(a);
            boolean status = bluetoothGatt.writeCharacteristic(charac);
            return status;
        }else{
            return false;
        }
    }

八:广播的注册事件:

private static IntentFilter makeGattUpdateIntentFilter() {
        final IntentFilter intentFilter = new IntentFilter();
        intentFilter.addAction(BluetoothLeService.ACTION_GATT_CONNECTED);
        intentFilter.addAction(BluetoothLeService.ACTION_GATT_DISCONNECTED);
        intentFilter.addAction(BluetoothLeService.ACTION_GATT_SERVICES_DISCOVERED);
        intentFilter.addAction(BluetoothLeService.ACTION_DATA_AVAILABLE);
        return intentFilter;
    }

九:断开广播与服务

@Override
    protected void onDestroy() {
        super.onDestroy();
        // 断开广播连接
        if(isunbind) {
            unregisterReceiver(mGattUpdateReceiver);

            if(progressDialog!=null){
                progressDialog.dismiss();
            }
            //断开蓝牙服务连接
            if(bluetoothService!=null){
                BluetoothService.disconnect();
            }
            //断开服务连接
            if(mServiceConnection!=null) unbindService(mServiceConnection);

            if(mediaPlayerUtil!=null){
                mediaPlayerUtil.mExit();
            }
            ActivityCollector.finishAll();
            isunbind = false;
        }
    }

十:在发现了有可支持的服务之后会回调Service中的onServicesDiscovered()函数,并发送广播,在官方的demo中发现了可用的Service之后,就查找该BLE设备支持的所有服务和characteristic,在这里不需要查找所有的服务,只需要向蓝牙写数据和读取数据的Service和characteristic的UUID即可。通过查询低功耗蓝牙(BLE)的数据手册可以得到所需要的UUID。

public class GattAttributes {
    //温度类型
    public static final String TEMPERATURE_TYPE = "00002a1d-0000-1000-8000-00805f9b34fb";
    //usual
    public static final String CLIENT_CHARACTERISTIC_CONFIG = "00002902-0000-1000-8000-00805f9b34fb";
    //温度探头one
    public static final String HEALTH_TEMP_MEASUREMENT = "333-0e0d-4bd4-33-9868ddsa";
    //温度探头two
    public static final String TEMP_DATA_NAME = "900876-a249-4443-a04e-7655750";
    //通道名字
    public static final String TEMP_DATA_TONGDAONAME = "89765tg-f54d-4abb-aa79-87544ffd21";

}

十一:蓝牙开发的具体思路,关于数据传输的一些服务,在这之前我们得先了解一下一些专业词汇:

1、profile 
        profile可以理解为一种规范,一个标准的通信协议,它存在于从机中。蓝牙组织规定了一些标准的profile,例如 HID OVER GATT ,防丢器 ,心率计等。每个profile中会包含多个service,每个service代表从机的一种能力。
2、service
        service可以理解为一个服务,在ble从机中,通过有多个服务,例如电量信息服务、系统信息服务等,每个service中又包含多个characteristic特征值。每个具体的characteristic特征值才是ble通信的主题。比如当前的电量是80%,所以会通过电量的characteristic特征值存在从机的profile里,这样主机就可以通过这个characteristic来读取80%这个数据
3、characteristic
        characteristic特征值,ble主从机的通信均是通过characteristic来实现,可以理解为一个标签,通过这个标签可以获取或者写入想要的内容。
4、UUID
        UUID,统一识别码,我们刚才提到的service和characteristic,都需要一个唯一的uuid来标识

十二:具体的蓝牙ble开发总结就这些,如果需要完整蓝牙demo,可以进行下载,博主亲自测试完毕,Demo搜索–链接–读取–写入,若有不理解的地方可以私信回复,希望帮助到更多的初学者!