有关Android Bluetooth/蓝牙的介绍

来源:互联网 发布:mac有没有软件助手 编辑:程序博客网 时间:2024/05/01 01:41

最近在做android bluetooth方面的项目,在网上找了很多所谓的demo和官方的demo。发现或多或少的都有些问题,今天是第一次写技术方面的文章,我就从这篇开始吧!
关于android bluetooth 无非就是三点:
一. 扫描蓝牙 二. 连接蓝牙设备 三. 通信。
下面让我们就同第一点开始:
android蓝牙的扫描有三种函数:
1.public boolean startDiscovery();
2.public boolean startLeScan(LeScanCallback callback)和 public boolean startLeScan(final UUID[] serviceUuids, final LeScanCallback callback)。
这两张函数都是在BluethoothAdapter这个类中。下面我们就来解释下这两个函数:
public boolean startDiscovery()这个函数只能扫描传统意义的蓝牙设备 时间扫描12s自动关闭,这是异步操作扫描蓝牙设备。首先你要注册一个接收者。
filter = new IntentFilter(BluetoothDevice.ACTION_FOUND);
this.registerReceiver(mReceiver, filter);
filter = new IntentFilter(BluetoothAdapter.ACTION_DISCOVERY_FINISHED);
this.registerReceiver(mReceiver, filter);
//广播接收者
private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
if (BluetoothDevice.ACTION_FOUND.equals(action)) {
} else if (BluetoothAdapter.ACTION_DISCOVERY_FINISHED.equals(action))
}
}
}
};
当然还有其他的广播事件你也可以注册。请自己查看SDK。
public boolean startLeScan(LeScanCallback callback)和 public boolean startLeScan(final UUID[] serviceUuids, final LeScanCallback callback)这两个函数是扫描低功耗蓝牙设备的,好像没有扫描时间限制,只能调用public void stopLeScan(LeScanCallback callback)来关闭。这个两个不同的地方就是可以过滤你想要扫描的UUID,他们都是通过的LeScanCallback回调接口来返回扫描的结果。
private BluetoothAdapter.LeScanCallback mLeScanCallback = new BluetoothAdapter.LeScanCallback() {
@Override
public void onLeScan(final BluetoothDevice device, int rssi, byte[] scanRecord) {

                runOnUiThread(new Runnable() {                    @Override                    public void run() {                        LogUtil.d(TAG, device.getAddress()+" LeScanCallback:::"+device.getName());                        if (!mArrayList.contains(device)) {                            mArrayList.add(device);                            mDeviceAdapter.notifyDataSetChanged();                        }                    }                });            }        };

但是这种扫描低功耗蓝牙的方法在api21就被标记废弃使用。下面介绍第三扫描蓝牙设备的函数:
3.public void startScan(final ScanCallback callback)和public void startScan(List filters, ScanSettings settings, final ScanCallback callback)这连个函数和第二差不多,区别是这个是用来代替第二个的,函数在BluetoothLeScanner类中。mBluetoothLeScanner = mBluetoothAdapter.getBluetoothLeScanner();也都是通过ScanCallBack的回调来处理函数结果的。区别是后面一个是用来过滤你想要扫描到低功耗蓝牙设备。至于怎么去过滤我还没去研究,可以自行看sdk和网上早资料。该动手的时候还是的自己来!有关android 蓝牙扫描就到这里了下面讲连接蓝牙设备。
第二点 蓝牙的连接:
public BluetoothGatt connectGatt(Context context, boolean autoConnect,
BluetoothGattCallback callback, int transport),扫描到结果后会得到BluetoothDevice。而这个函数恰好是在BluetoothDevice类中。调用它就可以连接蓝牙设备了,其中一个参数是BluetoothGattCallback这个回调函数中有:

  public void onConnectionStateChange(BluetoothGatt gatt, int status,                                    int newState) {}public void onServicesDiscovered(BluetoothGatt gatt, int status) {}public void onCharacteristicRead(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic,                                 int status) {}public void onCharacteristicWrite(BluetoothGatt gatt,                                  BluetoothGattCharacteristic characteristic, int status) {}public void onCharacteristicChanged(BluetoothGatt gatt,                                    BluetoothGattCharacteristic characteristic) {}public void onDescriptorRead(BluetoothGatt gatt, BluetoothGattDescriptor descriptor,                             int status) {}public void onDescriptorWrite(BluetoothGatt gatt, BluetoothGattDescriptor descriptor,                              int status) {}public void onReliableWriteCompleted(BluetoothGatt gatt, int status) {}public void onReadRemoteRssi(BluetoothGatt gatt, int rssi, int status) {}public void onMtuChanged(BluetoothGatt gatt, int mtu, int status) {}

