Anroid BLE蓝牙(手机分别作为中心设备和外围设备)

本文详细介绍了蓝牙BLE技术的基础概念及应用场景,包括移动扩展设备、汽车电子、健康医疗等多个领域。同时,提供了Android平台上蓝牙BLE的操作流程,从权限声明、设备支持判断到蓝牙的连接与数据交互,帮助开发者快速掌握BLE技术。

        蓝牙是一种短距的无线通讯技术,可实现固定设备、移动设备之间的数据交换。一般将蓝牙3.0之前的BR/EDR蓝牙称为传统蓝牙,而将蓝牙4.0规范下的LE蓝牙称为低功耗蓝牙。

 BLE蓝牙模块主要应用领域

    1、移动扩展设备

    2、汽车电子设备

    3、健康医疗用品:心跳带、血压计等

    4、定位应用:室内定位、井下定位等

    5、近距离数据采集:无线抄表、无线遥测等

    6、数据传输:智能家居室内控制、蓝牙调光、打印机等

   手机作为中心设备连接外围设备 蓝牙的操作流程

        1.声明蓝牙权限               

<uses-permission android:name="android.permission.BLUETOOTH" />
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN" />
<uses-permission android:name="android.permission.BLUETOOTH_PRIVILEGED" />

   在 Android 6.0 及以上,还需要打开位置权限。如果应用没有位置权限,蓝牙扫描功能不能使用

<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/>
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>

    2.判断设备是否支持BLE蓝牙

        

public boolean isSupportBle() {
    return mContext.getApplicationContext()
            .getPackageManager().hasSystemFeature(PackageManager.FEATURE_BLUETOOTH_LE);
}

   3.初始化蓝牙


public BleBluetooth(Context context) {
    this.context = context = context.getApplicationContext();
    bluetoothManager = (BluetoothManager) context
            .getSystemService(Context.BLUETOOTH_SERVICE);
    bluetoothAdapter = bluetoothManager.getAdapter();
}

4.是否开启蓝牙

public boolean isBlueEnable() {
    return bluetoothAdapter.isEnabled();
}

5.开启蓝牙

public void enableBluetooth() {
    bluetoothAdapter.enable();
}

6.扫描蓝牙

    6.0以上要动态设置权限

public void scanDevice(BluetoothAdapter.LeScanCallback callback, Activity activity) {
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
        // Android M Permission check
        if (activity.checkSelfPermission(Manifest.permission.ACCESS_COARSE_LOCATION) !=
                PackageManager.PERMISSION_GRANTED) {
            //TODO 权限适配 终止
            activity.requestPermissions(new String[]{Manifest.permission
                    .ACCESS_COARSE_LOCATION}, PERMISSION_REQUEST_COARSE_LOCATION);
        } else {
            
    mbluetoothAdapter.startLeScan(callBack);
} } else {
    mbluetoothAdapter.startLeScan(callBack);
}} @Override public void onRequestPermissionsResult( int requestCode , String[] permissions , int[] grantResults) { super.onRequestPermissionsResult(requestCode , permissions , grantResults) ; switch (requestCode) { case PERMISSION_REQUEST_COARSE_LOCATION: if (grantResults[ 0] == PackageManager. PERMISSION_GRANTED) {
        mbluetoothAdapter.startLeScan(callBack);
} break; }}
mbluetoothAdapter.startLeScan(callBack);

BluetoothAdapter.LeScanCallback callBack = new BluetoothAdapter.LeScanCallback() {
    @Override
    public void onLeScan(BluetoothDevice device, int rssi, byte[] scanRecord) {
    //TODO 处理扫描到的结果
        Device = device;
    }
}; 

6.连接蓝牙

7.寻找服务,并打开

Device.connectGatt(this,false,coreGattCallback);

