Anroid 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

  • 3
    点赞
  • 20
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 6
    评论
Android BLE 蓝牙是指 Android 平台上的低功耗蓝牙功能,可以在很小的能量消耗下进行短距离数据通信。BLE 蓝牙被广泛应用于智能家居、穿戴设备、健康设备、智能手环等领域。 BLE 蓝牙主要分为两种角色——中央设备外围设备。中央设备扫描周围的外围设备,并建立连接,然后从外围设备接收数据或向其发送数据。外围设备等待中央设备的连接请求,并在连接建立后向中央设备发送数据。BLE 蓝牙连接包括广告、扫描和连接三个阶段。 在连接过程中,BLE 蓝牙主要使用 GATT(通用属性配置文件)协议进行数据传输。GATT 是一个规则集,定义了通信所使用的所有服务和特征(属性)。属性是几乎所有 GATT 的构建块,它定义了服务和信息在设备之间交换的方式。 通过在 Android 平台上使用 BLE 蓝牙,我们还可以开发许多有用的应用程序。例如,我们可以使用 BLE 蓝牙实现室内定位、人员追踪和信标扫描等操作。我们还可以开发一些可穿戴设备,例如智能手环和智能手表,用于监测身体健康状况,如心率、血压等数据。 总之,BLE 蓝牙是非常有用和重要的技术,通过它我们可以轻松地连接和通信数据。Android BLE 提供了强大的开发工具包,可以用于开发各种有用的应用程序和服务。如果您是一名开发人员或热爱科技的用户,那么学习 BLE 蓝牙将会是您的不二之选!
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

甜美冰景

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

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

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

打赏作者

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

抵扣说明:

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

余额充值