android6.0以上版本蓝牙4.0开发

来源:互联网 发布:淘宝如何设置手机客服 编辑:程序博客网 时间:2024/06/05 13:23

        首先说一下蓝牙2.0和蓝牙4.0的区别,蓝牙2.0开发用的是socket协议直接连接设备指定的UUID,按字节读取的情况比较多,但是蓝牙4.0在开发时,新版本把它封装成一个类来调用的。

        开发蓝牙4.0,首先了解一下支持蓝牙4.0设备的基本信息:蓝牙有好多的gatt服务,也就是service,而每一个gatt服务下面有很多的特征值,也就是characteristic,每一个服务,特征值都会对应一个UUID,这个UUID一般都是硬件开发已经写好的,我们在用android开发和它通信时,只要找到正确的UUID就行了,有些硬件厂商会给,要是没给的话,可以自己一个一个试出来,反正一般情况下不会太多,毕竟谁会在硬件上开发那么多服务但是实际上用的却没几个。

        好了,了解上面的东西后,就知道怎么开发了,

        1.首先manifest配置权限,一般需要到的如下:

<uses-permission android:name="android.permission.BLUETOOTH" /><uses-permission android:name="android.permission.BLUETOOTH_ADMIN" /><uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
    这个就比较简单了,一般做开发的都知道,如果还需要存储和读写进SD卡,最好把sd卡的权限也加上。
     2.然后呢,因为谷歌在6.0之后权限做了约束,需要动态申请,这个代码大致如下:
public void requestPermission(){    if (ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION)            != PackageManager.PERMISSION_GRANTED) {        ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.ACCESS_COARSE_LOCATION},                1);        ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.BLUETOOTH, Manifest.permission.BLUETOOTH_ADMIN, Manifest.permission.BLUETOOTH_PRIVILEGED},                2);    }else {    }    if(ContextCompat.checkSelfPermission(this, Manifest.permission.BLUETOOTH) != PackageManager.PERMISSION_GRANTED){        ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.BLUETOOTH, Manifest.permission.BLUETOOTH_ADMIN, Manifest.permission.BLUETOOTH_PRIVILEGED},                5);    }    if (ContextCompat.checkSelfPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED){        ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE, Manifest.permission.READ_EXTERNAL_STORAGE,                        Manifest.permission.MOUNT_UNMOUNT_FILESYSTEMS},                3);    }}

