Android BLE 蓝牙编程(三)

上节咱们已经能够链接上蓝牙设备了。java

本节咱们就要获取手环的电池电量和计步啦。android

在介绍这个以前咱们须要先了解下什么是 服务 什么是 UUID编程

咱们记得上节中咱们item监听事件的回调的返回值是BluetoothGatt 类型的,还记得么?嘿嘿。数组

返回的bluetoothgatt中包含一个或多个BluetoothGattService(服务)app

每一个service包含一个或多个characteristic(特征值)异步

每一个特征值包含一个value 和多个 descriptor(注意看啊!是一个value)ide

这些对于本项目来讲某个特征值的value中就包含了记录的步数。(很遗憾我折腾了好久也没找到电池电量,不得不舍弃展现电池电量的想法)ui

先熟悉下下面的图片吧~~this

百度脑图spa

在了解下UUID 上图中每一个蓝牙设备都有本身的MAC 地址有了这个地址 咱们就能够链接这个设备。

链接上设备后会的到设备的服务就是上图中的Gattservice 这每一个service都有个固定的UUID以标识区分

每一个service又包含多个的characteristic 这些特征值也有惟一的UUID 这些UUID就是咱们编程须要的,

获取到characteristic对应的UUID就意味着获取到该characteristic提供的功能或者数据。

特征值对应的UUID所实现的功能是由硬件工程师决定的。

由于小米手环的硬件工程师咱们没有联系方式,何况人家也确定不会告诉我全部功能对应的UUID

所以咱们只好本身对应数值来找了。

 

简单说 上图的每一个characteristic 都对应一个UUID 这些UUID对应了设备的不一样功能

手环为例:

控制手环震动的 UUID :00002a06-0000-1000-8000-00805f9b34fb   手机向该 UUID 写入 0x01 或者 0x02 时手环都会震动,01强度弱于 02

计步的     UUID :0000ff06-0000-1000-8000-00805f9b34fb     读取该UUID下的value数组 第0 个数据就是 步数

 

首先咱们来获取下计步数吧

 通过一番折腾我终于找到了小米手环对应步数的 UUID :0000ff06-0000-1000-8000-00805f9b34fb

gattcallback 回调方法中找到 onServicesDiscovered

添加以下代码:

 @Override public void onServicesDiscovered(BluetoothGatt gatt, int status) { super.onServicesDiscovered(gatt, status); //寻找到服务时
            if (status == bluetoothGatt.GATT_SUCCESS) { final List<BluetoothGattService> services = bluetoothGatt.getServices(); runOnUiThread(new Runnable() { @Override public void run() { //List<String> serlist = new ArrayList<>();
                        for (final BluetoothGattService bluetoothGattService : services) { bluetoothGattServices = bluetoothGattService; Log.i(TAG, "onServicesDiscovered: " + bluetoothGattService.getUuid()); List<BluetoothGattCharacteristic> charc = bluetoothGattService.getCharacteristics(); for (BluetoothGattCharacteristic charac : charc) { Log.i(TAG, "run: " + charac.getUuid()); //找到透传特征值 // 00002a06-0000-1000-8000-00805f9b34fb 小米手环震动特征值 0x01震动 0x02强震
                                if (charac.getUuid().toString().equals("00002a06-0000-1000-8000-00805f9b34fb")) { //设备 震动特征值
                                    characteristic_zd = charac; } else if (charac.getUuid().toString().equals("0000ff06-0000-1000-8000-00805f9b34fb")) { //设备 步数
                                    characteristic_jb = charac; bluetoothGatt.readCharacteristic(characteristic_jb); Log.i(TAG, "run: 正在尝试读取步数"); } else if (charac.getUuid().toString().equals("")) { //设备 电量特征值
 } } serviceslist.add(bluetoothGattService.getUuid().toString()); } } }); } }

注释写的很清楚

我用 characteristic_zd 记住震动的特征值

 用 characteristic_jb  记住计步的

记住计步特征值后使用 bluetoothGatt 提供的read方法并传人相应特征值。该方法为异步方法他的返回内容会由

回调中的 onCharacteristicRead 方法接收到

找到该方法添加以下代码:

if (status == bluetoothGatt.GATT_SUCCESS) { final int sum = characteristic.getValue()[0]; runOnUiThread(new Runnable() { @Override public void run() { jibu.setText("走了" + sum + "步"); } }); Log.e(TAG, "onCharacteristicRead: " + characteristic.getValue()[0]); }

方法的参数中status表示状态,为 bluetoothGatt.GATT_SUCCESS 时表示成功获取返回

由于在异步方法中,想要操做UI线程,因而就用了 runOnUiThread 方法。显示出来步数便可。

好了下面贴出完整主Activity代码:

