安卓蓝牙BLE(3)

上一篇讲到连接设备,这一篇讲蓝牙设备通讯。
主要用到以下几个类。

BluetoothGattService:(蓝牙服务)一台蓝牙设备上最少有1个或一个以上服务。
BluetoothGattCharacteristic:(蓝牙特性)一个服务里最少有1个及以上的特性。
UUID:每个服务和特性都有一个特定的UUID类似于身份证号的意思。

代码:在连接成功中去寻找服务:

case BluetoothGatt.STATE_CONNECTED://已连接
                    Log.e("lee", "已连接");
                    //去寻找服务
                    bluetoothGatt.discoverServices();
                    break;

       //当服务被找到时回调此方法。
        @Override
        public void onServicesDiscovered(BluetoothGatt gatt, int status) {
            super.onServicesDiscovered(gatt, status);
            if (status == BluetoothGatt.GATT_SUCCESS) {//寻找服务成功。
                //或许该设备下的所有服务(每个服务都有自己的UUID)
                List<BluetoothGattService> services = gatt.getServices();
                for (BluetoothGattService service : services) {
                    //获取该服务下的所有的特性
                    List<BluetoothGattCharacteristic> characteristics = service.getCharacteristics();
                    for (BluetoothGattCharacteristic characteristic : characteristics) {
                        //此处可以和蓝牙设备的硬件工程师交流 哪个特征值是对应的什么效果。 然后通过调用
                        if (characteristic.getUuid().equals("00000")) {//(此处我就瞎写一个) 通过UUID来获取硬件工程师告诉你的特征
                            characteristic.setValue(new byte[]{0x05});//(这个也是我瞎写的  需要蓝牙硬件工程师告诉你)
                            //调用了这个setValue()方法写入对应的数据,就能调用蓝牙设备的该特性了。
                        }
                    }
                }
            }
        }

当然这里setValue()方法一般都是写在某个按钮的点击事件中,所以需要把
characteristic抽出来赋值成一个成员变量。

以上就完成了App去控制蓝牙设备的功能。

                        if (characteristic.getUuid().equals("11111")) {//(此处我就瞎写一个) 获取设备控制App的命令

                            //调用此方法获取设备的通知
                            characteristic.notify();//(这个也是我瞎写的)
                        }


        //当特征值改变时回调此方法。
        @Override
        public void onCharacteristicChanged(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic) {
            super.onCharacteristicChanged(gatt, characteristic);
            //通过判断characteristic的UUID和我们下面的那个11111的UUid是不是一样的 是一样的就可以做对应的操作了。
            if (characteristic.getUuid().equals("11111")){
                //获取characteristic中的值
                byte[] value = characteristic.getValue();
                //转化成16进制
                String s = bytesToHex(value);
                if (s.equals("0x55")){
                    //执行对应的操作
                }
            }
        }

以上就完成了蓝牙设备控制手机。

当需要一直读取设备上的某个信息时需要用到read方法

if (characteristic.getUuid().equals("22222")) {//(此处我就瞎写一个) 获取设备的电量

                            //调用此方法获取设备的通知 读取到时会回调
                            gatt.readCharacteristic(characteristic);
                        }


//当读取到设备的信息时回调此方法
        @Override
        public void onCharacteristicRead(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic, int status) {
            super.onCharacteristicRead(gatt, characteristic, status);
            if (status == BluetoothGatt.GATT_SUCCESS) {//读取成功
                if (characteristic.getUuid().equals("22222")) {
                    byte[] value = characteristic.getValue();
                }
            }
        }

以下就是全部代码

package com.demo.ibeacondemo;

import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity;

import android.Manifest;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothGatt;
import android.bluetooth.BluetoothGattCallback;
import android.bluetooth.BluetoothGattCharacteristic;
import android.bluetooth.BluetoothGattService;
import android.bluetooth.BluetoothManager;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.os.Build;
import android.os.Bundle;
import android.util.Log;
import android.widget.Toast;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;