BluetoothGattCallback connectCallback = new BluetoothGattCallback() {
    @Override
    public void onConnectionStateChange(BluetoothGatt gatt, int status, int newState) {
        super.onConnectionStateChange(gatt, status, newState);
       //TODO 蓝牙连接状态的回调,在这里根据newState判断蓝牙是否连接成功
        if (newState == BluetoothGatt.STATE_CONNECTED) {
            mbluetoothGatt = gatt;
        } else if (newState == BluetoothGatt.STATE_DISCONNECTED) {

        } else if (newState == BluetoothGatt.STATE_CONNECTING) {

        }
    }

    @Override
    public void onServicesDiscovered(BluetoothGatt gatt, int status) {
        super.onServicesDiscovered(gatt, status);
       //TODO 在发方法中找服务并找到可通知的特征值
        BluetoothGattService bleService = gatt.getService(UUID.fromString("0000fee7-0000-1000-8000-00805f9b34fb"));
        List<BluetoothGattCharacteristic> characteristics = bleService
                .getCharacteristics();
        for (BluetoothGattCharacteristic characteristic :characteristics) {
            int charaProp = characteristic.getProperties();
            //找到可通知的特征
            UUID_NOFITY = characteristic.getUuid();
            if ((charaProp & BluetoothGattCharacteristic.PROPERTY_NOTIFY) > 0) {
                //使所有的描述可通知
                for (BluetoothGattDescriptor descripter : characteristic.getDescriptors()){
                    descripter.setValue(BluetoothGattDescriptor.ENABLE_NOTIFICATION_VALUE);
                    gatt.writeDescriptor(descripter);
                }
            }else if((charaProp & BluetoothGattCharacteristic.PROPERTY_INDICATE) > 0){
                //使所有的描述可通知
                UUID_INDICATE = characteristic.getUuid();
                for (BluetoothGattDescriptor descripter : characteristic.getDescriptors()){
                    descripter.setValue(BluetoothGattDescriptor.ENABLE_INDICATION_VALUE);
                    gatt.writeDescriptor(descripter);
                }
            }
        }


        //根据notify还是indicate来设置可写的描述
        for (BluetoothGattCharacteristic characteristic :characteristics) {
            int charaProp = characteristic.getProperties();
            if((charaProp & BluetoothGattCharacteristic.PROPERTY_WRITE_NO_RESPONSE) > 0
                    || (charaProp & BluetoothGattCharacteristic.PROPERTY_WRITE) > 0){
                UUID_WRITE = characteristic.getUuid();

                //使所有的描述可通知
                for (BluetoothGattDescriptor descripter : characteristic.getDescriptors()){
                    if(UUID_NOFITY != null && UUID_INDICATE == null){
                        descripter.setValue(BluetoothGattDescriptor.ENABLE_NOTIFICATION_VALUE);
                    }else if(UUID_INDICATE != null && UUID_NOFITY == null){
                        descripter.setValue(BluetoothGattDescriptor.ENABLE_INDICATION_VALUE);
                    }
                    gatt.writeDescriptor(descripter);
                }
            }
        }

    }

    @Override
    public void onCharacteristicRead(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic, int status) {
        super.onCharacteristicRead(gatt, characteristic, status);
    }

    @Override
    public void onCharacteristicWrite(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic, int status) {
        super.onCharacteristicWrite(gatt, characteristic, status);
        //TODO 在这里判断想设备是否写数据成功
    }

    @Override
    public void onCharacteristicChanged(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic) {
        super.onCharacteristicChanged(gatt, characteristic);
        //TODO 接受设备上发是数据
    }

    @Override
    public void onDescriptorRead(BluetoothGatt gatt, BluetoothGattDescriptor descriptor, int status) {
        super.onDescriptorRead(gatt, descriptor, status);
    }

    @Override
    public void onDescriptorWrite(BluetoothGatt gatt, BluetoothGattDescriptor descriptor, int status) {
        super.onDescriptorWrite(gatt, descriptor, status);

 } 
@Override
 
public void 
onReliableWriteCompleted(BluetoothGatt gatt
, int status) { 
super.onReliableWriteCompleted(gatt
, status)
;
 } 
@Override
 
public void 
onReadRemoteRssi(BluetoothGatt gatt
, int rssi
, int status) { 
super.onReadRemoteRssi(gatt
, rssi
, status)
;
 } 
@Override
 
public void 
onMtuChanged(BluetoothGatt gatt
, int mtu
, int status) { 
super.onMtuChanged(gatt
, mtu
, status)
;
 }}
