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

2024-09-07 16:48

本文主要是介绍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

这篇关于Anroid BLE蓝牙(手机分别作为中心设备和外围设备)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1145599

相关文章

跨国公司撤出在华研发中心的启示:中国IT产业的挑战与机遇

近日,IBM中国宣布撤出在华的两大研发中心,这一决定在IT行业引发了广泛的讨论和关注。跨国公司在华研发中心的撤出,不仅对众多IT从业者的职业发展带来了直接的冲击,也引发了人们对全球化背景下中国IT产业竞争力和未来发展方向的深思。面对这一突如其来的变化,我们应如何看待跨国公司的决策?中国IT人才又该如何应对?中国IT产业将何去何从?本文将围绕这些问题展开探讨。 跨国公司撤出的背景与

如何编写Linux PCIe设备驱动器 之二

如何编写Linux PCIe设备驱动器 之二 功能(capability)集功能(capability)APIs通过pci_bus_read_config完成功能存取功能APIs参数pos常量值PCI功能结构 PCI功能IDMSI功能电源功率管理功能 功能(capability)集 功能(capability)APIs int pcie_capability_read_wo

cell phone teardown 手机拆卸

tweezer 镊子 screwdriver 螺丝刀 opening tool 开口工具 repair 修理 battery 电池 rear panel 后盖 front and rear cameras 前后摄像头 volume button board 音量键线路板 headphone jack 耳机孔 a cracked screen 破裂屏 otherwise non-functiona

开放式耳机好用?平价开放式耳机推荐?四款开放式的蓝牙耳机推荐

开放式耳机好用吗?有平价些的开放式耳机推荐吗?那这两个问题的回答当然是肯定的。 首先开放式耳机好不好用取决于对耳机的需求,因为开放式耳机其实是比较适用于需要注意周围环境、需要‌长时间佩戴舒适以及需要频繁与人交流的场景中,在这些场景下使用开放式耳机的话就会比较有优势。就例如跑步骑行健身等运动的时候,能够兼得佩戴舒适度的同时,增加一定的安全性;还有在办公学习的时候,会很适合长时间佩戴,能够方便和

文章解读与仿真程序复现思路——电力自动化设备EI\CSCD\北大核心《考虑燃料电池和电解槽虚拟惯量支撑的电力系统优化调度方法》

本专栏栏目提供文章与程序复现思路,具体已有的论文与论文源程序可翻阅本博主免费的专栏栏目《论文与完整程序》 论文与完整源程序_电网论文源程序的博客-CSDN博客https://blog.csdn.net/liang674027206/category_12531414.html 电网论文源程序-CSDN博客电网论文源程序擅长文章解读,论文与完整源程序,等方面的知识,电网论文源程序关注python

全英文地图/天地图和谷歌瓦片地图杂交/设备分布和轨迹回放/无需翻墙离线使用

一、前言说明 随着风云局势的剧烈变化,对我们搞软件开发的人员来说,影响也是越发明显,比如之前对美对欧的软件居多,现在慢慢的变成了对大鹅和中东以及非洲的居多,这两年明显问有没有俄语或者阿拉伯语的输入法的增多,这要是放在2019年以前,一年也遇不到一个人问这种需求场景的。 地图应用这块也是,之前的应用主要在国内,现在慢慢的多了一些外国的应用场景,这就遇到一个大问题,我们平时主要开发用的都是国内的地

驱动(RK3588S)第七课时:单节点设备树

目录 需求一、设备树的概念1、设备树的后缀名:2、设备树的语法格式3、设备树的属性(重要)4、设备树格式举例 二、设备树所用函数1、如何在内核层种获取设备树节点:2、从设备树上获取 gpio 口的属性3、获取节点上的属性只针对于字符串属性的4、函数读取 np 结点中的 propname 属性的值,并将读取到的 u32 类型的值保存在 out_value 指向的内存中,函数的返回值表示读取到的

想要从OPPO手机恢复数据?免费OPPO照片视频恢复软件

此实用程序可帮助那些寻找以下内容的用户: 在OPPO手机中格式化存储卡后可以恢复图片吗?我删除了 OPPO上的视频和图片,我感觉很糟糕,因为里面有我在拉斯维加斯拍摄的视频和照片 免费OPPO照片视频恢复软件 您能恢复OPPO上已删除的照片吗?我不小心格式化了OPPO SD 卡,有希望恢复已删除的照片吗? 救命!我在清理时删除了我的照片,我的问题是是否有任何免费软件可以从OPPO中恢复已

模具要不要建设3D打印中心

随着3D打印技术的日益成熟与广泛应用,模具企业迎来了自建3D打印中心的热潮。这一举措不仅为企业带来了前所未有的发展机遇,同时也伴随着一系列需要克服的挑战,如何看待企业引进增材制造,小编为您全面分析。 机遇篇: 加速产品创新:3D打印技术如同一把钥匙,为模具企业解锁了快速迭代产品设计的可能。企业能够迅速将创意转化为实体模型,缩短产品从设计到市场的周期,抢占市场先机。 强化定制化服务:面

自定义view中常用到哪些方法作用分别是什么

目录 构造函数onMeasure(int widthMeasureSpec, int heightMeasureSpec)onDraw(Canvas canvas)onLayout(boolean changed, int left, int top, int right, int bottom)onTouchEvent(MotionEvent event)onSizeChanged(int