关于蓝牙ble开发相关知识

蓝牙的基础知识

1. 相关权限申请

权限

android:name="android.permission.BLUETOOTH"/>

android:name="android.permission.BLUETOOTH_ADMIN"/>

注意:android6.0后 需要再添加如下权限定位权限 (如下一个就可以了 也可以多个申请)

android:name="android.permission.ACCESS_COARSE_LOCATION"/>

android:name="android.permission.ACCESS_FINE_LOCATION"/>

2. 搜索蓝牙流程

2.1 打开蓝牙(需要在此之前获取蓝牙适配器BluetoothAdapter 才可以 调起打开蓝牙)

 2.1.1 获取蓝牙适配器BluetoothAdapter

BluetoothManager bluetoothManager =

(BluetoothManager) getSystemService(Context.BLUETOOTH_SERVICE);

mBluetoothAdapter = bluetoothManager.getAdapter();

  2.1.2 权限申请成功后 就可以 打开蓝牙 ,如下是蓝牙是

if(mBluetoothAdapter ==null|| !mBluetoothAdapter.isEnabled()) {

Intent enableBtIntent =newIntent(BluetoothAdapter.ACTION_REQUEST_ENABLE);

startActivityForResult(enableBtIntent,REQUEST_ENABLE_BT);

}

2.2 扫描蓝牙设备

mBluetoothAdapter.startLeScan(mLeScanCallback)

需要注意:搜索是一个不间断的搜索过程,需要我们手动 停止搜索

所以需要 调用mBluetoothAdapter. mBluetoothAdapter.stopLeScan(mLeScanCallback);

具体代码 定时搜索 如下

