安卓BLE开发教程(二) BLE开发流程

在安卓上进行BLE开发时,就不必像理解BLE协议栈那样复杂了。因为安卓的BLE包为我们提供了十分丰富的API、各类常量、各类连接通信情况下的回调API等。

具体流程

一、声明权限

二、获取Adapter适配器

三、开启蓝牙

四、BLE扫描与停止

五、连接设备

六、枚举特征值及其属性

七、利用特征值通讯

八、关闭蓝牙


一、声明权限

在AndroidManifest.xml文件中声明应用需要的特性及权限。

<!-- 声明App使用条件为支持BLE -->
<uses-feature android:name="android.hardware.bluetooth_le" android:required="true"/>
<!-- 声明蓝牙权限 -->
<uses-permission android:name="android.permission.BLUETOOTH"/>
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN"/>
<!-- 安卓6.0开始需要此权限 -->
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/>

二、获取Adapter适配器

final BluetoothManager mBluetoothManager =
        (BluetoothManager)getSystemService(Context.BLUETOOTH_SERVICE);
BluetoothAdapter mBluetoothAdapter = mBluetoothManager.getAdapter();

三、开启蓝牙

if (mBluetoothAdapter != null && !mBluetoothAdapter.isEnabled()) {
    Intent intent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
    startActivityForResult(intent, BLE_ENABLE);
}

四、BLE扫描与停止

private boolean mScanning;//是否正在搜索
private Handler mHandler = new Handler();
// 预设15秒扫描时间
private static final int SCAN_PERIOD = 15000;

private void scanLeDevice(final boolean enable) {
    if (enable) {
        // 控制BLE扫描时间
        mHandler.postDelayed(new Runnable() {
            @Override
            public void run() {
                mBluetoothAdapter.stopLeScan(mLeScanCallback);
            }
        }, SCAN_PERIOD);
        mScanning = true;
        // 开始扫描
        mBluetoothAdapter.startLeScan(mLeScanCallback);
    } else {
        mScanning = false;
        // 停止扫描
        mBluetoothAdapter.stopLeScan(mLeScanCallback);
    }
}

在BLE扫描回调函数中保存设备对应的BlueToothDevice对象,rssi信号强度等。

private BluetoothAdapter.LeScanCallback mLeScanCallback = new BluetoothAdapter.LeScanCallback() {
        @Override
        public void onLeScan(final BluetoothDevice device, final int rssi, final byte[] scanRecord) {
            // 保存device及相关信息,也可以通知UI线程显示信息
        }
    };

五、连接设备

使用扫描结果中保存的BluetoothDevice对象调用connectGatt进行通讯。

BluetoothGatt mBluetoothGatt;
// 参数一:context上下文 
// 参数二:是否自动重连
// 参数三: 连接回调
mBluetoothGatt = mBluetoothDevice.connectGatt(context, false, mGattCallback);

连接回调函数实现如下,开发时在此处处理各类可能遇到的情况。

private BluetoothGattCallback mGattCallback = new BluetoothGattCallback() {
    // 连接状态改变的回调
    @Override
    public void onConnectionStateChange(BluetoothGatt gatt, int status,
        int newState) {
        // 具体处理见后文第八项
    };

    // 发现服务回调
    @Override
    public void onServicesDiscovered(BluetoothGatt gatt, int status) {
        // 具体处理见后文第六项
    };

    @Override
    public void onReadRemoteRssi(BluetoothGatt gatt, int rssi, int status) {
        // 由mBluetoothGatt.readRemoteRssi()调用得到,可不停刷新rssi信号强度
        Log.e(TAG, "信号强度RSSI:" + rssi);
    }

    // 写描述信息回调
    @Override
    public void onDescriptorWrite(BluetoothGatt gatt, BluetoothGattDescriptor
        descriptor, int status) {
        
    };

    // 写操作回调
    @Override
    public void onCharacteristicWrite(BluetoothGatt gatt,BluetoothGattCharacteristic 
        characteristic, int status) {
        if (status == BluetoothGatt.GATT_SUCCESS) {
            Log.e(TAG, "写入成功:" + characteristic.getValue());
        }
    };

    // 读操作回调
    @Override
    public void onCharacteristicRead(BluetoothGatt gatt,BluetoothGattCharacteristic 
        characteristic, int status) {
        if (status == BluetoothGatt.GATT_SUCCESS) {
            Log.e(TAG, "读取成功:" + characteristic.getValue());
        }
    }

    // 数据改变回调(接收BLE设备发送的数据)
    @Override
    public void onCharacteristicChanged(BluetoothGatt gatt,BluetoothGattCharacteristic 
        characteristic) {

        };
    };
}