ACCESS_COARSE_LOCATION 也很重要,以前的蓝牙开发是不需要这个权限的,到后来需要也加上这个权限。
3.判断蓝牙设备是否支持:
//initial bluetooth adapterBluetoothManager bluetoothManager =        (BluetoothManager) a.getSystemService(Context.BLUETOOTH_SERVICE);mBluetoothAdapter = bluetoothManager.getAdapter();//check support adapter or notif (mBluetoothAdapter == null) {    Toast.makeText(a,"device is not supported", Toast.LENGTH_SHORT).show();    return;}
4.获取scanner对象和BluetoothGattCallBack对象,BluetoothGattCallBack这个类是在连接设备后获取gatt服务的回调。
mBluetoothLeScanner = mBluetoothAdapter.getBluetoothLeScanner();
mBluetoothGattCallBack = new BluetoothGattCallback() {            @Override            public void onConnectionStateChange(BluetoothGatt gatt, int status, int newState) {                Log.i("blb", "--------state change");//                gatt.discoverServices();                if (newState == BluetoothProfile.STATE_CONNECTED) {//                    gatt.discoverServices();//if connected, discover services of remote device                    Log.i("blb","-------state connected");
    //自己定义一个广播通知已经连接                    a.sendBroadcast(new Intent(CONNECTION_ACTION));//send broadcast to notify device is connected                    gatt.discoverServices();                }else if (newState == BluetoothProfile.STATE_DISCONNECTED){                    Log.i("blb", "---------disconnected");
                    //自己定义一个广播通知已经断开                    a.sendBroadcast(new Intent(DISCONNECTED_ACTION));//send broadcast to notify device is disconnected                }                Log.i("blb", "state change" + ", status:" + status + ", new State:" + newState);                super.onConnectionStateChange(gatt, status, newState);            }            @Override            public void onServicesDiscovered(BluetoothGatt gatt, int status) {                super.onServicesDiscovered(gatt, status);                Log.i("blb", "device service discovered");                List<BluetoothGattService> lists = gatt.getServices();                Log.i("blb", "-------gatt service size:" + lists.size());                for (int i = 0; i < lists.size(); i++) {                    BluetoothGattService temp = lists.get(i);                    List<BluetoothGattCharacteristic> cLists = temp.getCharacteristics();                    Log.i("blb", "--------i:" + i + ", uuid:" + temp.getUuid() + ", characteristic size:" + cLists.size());                    for (int j = 0; j < cLists.size(); j++) {                        final BluetoothGattCharacteristic bcdemo = cLists.get(j);                        final int charaProp = bcdemo.getProperties();                        Log.i("blb", "---------i's character:" + bcdemo.getUuid() + ", ");                        if ((charaProp | BluetoothGattCharacteristic.PROPERTY_NOTIFY) > 0) {                            Log.i("blb", "----notifycation is available" + ", i:" + i + ", j:" + j);                        }                    }                }
//这里可以设置需要访问的属性值,就是前面说的UUID,可以从厂商那里得到,也可以自己一个一个试出来
mBluetoothGatt.setCharacteristicNotification(lists.get(3).getCharacteristics().get(0), true); }
           
            @Override            public void onCharacteristicRead(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic, int status) {                super.onCharacteristicRead(gatt, characteristic, status);                Log.i("blb", "character read");                String value = bytesToHexString(characteristic.getValue());                Log.i("blb",gatt.getDevice().getName() + " recieved " + value + ", length:" + characteristic.getValue().length);            }            @Override            public void onCharacteristicWrite(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic, int status) {                super.onCharacteristicWrite(gatt, characteristic, status);                Log.i("blb", "------write");            }
            //这个回调是你设置的那个蓝牙service下的特征值发生改变时,会走这个方法,在这里做业务上的处理就行了,如果只需要读一次的话,直接使用read方法,            @Override            public void onCharacteristicChanged(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic) {                super.onCharacteristicChanged(gatt, characteristic);                    Log.i("blb", "---------characteristic changed read from device:" + bytesToHexString(characteristic.getValue()));            }            @Override            public void onDescriptorRead(BluetoothGatt gatt, BluetoothGattDescriptor descriptor, int status) {                super.onDescriptorRead(gatt, descriptor, status);                Log.i("blb", "descrptor read");                descriptor.getValue();            }            @Override            public void onDescriptorWrite(BluetoothGatt gatt, BluetoothGattDescriptor descriptor, int status) {                super.onDescriptorWrite(gatt, descriptor, status);                Log.i("blb", "descrptor write");            }            @Override            public void onReliableWriteCompleted(BluetoothGatt gatt, int status) {                super.onReliableWriteCompleted(gatt, status);                Log.i("blb", "ReliableWriteCompleted");            }            @Override            public void onReadRemoteRssi(BluetoothGatt gatt, int rssi, int status) {                super.onReadRemoteRssi(gatt, rssi, status);                Log.i("blb", "ReadRemoteRssi");            }            @Override            public void onMtuChanged(BluetoothGatt gatt, int mtu, int status) {                super.onMtuChanged(gatt, mtu, status);                Log.i("blb", "----onMtuChanged");            }        };
    5.扫描的时候需要用到一个回调,这个类就是ScanCallBack类,new一个就行:
mScanCallback = new ScanCallback() {            @Override            public void onScanResult(int callbackType, ScanResult result) {                super.onScanResult(callbackType, result);                BluetoothDevice bluetoothDevice = result.getDevice();                Log.i("blb", "-------scan result:" + bluetoothDevice.getName() + ", address:" + bluetoothDevice.getAddress());                //00:15:83:00:41:DB.equalsIgnoreCase(bluetoothDevice.getAddress()                if (bluetoothDevice.getName() != null){                    if (bluetoothDevice.getName().toLowerCase().contains("bpm")){//根据字符串判断出是否是指定型号的设备,如果已经搜到就停止搜索                        Log.i("blb", "-------contains");                        mBluetoothLeScanner.stopScan(mScanCallback);//停止搜索                        mBluetoothGatt = bluetoothDevice.connectGatt(a, true, mBluetoothGattCallBack);//连接gatt服务                    }                }                ParcelUuid[] uuids = bluetoothDevice.getUuids();                if (uuids != null){                    Log.i("blb", "------uuid length:" + uuids.length);                    for (int i = 0; i < uuids.length; i++) {                    }                }            }            @Override            public void onBatchScanResults(List<ScanResult> results) {                super.onBatchScanResults(results);                Log.i("blb", "---------batch scan result");            }            @Override            public void onScanFailed(int errorCode) {                super.onScanFailed(errorCode);                Log.i("blb", "--------scan failed");            }        };
    6.前面的工作全部做好后,就可以扫描了,扫描后自动连接,可以获取蓝牙设备的所有服务,你只要找到UUID就可以通信了。
//start le scanpublic void startLeScan(){    mBluetoothLeScanner.startScan(mScanCallback);}
   7.停止的话就直接调用stopScan就行了,如果只是单单的读取一次的话,直接调用read方法就行,后面会回调到onCharacteristicRead方法,根据需求自己用逻辑处理下就行了。
0 0