;

8.断开蓝牙

mbluetoothGatt.close();

手机作为外围设备,发送广播供中心设备连接

1.获取BluetoothLeAdvertiser实例

private void initialize(){
    if(mBluetoothLeAdvertiser==null){
       mBluetoothManager=(BluetoothManager)getSystemService(Context.BLUETOOTH_SERVICE);
        if(mBluetoothManager!=null){
            BluetoothAdapter bluetoothAdapter=mBluetoothManager.getAdapter();
            if(bluetoothAdapter!=null){
                mBluetoothLeAdvertiser=bluetoothAdapter.getBluetoothLeAdvertiser();
            }else{
                Toast.makeText(this,"设备不支持蓝牙广播",Toast.LENGTH_SHORT).show();
            }
        }else{
            Toast.makeText(this,"不支持蓝牙",Toast.LENGTH_SHORT).show();
        }
    }
}
2.设置参数
private AdvertiseSettings buildAdvertiseSettings(){
    AdvertiseSettings.Builder settingsBuilder=new AdvertiseSettings.Builder();
    settingsBuilder.setAdvertiseMode(AdvertiseSettings.ADVERTISE_MODE_LOW_POWER);
    settingsBuilder.setTimeout(0);

    return settingsBuilder.build();
}
private AdvertiseData buildAdvertiseData(){
    AdvertiseData.Builder dataBuilder=new AdvertiseData.Builder();
    dataBuilder.setIncludeDeviceName(true);

    return dataBuilder.build();
}
3.开始广播
private void startAdvertising(){
    
    Log.d(TAG,"服务开始广播");
    if(mAdertiseCallback==null){
        AdvertiseSettings settings=buildAdvertiseSettings();
        AdvertiseData data=buildAdvertiseData();
        mAdertiseCallback=new SampleAdvertiseCallback();

        if(mBluetoothLeAdvertiser!=null){
            mBluetoothLeAdvertiser.startAdvertising(settings,data,mAdertiseCallback);
        }
    }
}
4.广播回调
private class SampleAdvertiseCallback extends AdvertiseCallback{
    @Override
    public void onStartFailure(int errorCode){
        super.onStartFailure(errorCode);

        Log.d(TAG,"广播失败");
        sendFailureIntent(errorCode);
        stopSelf();
    }

    @Override
    public void onStartSuccess(AdvertiseSettings settingsInEffect){
        super.onStartSuccess(settingsInEffect);
        Log.d(TAG,"服务端的广播成功开启");
        initServices(getContext());//该方法是添加一个服务,在此处调用即将服务广播出去
    }
}
5. 为设备添加服务
 private void initServices(Context context){
//        获取BluetoothGattServer的实例
        mBluetoothGattServer=mBluetoothManager.openGattServer(context,bluetoothGattServerCallback);
        BluetoothGattService service=new BluetoothGattService(UUID_SERVER,BluetoothGattService.SERVICE_TYPE_PRIMARY);

        characteristicRead=new BluetoothGattCharacteristic(UUID_CHARREAD,BluetoothGattCharacteristic.PROPERTY_READ,BluetoothGattCharacteristic.PERMISSION_READ);
        service.addCharacteristic(characteristicRead);

         characteristicWrite=new BluetoothGattCharacteristic(UUID_CHARWRITE,
                BluetoothGattCharacteristic.PROPERTY_WRITE ,
                BluetoothGattCharacteristic.PERMISSION_WRITE);
        service.addCharacteristic(characteristicWrite);


        characteristicIndicate = new BluetoothGattCharacteristic(UUID_INDICATE,
                BluetoothGattCharacteristic.PROPERTY_INDICATE,
                BluetoothGattCharacteristic.PERMISSION_WRITE);
        BluetoothGattDescriptor descriptor=new BluetoothGattDescriptor(UUID_DESCRIPTOR,BluetoothGattCharacteristic.PERMISSION_WRITE);
        characteristicIndicate.addDescriptor(descriptor);
        service.addCharacteristic(characteristicIndicate);

        mBluetoothGattServer.addService(service);
    }