MainActivity.java:

package com.wbnq.shouhuan; import android.bluetooth.BluetoothAdapter; import android.bluetooth.BluetoothDevice; import android.bluetooth.BluetoothGatt; import android.bluetooth.BluetoothGattCallback; import android.bluetooth.BluetoothGattCharacteristic; import android.bluetooth.BluetoothGattDescriptor; import android.bluetooth.BluetoothGattService; import android.bluetooth.BluetoothManager; import android.content.Intent; import android.support.v7.app.AppCompatActivity; import android.os.Bundle; import android.util.Log; import android.view.View; import android.widget.AdapterView; import android.widget.ArrayAdapter; import android.widget.Button; import android.widget.ListView; import android.widget.TextView; import android.widget.Toast; import java.util.ArrayList; import java.util.List; import java.util.UUID; public class MainActivity extends AppCompatActivity implements View.OnClickListener { private Button saomiao, duanzhen, changzhen, buting, tingxia; private TextView jibu, dianliang, lianjiezhuangtai; private ListView list; public static String TAG = "shouhuan-MainActivity"; BluetoothAdapter bluetoothAdapter; BluetoothGatt bluetoothGatt; List<BluetoothDevice> deviceList = new ArrayList<>(); List<String> serviceslist = new ArrayList<String>(); BluetoothDevice bluetoothDevice; BluetoothGattService bluetoothGattServices; BluetoothGattCharacteristic characteristic_zd, characteristic_jb; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); initView(); //蓝牙管理,这是系统服务能够经过getSystemService(BLUETOOTH_SERVICE)的方法获取实例
        BluetoothManager bluetoothManager = (BluetoothManager) getSystemService(BLUETOOTH_SERVICE); //经过蓝牙管理实例获取适配器,而后经过扫描方法(scan)获取设备(device)
        bluetoothAdapter = bluetoothManager.getAdapter(); } private void initView() { saomiao = (Button) findViewById(R.id.saomiao); duanzhen = (Button) findViewById(R.id.zhendong); changzhen = (Button) findViewById(R.id.changzhen); buting = (Button) findViewById(R.id.buting); tingxia = (Button) findViewById(R.id.tingxia); list = (ListView) findViewById(R.id.list); jibu = (TextView) findViewById(R.id.jibu); dianliang = (TextView) findViewById(R.id.dianliang); lianjiezhuangtai = (TextView) findViewById(R.id.lianjiezhuangtai); saomiao.setOnClickListener(this); duanzhen.setOnClickListener(this); changzhen.setOnClickListener(this); buting.setOnClickListener(this); tingxia.setOnClickListener(this); //item 监听事件
        list.setOnItemClickListener(new AdapterView.OnItemClickListener() { @Override public void onItemClick(AdapterView<?> adapterView, View view, int i, long l) { bluetoothDevice = deviceList.get(i); //链接设备的方法,返回值为bluetoothgatt类型
                bluetoothGatt = bluetoothDevice.connectGatt(MainActivity.this, false, gattcallback); lianjiezhuangtai.setText("链接" + bluetoothDevice.getName() + "中..."); } }); } @Override public void onClick(View view) { switch (view.getId()) { case R.id.saomiao: //开始扫描前开启蓝牙
                Intent turn_on = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE); startActivityForResult(turn_on, 0); Toast.makeText(MainActivity.this, "蓝牙已经开启", Toast.LENGTH_SHORT).show(); Thread scanThread = new Thread(new Runnable() { @Override public void run() { Log.i("TAG", "run: saomiao ..."); saomiao(); } }); scanThread.start(); lianjiezhuangtai.setText("正在扫描"); break; case R.id.zhendong: break; case R.id.changzhen: break; case R.id.buting: break; case R.id.tingxia: break; case R.id.list: break; } } public void saomiao() { deviceList.clear(); bluetoothAdapter.startLeScan(callback); } //扫描回调
    public BluetoothAdapter.LeScanCallback callback = new BluetoothAdapter.LeScanCallback() { @Override public void onLeScan(final BluetoothDevice bluetoothDevice, int i, byte[] bytes) { Log.i("TAG", "onLeScan: " + bluetoothDevice.getName() + "/t" + bluetoothDevice.getAddress() + "/t" + bluetoothDevice.getBondState()); //重复过滤方法,列表中包含不应设备才加入列表中,并刷新列表
            if (!deviceList.contains(bluetoothDevice)) { //将设备加入列表数据中
 deviceList.add(bluetoothDevice); list.setAdapter(new MyAdapter(MainActivity.this, deviceList)); } } }; private BluetoothGattCallback gattcallback = new BluetoothGattCallback() { @Override public void onConnectionStateChange(BluetoothGatt gatt, int status, final int newState) { super.onConnectionStateChange(gatt, status, newState); runOnUiThread(new Runnable() { @Override public void run() { String status; switch (newState) { //已经链接
                        case BluetoothGatt.STATE_CONNECTED: lianjiezhuangtai.setText("已链接"); bluetoothAdapter.stopLeScan(callback); //该方法用于获取设备的服务,寻找服务
 bluetoothGatt.discoverServices(); break; //正在链接
                        case BluetoothGatt.STATE_CONNECTING: lianjiezhuangtai.setText("正在链接"); break; //链接断开
                        case BluetoothGatt.STATE_DISCONNECTED: lianjiezhuangtai.setText("已断开"); break; //正在断开
                        case BluetoothGatt.STATE_DISCONNECTING: lianjiezhuangtai.setText("断开中"); break; } //pd.dismiss();
 } }); } @Override public void onServicesDiscovered(BluetoothGatt gatt, int status) { super.onServicesDiscovered(gatt, status); //寻找到服务时
            if (status == bluetoothGatt.GATT_SUCCESS) { final List<BluetoothGattService> services = bluetoothGatt.getServices(); runOnUiThread(new Runnable() { @Override public void run() { //List<String> serlist = new ArrayList<>();
                        for (final BluetoothGattService bluetoothGattService : services) { bluetoothGattServices = bluetoothGattService; Log.i(TAG, "onServicesDiscovered: " + bluetoothGattService.getUuid()); List<BluetoothGattCharacteristic> charc = bluetoothGattService.getCharacteristics(); for (BluetoothGattCharacteristic charac : charc) { Log.i(TAG, "run: " + charac.getUuid()); //找到透传特征值 // 00002a06-0000-1000-8000-00805f9b34fb 小米手环震动特征值 0x01震动 0x02强震
                                if (charac.getUuid().toString().equals("00002a06-0000-1000-8000-00805f9b34fb")) { //设备 震动特征值
                                    characteristic_zd = charac; } else if (charac.getUuid().toString().equals("0000ff06-0000-1000-8000-00805f9b34fb")) { //设备 步数
                                    characteristic_jb = charac; bluetoothGatt.readCharacteristic(characteristic_jb); Log.i(TAG, "run: 正在尝试读取步数"); } else if (charac.getUuid().toString().equals("")) { //设备 电量特征值
 } } serviceslist.add(bluetoothGattService.getUuid().toString()); } // ArrayAdapter<String> adapter = new ArrayAdapter<String>( // MainActivity.this, android.R.layout.simple_expandable_list_item_1, serviceslist); //list.setAdapter(adapter);
 } }); } } @Override public void onCharacteristicRead(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic, int status) { super.onCharacteristicRead(gatt, characteristic, status); if (status == bluetoothGatt.GATT_SUCCESS) { final int sum = characteristic.getValue()[0]; runOnUiThread(new Runnable() { @Override public void run() { jibu.setText("走了" + sum + "步"); } }); Log.e(TAG, "onCharacteristicRead: " + characteristic.getValue()[0]); } } @Override public void onCharacteristicWrite(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic, int status) { super.onCharacteristicWrite(gatt, characteristic, status); } //获取返回 数据
 @Override public void onCharacteristicChanged(BluetoothGatt gatt, final BluetoothGattCharacteristic characteristic) { super.onCharacteristicChanged(gatt, characteristic); Log.i(TAG, "onCharacteristicChanged: 获取回调方法"); Log.e("", "命令:" + HexUtil.encodeHexStr(characteristic.getValue())); final byte[] values = characteristic.getValue(); runOnUiThread(new Runnable() { @Override public void run() { Toast.makeText(MainActivity.this, HexUtil.encodeHexStr(values), Toast.LENGTH_SHORT).show(); } }); } }; private boolean enableNotification(boolean enable, BluetoothGattCharacteristic characteristic) { if (bluetoothGatt == null || characteristic == null) return false; if (!bluetoothGatt.setCharacteristicNotification(characteristic, enable)) return false; BluetoothGattDescriptor clientConfig = characteristic.getDescriptor(UUID.fromString("00002902-0000-1000-8000-00805f9b34fb")); if (clientConfig == null) return false; if (enable) { clientConfig.setValue(BluetoothGattDescriptor.ENABLE_NOTIFICATION_VALUE); } else { clientConfig.setValue(BluetoothGattDescriptor.DISABLE_NOTIFICATION_VALUE); } return bluetoothGatt.writeDescriptor(clientConfig); } }
View Code

今天就写这些,下次要实现震动方法咯!是否是很激动呢~~

嘿嘿嘿~

你们加油啦~~

相关文章
相关标签/搜索