这里面有多个函数的回调处理结果。当你连接成功或断开后会回调onConnectionStateChange();而onServicesDiscovered()的这个函数的回调要主动请求的。
public void onConnectionStateChange(BluetoothGatt gatt, int status, int newState) {
super.onConnectionStateChange(gatt, status, newState);
if (newState == BluetoothProfile.STATE_CONNECTED){
gatt.discoverServices();}
调用粗体的函数后才会触发onServicesDiscovered(BluetoothGatt gatt, int status) 。onServicesDiscovered(BluetoothGatt gatt, int status) 的作用是发现蓝牙可用的services,List list = gatt.getServices();会获取到所有services。一个蓝牙设备会有多个services,一个service会有多个BluetoothGattCharacteristic,一个BluetoothGattCharacteristic会有多个BluetoothGattDescriptor:

   public void setService(final BluetoothGatt gatt){    List<BluetoothGattService> list = gatt.getServices();    List<BluetoothGattCharacteristic> mCharacteristics;    List<BluetoothGattDescriptor> mDescriptors;    if (list.size()>0){        for (BluetoothGattService service : list){            int type = service.getType();            if (service.getUuid().toString().equalsIgnoreCase(SERUUID_STR.toString())){                LogUtil.e(TAG, "-->BluetoothGattService uuid:" + service.getUuid());                LogUtil.e(TAG, "-->BluetoothGattService value:" + service.getType());                mCharacteristics = service.getCharacteristics();                for (BluetoothGattCharacteristic characteristic : mCharacteristics){                    if (characteristic.getUuid().toString().equalsIgnoreCase(WRITE_UUID.toString())){                        LogUtil.e(TAG, "-->characteristic write uuid:" + characteristic.getUuid());                        LogUtil.e(TAG, "-->characteristic value:" + characteristic.getValue());                        LogUtil.e(TAG, "-->characteristic getProperties:" + characteristic.getProperties());                        LogUtil.e(TAG, "-->characteristic getPermissions:" + characteristic.getPermissions());                        write_characteristic = characteristic;                        **setCharacteristicNotification**(write_characteristic,true);                     }                 else if(characteristic.getUuid().toString().equalsIgnoreCase(READ_UUID.toString())){                        LogUtil.e(TAG, "-->characteristic write uuid:" + characteristic.getUuid());                        LogUtil.e(TAG, "-->characteristic value:" + characteristic.getValue());                        LogUtil.e(TAG, "-->characteristic getProperties:" + characteristic.getProperties());                        LogUtil.e(TAG, "-->characteristic getPermissions:" + characteristic.getPermissions());                        read_characteristic = characteristic;                        **setCharacteristicNotification**(read_characteristic,true);                        readCharacteristic(read_characteristic);                    }                    mDescriptors = characteristic.getDescriptors();                    for (BluetoothGattDescriptor  descriptor : mDescriptors){                        LogUtil.e(TAG, "-->BluetoothGattDescriptor  uuid:" + descriptor.getUuid());                        LogUtil.e(TAG, "-->BluetoothGattDescriptor value:" + descriptor.getValue());                        LogUtil.e(TAG, "-->BluetoothGattDescriptor getPermissions:" + descriptor.getPermissions());                    }                }            }        }        }

以上都是android蓝牙链接蓝牙设备的介绍。
第三点 蓝牙之间的通信:
在上面你可以获取到所有的BluetoothGattService,BluetoothGattCharacteristic,
BluetoothGattDescriptor。通过设置BluetoothGattCharacteristic的setCharacteristicNotification(read_characteristic,true)来达到数据交换。每一个BluetoothGattCharacteristic都有个UUID和属性是通过蓝牙文档来了解每个BluetoothGattCharacteristic的读,写,提醒等属性来进行数据交换。会触发BluetoothGattCallback这个回调函数中的读写提醒等回调函数的回调,然后你就可以获取读写的数据了。
下面在写下在android蓝牙开发中应该注意的一些问题,希望对看到的人有点帮助:
1.权限的问题

  <uses-permission android:name="android.permission.BLUETOOTH_ADMIN" />    <uses-permission android:name="android.permission.BLUETOOTH" /><uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/> 第三个权限是在有的机型上面需要获取位置信息才能扫描的。 在sdk 23上面版本的时候需要 代码获取位置权限 private boolean mayRequestLocation() {    if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) {        return true;    }    if (checkSelfPermission(permission) == PackageManager.PERMISSION_GRANTED) {        return true;    }    else {        LogUtil.d(TAG,"REQUEST PERMISSION");        requestPermissions(new String[]{permission}, REQUEST_FINE_LOCATION);    }    return false;}要不然你很有可能扫不到蓝牙设备。

2.数据读写问题
楼主在写入数据的时候会出现数据丢失,蓝牙设备有时候会丢失一段数据,据楼主观察是写入数据的时候太快的问题,但我在写入数据时候稍微延迟300ms的时候会好很多。具体楼主觉得写入太快导致。

3.demo问题
请不要让我发demo,如需要参考你参考android sdk中有关于蓝牙的两个demo 一个是 bluetoothchat 这是用蓝牙实现聊天的demo用的bluetoothSocket实现的。还有一个低功耗的bluetoothLeGatt的demo。大家可以去了解下,多动手多动脑多犯错!

0 0