六、枚举特征值及其属性

@Override
// 发现服务回调,即调用了mBluetoothGatt.discoverServices()执行的回调
public void onServicesDiscovered(BluetoothGatt gatt, int status) {
    if (status == BluetoothGatt.GATT_SUCCESS) {
        // 获取Service
        List<BluetoothGattService> mGattServices = gatt.getServices();
        // 获取Service的Characteristics
        for (BluetoothGattService gattService : mGattServices) {
            List<BluetoothGattCharacteristic> mGattCharacteristics =     
                gattService.getCharacteristics();
            for (BluetoothGattCharacteristic gattCharacteristic :
                mGattCharacteristics) {
                int charaProp = gattCharacteristic.getProperties();
                // 所有Characteristics按属性分类
                if ((charaProp | BluetoothGattCharacteristic.PROPERTY_READ) > 0) {
                    Log.e(TAG, "gattCharacteristic的UUID为:" +             
                    gattCharacteristic.getUuid());
                    Log.e(TAG, "gattCharacteristic的属性为:可读");
                    readUuids.add(gattCharacteristic.getUuid());
                }
                if ((charaProp | BluetoothGattCharacteristic.PROPERTY_WRITE) > 0) {
                    Log.e(TAG, "gattCharacteristic的UUID为:" + 
                    gattCharacteristic.getUuid());
                    Log.e(TAG, "gattCharacteristic的属性为:可写");
                    writeUuids.add(gattCharacteristic.getUuid());
                }
                if ((charaProp | BluetoothGattCharacteristic.PROPERTY_NOTIFY) > 0) {
                    Log.e(TAG, "gattCharacteristic的UUID为:" + 
                    gattCharacteristic.getUuid() + gattCharacteristic);
                    Log.e(TAG, "gattCharacteristic的属性为:具备通知属性");
                    notifyUuids.add(gattCharacteristic.getUuid());
                }
            }
        }
    } else {
        Log.e(TAG, "onServicesDiscovered 失败,status:" + status);
    }
}

七、利用特征值通讯

1、写数据

public void writeChara(byte) {
    BluetoothGattCharacteristic mGattCharacteristic =             
        mBluetoothGatt.getCharacteristic(writeUuid);
    mGattCharacteristic.setValue(sendValue);
    mBluetoothGatt.writeCharacteristic(mGattCharacteristic);
}

2、读数据

public void readChara() {
    // 读取数据
    BluetoothGattCharacteristic mGattCharacteristic =         
        mBluetoothGatt.getCharacteristic(readUuid);
    mBluetoothGatt.readCharacteristic(mGattCharacteristic);
}

3、监听通知属性的数据

mBluetoothGatt.setCharacteristicNotification(mGattCharacteristic, enabled);
BluetoothGattDescriptor mGattDescriptor = mGattCharacteristic.getDescriptor(
        UUID.fromString(SampleGattAttributes.CLIENT_CHARACTERISTIC_CONFIG));
mGattDescriptor.setValue(BluetoothGattDescriptor.ENABLE_NOTIFICATION_VALUE);
mBluetoothGatt.writeDescriptor(mGattDescriptor);

八、关闭蓝牙

合理的关闭步骤为,先调用BluetoothGatt#disconnect进行断开连接,此时会在BluetoothGattCallback#onConnectionStateChange接收到断开成功的回调,然后在回调中调用BluetoothGatt#close释放相关资源。

// 首先执行该disconnect操作,然后等待回调通知
mBluetoothGatt.disconnect();
@Override
public void onConnectionStateChange(BluetoothGatt gatt, int status,
    int newState) {
    if (newState != BluetoothGatt.GATT_SUCCESS) {
        // 连接失败直接在此处理即可,因此时调用disconnect无法进入下面条件
        Log.e(TAG, "连接失败, status:" + status);
        gatt.close();
        return;
    }
    if (newState == BluetoothGatt.STATE_DISCONNECTED) {
        // 连接断开
        Log.e(TAG, "连接断开");
        mBluetoothGatt.close();
    } else if (newState == BluetoothProfile.STATE_CONNECTED) {
        // 连接成功后启动服务发现
        Log.e(TAG, "连接成功");
        mBluetoothGatt.discoverServices();
    }
};
发布了131 篇原创文章 · 获赞 464 · 访问量 62万+

猜你喜欢

转载自blog.csdn.net/JAZZSOLDIER/article/details/85131396
今日推荐