6.服务回调
//服务事件的回调
private BluetoothGattServerCallback bluetoothGattServerCallback=new BluetoothGattServerCallback() {
    //1、首先是连接状态的回调
    @Override
    public void onConnectionStateChange(BluetoothDevice device, int status, int newState) {
        super.onConnectionStateChange(device, status, newState);
        Log.e(TAG,"连接状态发生改变,安卓系统回调onConnectionStateChange:device name="+device.getName()+"address="+device.getAddress()+"status="+status+"newstate="+newState);
    }

    @Override
    public void onCharacteristicReadRequest(BluetoothDevice device, int requestId, int offset, BluetoothGattCharacteristic characteristic) {
        super.onCharacteristicReadRequest(device, requestId, offset, characteristic);
        Log.e(TAG,"客户端有读的请求,安卓系统回调该onCharacteristicReadRequest()方法");

        mBluetoothGattServer.sendResponse(device,requestId, BluetoothGatt.GATT_SUCCESS,offset,characteristic.getValue());
    }

    //接受具体字节,当有特征被写入时,回调该方法,写入的数据为参数中的value
    @Override
    public void onCharacteristicWriteRequest(BluetoothDevice device, int requestId, BluetoothGattCharacteristic characteristic, boolean preparedWrite, boolean responseNeeded, int offset, byte[] value) {
        super.onCharacteristicWriteRequest(device, requestId, characteristic, preparedWrite, responseNeeded, offset, value);
        Log.e(TAG,"客户端有写的请求,安卓系统回调该onCharacteristicWriteRequest()方法");

        //特征被读取,在该回调方法中回复客户端响应成功
        mBluetoothGattServer.sendResponse(device,requestId,BluetoothGatt.GATT_SUCCESS,offset,value);

        //处理响应内容
        //value:客户端发送过来的数据
        onResponseToClient(value,device,requestId,characteristic);
    }

    //特征被读取。当回复相应成功后,客户端胡读取然后触发本方法
    @Override
    public void onDescriptorReadRequest(BluetoothDevice device, int requestId, int offset, BluetoothGattDescriptor descriptor) {
        super.onDescriptorReadRequest(device, requestId, offset, descriptor);

        mBluetoothGattServer.sendResponse(device,requestId,BluetoothGatt.GATT_SUCCESS,offset,null);
    }

    //2、其次,当有描述请求被写入时,回调该方法,
    @Override
    public void onDescriptorWriteRequest(BluetoothDevice device, int requestId, BluetoothGattDescriptor descriptor, boolean preparedWrite, boolean responseNeeded, int offset, byte[] value) {
        super.onDescriptorWriteRequest(device, requestId, descriptor, preparedWrite, responseNeeded, offset, value);

        mBluetoothGattServer.sendResponse(device,requestId,BluetoothGatt.GATT_SUCCESS,offset,value);
       // onResponseToClient(value,device,requestId,descriptor.getCharacteristic());
    }

    @Override
    public void onServiceAdded(int status,BluetoothGattService service){
        super.onServiceAdded(status,service);
        Log.e(TAG,"添加服务成功,安卓系统回调该onServiceAdded()方法");
    }
};

参考连接
BLE源码

1、蓝牙Bluetooth BR/EDR 和 Bluetooth Smart 必需要知道的十个不同点 
2、BLE简介和Android BLE编程 

3、BLE广播数据解析

4、BLE学习

5 Android Bluetooth api

评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

甜美冰景

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值