public class MainActivity extends AppCompatActivity {
    private BluetoothAdapter mBluetoothAdapter;
    private static final int REQUEST_COARSE_LOCATION = 0;
    private List<BluetoothDevice> devices = new ArrayList<>();
    private BluetoothGatt bluetoothGatt;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        isLocationOpen();
        BluetoothManager bluetoothManager = (BluetoothManager) getSystemService(Context.BLUETOOTH_SERVICE);
        mBluetoothAdapter = bluetoothManager.getAdapter();
        if (mBluetoothAdapter == null || !mBluetoothAdapter.isEnabled()) {

            Intent enableBluetooth = new Intent(

                    BluetoothAdapter.ACTION_REQUEST_ENABLE);

            startActivityForResult(enableBluetooth, 1);
        }
        mBluetoothAdapter.startLeScan(mLeScanCallback);
    }

    static final char[] hexArray = "0123456789ABCDEF".toCharArray();

    private void isLocationOpen() {
        //清单文件里面也需要配置
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M &&
                checkSelfPermission(Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED &&
                checkSelfPermission(Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED &&
                checkSelfPermission(Manifest.permission.CAMERA) != PackageManager.PERMISSION_GRANTED) {
            requestPermissions(new String[]{Manifest.permission.ACCESS_COARSE_LOCATION, Manifest.permission.ACCESS_FINE_LOCATION,
                    Manifest.permission.CAMERA,}, 0);
        }
    }

    //系统方法,从requestPermissions()方法回调结果
    @Override
    public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
        //确保是我们的请求
        if (requestCode == REQUEST_COARSE_LOCATION) {
            if (grantResults[0] == PackageManager.PERMISSION_GRANTED) {
                Toast.makeText(this, "权限被授予", Toast.LENGTH_SHORT).show();
            } else if (grantResults[0] != PackageManager.PERMISSION_GRANTED) {
                Toast.makeText(this, "权限被拒绝", Toast.LENGTH_SHORT).show();
            }
        } else {
            super.onRequestPermissionsResult(requestCode, permissions, grantResults);
        }
    }

    private static String bytesToHex(byte[] bytes) {

        char[] hexChars = new char[bytes.length * 2];

        for (int j = 0; j < bytes.length; j++) {

            int v = bytes[j] & 0xFF;

            hexChars[j * 2] = hexArray[v >>> 4];

            hexChars[j * 2 + 1] = hexArray[v & 0x0F];

        }

        return new String(hexChars);

    }

    private BluetoothAdapter.LeScanCallback mLeScanCallback = new BluetoothAdapter.LeScanCallback() {

        @Override

        public void onLeScan(final BluetoothDevice device, final int rssi, final byte[] scanRecord) {
            if (!devices.contains(device)) {

            }
            bluetoothGatt = device.connectGatt(MainActivity.this, false, gattCallback);
        }
    };


    private BluetoothGattCallback gattCallback = new BluetoothGattCallback() {
        //链接状态改变回调此方法。
        @Override
        public void onConnectionStateChange(BluetoothGatt gatt, int status, int newState) {
            super.onConnectionStateChange(gatt, status, newState);
            switch (newState) {
                case BluetoothGatt.STATE_CONNECTED://已连接
                    Log.e("lee", "已连接");
                    //去寻找服务
                    bluetoothGatt.discoverServices();
                    break;
                case BluetoothGatt.STATE_CONNECTING://连接中
                    Log.e("lee", "连接中");
                    break;
                case BluetoothGatt.STATE_DISCONNECTED://已断开
                    Log.e("lee", "已断开");
                    break;
                case BluetoothGatt.STATE_DISCONNECTING://断开中
                    Log.e("lee", "断开中");
                    break;
            }
        }
		
		//当读取到设备的信息时回调此方法
        @Override
        public void onCharacteristicRead(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic, int status) {
            super.onCharacteristicRead(gatt, characteristic, status);
            if (status == BluetoothGatt.GATT_SUCCESS) {//读取成功
                if (characteristic.getUuid().equals("22222")) {
                    byte[] value = characteristic.getValue();
                }
            }
        }

        //当特征值改变时回调此方法。
        @Override
        public void onCharacteristicChanged(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic) {
            super.onCharacteristicChanged(gatt, characteristic);
            //通过判断characteristic的UUID和我们下面的那个11111的UUid是不是一样的 是一样的就可以做对应的操作了。
            if (characteristic.getUuid().equals("11111")){
                //获取characteristic中的值
                byte[] value = characteristic.getValue();
                //转化成16进制
                String s = bytesToHex(value);
                if (s.equals("0x55")){
                    //执行对应的操作
                }
            }
        }

        //当服务被找到时回调此方法。
        @Override
        public void onServicesDiscovered(BluetoothGatt gatt, int status) {
            super.onServicesDiscovered(gatt, status);
            if (status == BluetoothGatt.GATT_SUCCESS) {//寻找服务成功。
                //或许该设备下的所有服务(每个服务都有自己的UUID)
                List<BluetoothGattService> services = gatt.getServices();
                for (BluetoothGattService service : services) {
                    //获取该服务下的所有的特性
                    List<BluetoothGattCharacteristic> characteristics = service.getCharacteristics();
                    for (BluetoothGattCharacteristic characteristic : characteristics) {
                        //此处可以和蓝牙设备的硬件工程师交流 哪个特征值是对应的什么效果。 然后通过调用
                        if (characteristic.getUuid().equals("00000")) {//(此处我就瞎写一个) 通过UUID来获取硬件工程师告诉你的特征
                            characteristic.setValue(new byte[]{0x05});//(这个也是我瞎写的  需要蓝牙硬件工程师告诉你)
                            //调用了这个setValue()方法写入对应的数据,就能调用蓝牙设备的该特性了。
                        }


                        if (characteristic.getUuid().equals("11111")) {//(此处我就瞎写一个) 获取设备控制App的命令

                            //调用此方法获取设备的通知
                            characteristic.notify();//(这个也是我瞎写的)
                        }
                        
    					if (characteristic.getUuid().equals("22222")) {//(此处我就瞎写一个) 获取设备的电量

                            //调用此方法获取设备的通知 读取到时会回调
                            gatt.readCharacteristic(characteristic);
                        }
                    }
                }
            }
        }
    };
}

总而言之当App主动联系设备时调用写入,当设备主动联系App是调用通知,当App可能长时间获取设备信息时用读取方法。(这些很多都要看设备的文档信息)

猜你喜欢

转载自blog.csdn.net/qq77485042/article/details/109312987