private voidscanLeDevice(final booleanenable) {

if(enable) {

// Stops scanning after a pre-defined scan period.

mHandler.postDelayed(newRunnable() {

@Override

public voidrun() {

mScanning =false;

mBluetoothAdapter.stopLeScan(mLeScanCallback);

}

},SCAN_PERIOD);

mScanning =true;

mBluetoothAdapter.startLeScan(mLeScanCallback);

}else{

mScanning =false;

mBluetoothAdapter.stopLeScan(mLeScanCallback);

}

关于mLeScanCallback的具体实现

privateBluetoothAdapter.LeScanCallback mLeScanCallback =

newBluetoothAdapter.LeScanCallback() {

@Override

public voidonLeScan(finalBluetoothDevice device, intrssi,

byte[] scanRecord) {

//搜索到蓝牙 将会在该方法回调 , device就是搜索到的蓝牙

}

};

注意:蓝牙搜索过程 是没有帮我们过来重复搜索到蓝牙 ,如果想要把搜索结果放在集合返回,有可能一个设备会重复给搜索到,这个时候需要自己做个过滤,可通过bleDevice 的mac 地址不同进行过滤

2. 连接蓝牙流程

2.1 先理清 将会常操作的几个 类的概念 如下是它们的关系流程图

BluetoothGatt:手机与BLE终端设备建立通信的一个管道,只有有了这个管道,之后的所有读写通知操作都是通过这个来操作

BluetoothGattService:蓝牙设备的服务,每个BluetoothGatt有多个BluetoothGattService,在这里我们把BluetoothGattService比喻成班级。而Bluetoothdevice我们把它比喻成学校,一个学校里面可以有很多班级,也就是说我们每台BLE终端设备拥有多个服务,班级(各个服务)之间通过UUID(唯一标识符)区别

BluetoothGattCharacteristic:蓝牙所拥有的特征 。每个BluetoothGattService有多个BluetoothGattCharacteristic。它是手机与BLE终端设备交换数据的关键,我们做的所有事情,目的就是为了得到它。在这里我们把它比喻成学生,一个班级里面有很多个学生,也就是说我们每个服务下拥有多个特征,学生(各个特征)之间通过UUID(唯一标识符)区别。

理清了我们开始连接蓝牙

2.2连接蓝牙

搜索到蓝牙后 拿到蓝牙对象 BluetoothDevice device 调用如下方法

参数:第一个参数是上下文对象,第二个参数是是否自动连接,这里设置为false,第三个参数就是上面的回调方法

mBluetoothGatt = device.connectGatt(this, false,mGattCallback);

mGattCallback的具体实现

privateBluetoothGattCallbackmGattCallback=newBluetoothGattCallback() {

//连接状态改变的回调

@Override

public voidonConnectionStateChange(BluetoothGatt gatt, intstatus,

intnewState) {

if(newState == BluetoothProfile.STATE_CONNECTED) {

// 连接成功后 必须启调用 服务发现 (discoverServices)

//调用后 当回调 onServicesDiscovered(BluetoothGatt gatt, int status)方法

//才属于真正的成功连接

mBluetoothGatt.discoverServices();

}

}

//发现服务的回调

public voidonServicesDiscovered(BluetoothGatt gatt, intstatus) {

if(status == BluetoothGatt.GATT_SUCCESS) {

Log.e(TAG,"成功发现服务");

}else{

Log.e(TAG,"服务发现失败,错误码为:"+ status);

}

if(status == BluetoothGatt.GATT_SUCCESS) {

if(mBluetoothGatt !=null&& isServiceConnected) {

BluetoothGattService gattService = mBluetoothGatt.getService(UUID_SERVICE);

BluetoothGattCharacteristic characteristic = gattService.getCharacteristic(UUID_NOTIFICATION);

booleanb = mBluetoothGatt.setCharacteristicNotification(characteristic, true);

if(b) {

List descriptors = characteristic.getDescriptors();

for(BluetoothGattDescriptor descriptor : descriptors) {

booleanb1 = descriptor.setValue(BluetoothGattDescriptor.ENABLE_INDICATION_VALUE);

if(b1) {

mBluetoothGatt.writeDescriptor(descriptor);

Log.d(TAG,"startRead: "+"监听收数据");

}

}

}

}

}

//写操作的回调

public voidonCharacteristicWrite (BluetoothGatt gatt,BluetoothGattCharacteristic

characteristic,intstatus){

if(status == BluetoothGatt.GATT_SUCCESS) {

Log.e(TAG,"写入成功"+ characteristic.getValue());

}

}

//读操作的回调

public voidonCharacteristicRead (BluetoothGatt gatt,BluetoothGattCharacteristic

characteristic,intstatus){

if(status == BluetoothGatt.GATT_SUCCESS) {

Log.e(TAG,"读取成功"+ characteristic.getValue());

}

}

//数据返回的回调(此处接收BLE设备返回数据)

public voidonCharacteristicChanged (BluetoothGatt gatt,BluetoothGattCharacteristic

characteristic){

}

}

}

当 回调  onServicesDiscovered(BluetoothGatt gatt, int status) 方法 后  就可以拿着    gatt(上文有解释概念) 进行 读写通知 操作了

3 关于 读,写,通知,操作

 写数据

public void startSend(View view) {

if (mBluetoothGatt != null && isServiceConnected) {

BluetoothGattService gattService = mBluetoothGatt.getService(UUID_SERVICE);

BluetoothGattCharacteristic characteristic = gattService.getCharacteristic(UUID_WRITE);

byte[] bytes = new byte[2];

bytes[0] = 04;

bytes[1] = 01;

characteristic.setValue(bytes);

characteristic.setWriteType(BluetoothGattCharacteristic.WRITE_TYPE_NO_RESPONSE);

mBluetoothGatt.writeCharacteristic(characteristic);

}}

写入成功会回调

public void onCharacteristicWrite(BluetoothGatt gatt,BluetoothGattCharacteristic characteristic, int status) {

if (status == BluetoothGatt.GATT_SUCCESS) {

Log.e(TAG, "写入成功" +characteristic.getValue());

}

}

读数据

public void startSend(View view) {

if (mBluetoothGatt != null && isServiceConnected) {

BluetoothGattService gattService = mBluetoothGatt.getService(UUID_SERVICE);

BluetoothGattCharacteristic characteristic = gattService.getCharacteristic(UUID_WRITE);

byte[] bytes = new byte[2];

bytes[0] = 04;

bytes[1] = 01;

characteristic.setValue(bytes);

mBluetoothGatt.readCharacteristic(characteristic);

}

}

读取成功会回调

//读操作的回调

public voidonCharacteristicRead(BluetoothGatt gatt,BluetoothGattCharacteristic characteristic, intstatus) {

if(status == BluetoothGatt.GATT_SUCCESS) {

Log.e(TAG,"读取成功"+characteristic.getValue());

}

}

注意: 在 读写操作过程  不可以 用for 一次性进行操作  会出现阻塞  需要 将读写操作 写入 队列中  一个一个写入  才是比较好的操作  也不会出现堵塞问题

  蓝牙的操作流程  就此结束    在此基础上  可以再次封装一层  代码就不出来了,一下是流程图



©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 216,324评论 6 498
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,356评论 3 392
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 162,328评论 0 353
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,147评论 1 292
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,160评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,115评论 1 296
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,025评论 3 417
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,867评论 0 274
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,307评论 1 310
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,528评论 2 332
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,688评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,409评论 5 343
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,001评论 3 325
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,657评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,811评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,685评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,573评论 2 353

推荐阅读更多精彩内容