参考资料:
Android BLE 蓝牙开发入门 - 简书 // 部分方法过时
android蓝牙BLE(一) —— 扫描 - 简书 //分四部讲解 比较详细 推荐
demo1下载链接:service后台读取数据通知广播更新界面
图:
demo2下载链接:BlueTooth_Test.zip-Android文档类资源-CSDN下载
添加权限
蓝牙扫描需要开启位置权限:
targetSdkVersion 28以前需要动态申请开启模糊定位,targetSdkVersion 大于28需要开启精准定位,否则扫描不到蓝牙设备。
main_layout:
MainActivity:
package youli.com.example.administrator.bluetooth_servise_bread;
import android.Manifest;
import android.app.Activity;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothManager;
import android.bluetooth.le.BluetoothLeScanner;
import android.bluetooth.le.ScanCallback;
import android.bluetooth.le.ScanResult;
import android.content.BroadcastReceiver;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.ServiceConnection;
import android.content.pm.PackageManager;
import android.os.Build;
import android.os.Bundle;
import android.os.Handler;
import android.os.IBinder;
import android.os.Looper;
import android.text.TextUtils;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;
import android.widget.Toast;
import androidx.annotation.Nullable;
import androidx.appcompat.app.AppCompatActivity;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import java.util.ArrayList;
import java.util.List;
public class MainActivity extends AppCompatActivity {
private TextView text_data;
private TextView text_rssi;
private final int REQUEST_ENABLE_BT = 1;
private BleService bleService;
private BluetoothAdapter bluetoothAdapter;
private BluetoothLeScanner bluetoothLeScanner;
private BluetoothManager bluetoothManager; //蓝牙管理类
private List mBluetoothDeviceList;
private List mRssiList;
private RecyclerView mRvDeviceList;
private Button mBtnScan;
private DeviceListAdapter mDeviceListAdapter;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
getLOCATION();
initView();
initBle();
}
private void initView() {
text_data = findViewById(R.id.text_data);
text_rssi = findViewById(R.id.text_rssi);
mRvDeviceList = (RecyclerView) findViewById(R.id.rv_device_list);
mBtnScan = (Button) findViewById(R.id.btn_scan);
mBtnScan.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
scanBleDevice();
}
});
// 蓝牙设备列表
mBluetoothDeviceList = new ArrayList<>();
// 蓝牙设备RSSI列表
mRssiList = new ArrayList<>();
mDeviceListAdapter = new DeviceListAdapter(mBluetoothDeviceList, mRssiList);
mRvDeviceList.setLayoutManager(new LinearLayoutManager(this));
mRvDeviceList.setAdapter(mDeviceListAdapter);
// 连接蓝牙设备
mDeviceListAdapter.setOnItemClickListener(new DeviceListAdapter.OnItemClickListener() {
@Override
public void onItemClick(View view, int position) {
Toast.makeText(MainActivity.this, "开始连接", Toast.LENGTH_SHORT).show();
bluetoothLeScanner.stopScan(scanCallback);
bleService.connect(bluetoothAdapter, mBluetoothDeviceList.get(position).getAddress());
}
});
// 绑定服务
Intent intent = new Intent(MainActivity.this, BleService.class);
bindService(intent, serviceConnection, Context.BIND_AUTO_CREATE);
//注册广播
IntentFilter filter = new IntentFilter();
filter.addAction(BleService.ACTION_GATT_CONNECTED);
filter.addAction(BleService.ACTION_GATT_DISCONNECTED);
filter.addAction(BleService.ACTION_GATT_SERVICES_DISCOVERED);
filter.addAction(BleService.ACTION_DATA_AVAILABLE);
filter.addAction(BleService.ACTION_CONNECTING_FAIL);
filter.addAction(BleService.EXTRA_RSSI_DATA);
BleReceiver bleReceiver = new BleReceiver();
registerReceiver(bleReceiver, filter);
}
/**
* 初始化数据
*/
private void initBle() {
bluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
// bluetoothManager = (BluetoothManager) getSystemService(Context.BLUETOOTH_SERVICE);
// bluetoothAdapter = bluetoothManager.getAdapter();
if (bluetoothAdapter == null) {
Toast.makeText(this, "蓝牙不可用", Toast.LENGTH_LONG).show();
return;
}
if (!bluetoothAdapter.isEnabled()) {
Intent intent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
startActivityForResult(intent, REQUEST_ENABLE_BT);
return;
}
scanBleDevice();
}
/**
* 搜索蓝牙设备
*/
private void scanBleDevice() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR2) {
bluetoothLeScanner = bluetoothAdapter.getBluetoothLeScanner();
bluetoothLeScanner.stopScan(scanCallback);
bluetoothLeScanner.startScan(scanCallback);
new Handler(Looper.getMainLooper()).postDelayed(new Runnable() {
@Override
public void run() {
bluetoothLeScanner.stopScan(scanCallback);
}
}, 10000);
}
}
/**
* 搜索蓝牙设备回调
*/
ScanCallback scanCallback = new ScanCallback() {
@Override//扫描结果
public void onScanResult(int callbackType, ScanResult result) {
super.onScanResult(callbackType, result);
BluetoothDevice bluetoothDevice = result.getDevice();
int rssi = result.getRssi();
if (!TextUtils.isEmpty(bluetoothDevice.getName())) {
if (!mBluetoothDeviceList.contains(bluetoothDevice)) {
mBluetoothDeviceList.add(bluetoothDevice);
mRssiList.add(String.valueOf(rssi));
mDeviceListAdapter.notifyDataSetChanged();
}
}
}
@Override//批量返回扫描结果
public void onBatchScanResults(List results) {
super.onBatchScanResults(results);
}
@Override //扫描失败
public void onScanFailed(int errorCode) {
super.onScanFailed(errorCode);
}
};
ServiceConnection serviceConnection = new ServiceConnection() {
@Override //在线服务连接
public void onServiceConnected(ComponentName name, IBinder service) {
// BleService.LocalBinder localBinder= (BleService.LocalBinder) service;
bleService = ((BleService.LocalBinder) service).getService();
}
@Override//OnService断开连接
public void onServiceDisconnected(ComponentName name) {
bleService = null;
}
};
private List
daqiBluetoothGattCallback:
package youli.com.example.administrator.bluetooth_test;
import android.bluetooth.BluetoothGatt;
import android.bluetooth.BluetoothGattCallback;
import android.bluetooth.BluetoothGattCharacteristic;
import android.bluetooth.BluetoothGattDescriptor;
import android.bluetooth.BluetoothGattService;
import android.bluetooth.BluetoothProfile;
import android.os.Build;
import android.util.Log;
import androidx.annotation.RequiresApi;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;
@RequiresApi(api = Build.VERSION_CODES.JELLY_BEAN_MR2)
public class daqiBluetoothGattCallback extends BluetoothGattCallback {
private BluetoothGatt bluetoothGatt;
private Refresh refresh;
public daqiBluetoothGattCallback(Refresh refresh) {
this.refresh = refresh;
}
interface Refresh {
void OnClick_Connected(); //连接成功回调
void OnClick_Disconnect();//断开连接回调
void OnClick_Riis(int value); //型号强度回调
void OnClick_Refresh(int value); //更新数据回调
}
//定义重连次数
private int reConnectionNum = 0;
//最多重连次数
private int maxConnectionNum = 3;
private List mlist_bleValue = new ArrayList();
/**
* UUID设置不对,不会调用onCharacteristicChanged
*/
//定义需要进行通信的ServiceUUID
private UUID mServiceUUID = UUID.fromString("0000fee0-0000-1000-8000-00805f9b34fb");
//定义需要进行通信的CharacteristicUUID特征标识(读取数据)
private UUID mCharacteristicUUID = UUID.fromString("0000fee1-0000-1000-8000-00805f9b34fb");
//定义需要进行通信的ServiceUUID特征标识(发送数据时用到)
private UUID CHARACTERISTIC_WRITE_UUID = UUID.fromString("0000fee1-0000-1000-8000-00805f9b34fb");
//定义需要进行通信的DescriptorUUID
private UUID mDescriptorUUID = UUID.fromString("00002902-0000-1000-8000-00805f9b34fb");
//64:CF:D9:0A:F7:81
@Override//连接状态回调
public void onConnectionStateChange(BluetoothGatt gatt, int status, int newState) {
if (status == BluetoothGatt.GATT_SUCCESS) { //正在执行连接操作
if (newState == BluetoothProfile.STATE_CONNECTED) { //设备已连接
//连接后的操作 发现蓝牙服务,也就是 Service
Log.i("TAG", "设备已连接");
gatt.discoverServices(); //发现服务成功后,会触发BluetoothGattCallback#onServicesDiscovered()回调
if (refresh != null) {
refresh.OnClick_Connected();
}
} else if (newState == BluetoothProfile.STATE_DISCONNECTED) { //断开连接
Log.i("TAG", "断开连接");
if (refresh != null) {
refresh.OnClick_Disconnect();
}
}
} else {//连接出错 执行重连
/**
* 异常码
* 133 :连接超时或未找到设备。
* 8 : 设备超出范围
* 22 :表示本地设备终止了连接
*/
//重连次数不大于最大重连次数
if (reConnectionNum < maxConnectionNum) {
//重连次数自增
reConnectionNum++;
//重新连接设备
boolean a = gatt.connect();
} else {
//断开连接,返回连接失败回调
Log.i("TAG", "设备重连失败");
}
}
}
@Override //服务发现回调
public void onServicesDiscovered(BluetoothGatt gatt, int status) {
if (status == BluetoothGatt.GATT_SUCCESS) { // 发现蓝牙服务成功
// // 获取UUID
// List gattServicesList = gatt.getServices(); //全部服务
// for (int i = 0; i < gattServicesList.size(); i++) {
// Log.d("TAG1", " 服务 UUID=" + gattServicesList.get(i).getUuid());
// List characteristics = gattServicesList.get(i).getCharacteristics();//全部特征
// for (int j = 0; j < characteristics.size(); j++) {
// Log.d("TAG1", " 特征 UUID=" + characteristics.get(j).getUuid());
//
// List descriptors = characteristics.get(j).getDescriptors();//全部描述符
// for (int a = 0; a < descriptors.size(); a++) {
// Log.d("TAG1", " 描述符 UUID=" + descriptors.get(a).getUuid());
// }
// }
// }
// //上面代码得到的全部uuid 至于用那个需要试过才知道
// 服务 UUID=00001800-0000-1000-8000-00805f9b34fb
// 特征 UUID=00002a00-0000-1000-8000-00805f9b34fb
// 特征 UUID=00002a01-0000-1000-8000-00805f9b34fb
// 特征 UUID=00002a02-0000-1000-8000-00805f9b34fb
// 特征 UUID=00002a03-0000-1000-8000-00805f9b34fb
// 特征 UUID=00002a04-0000-1000-8000-00805f9b34fb
// 服务 UUID=00001801-0000-1000-8000-00805f9b34fb
// 特征 UUID=00002a05-0000-1000-8000-00805f9b34fb
// 描述符 UUID=00002902-0000-1000-8000-00805f9b34fb 使用
// 服务 UUID=0000fee0-0000-1000-8000-00805f9b34fb 使用
// 特征 UUID=0000fee1-0000-1000-8000-00805f9b34fb 使用
// 描述符 UUID=00002902-0000-1000-8000-00805f9b34fb
// 服务 UUID=0000180a-0000-1000-8000-00805f9b34fb
// 特征 UUID=00002a23-0000-1000-8000-00805f9b34fb
// 特征 UUID=00002a24-0000-1000-8000-00805f9b34fb
// 特征 UUID=00002a25-0000-1000-8000-00805f9b34fb
// 特征 UUID=00002a26-0000-1000-8000-00805f9b34fb
// 特征 UUID=00002a27-0000-1000-8000-00805f9b34fb
// 特征 UUID=00002a28-0000-1000-8000-00805f9b34fb
// 特征 UUID=00002a29-0000-1000-8000-00805f9b34fb
// 特征 UUID=00002a2a-0000-1000-8000-00805f9b34fb
// 特征 UUID=00002a50-0000-1000-8000-00805f9b34fb
BluetoothGattService gattServicesList = gatt.getService(mServiceUUID);
if (gattServicesList != null) {
BluetoothGattCharacteristic gattCharacteristic = gattServicesList.getCharacteristic(mCharacteristicUUID);
if (gattCharacteristic != null) {
//获取其对应的通知Descriptor
BluetoothGattDescriptor descriptor = gattCharacteristic.getDescriptor(mDescriptorUUID);
if (descriptor != null) {
//开启 Android 端接收通知的开关,还需要往 Characteristic 的 Descriptor 属性写入开启通知的数据开关使得当硬件的数据改变时,主动往手机发送数据。
descriptor.setValue(BluetoothGattDescriptor.ENABLE_INDICATION_VALUE);//开启 Android 端接收通知
boolean descriptorResult = gatt.writeDescriptor(descriptor);
/**
* readCharacteristic单向通讯
* setCharacteristicNotification双向通讯
*/
// boolean a = gatt.readCharacteristic(gattCharacteristic); //当成功读取特征值时,会触发BluetoothGattCallback#onCharacteristicRead()回调。
boolean b = gatt.setCharacteristicNotification(gattCharacteristic, true);//当成功读取特征值时,会触发BluetoothGattCallback#onCharacteristicRead()回调。
}
}
} else {
Log.e("onServicesDiscovered", "获取服务失败:" + status);
}
}
}
@Override //读取到特征值回调
public void onCharacteristicRead(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic, int status) {
if (status == BluetoothGatt.GATT_SUCCESS) {
byte[] _b = characteristic.getValue();
Log.i("TAG", "6: " + _b);
Log.i("TAG", "7: " + byte2HexStr(_b));
//获取写入到外设的特征值
byte[] value = characteristic.getValue();
String a = byte2HexStr(value);
Log.i("TAG", "5:" + gatt.getDevice().getName() + " 读取成功 " + characteristic.getValue() + ":转换16进制:" + a);
}
}
@Override//特征写入回调
public void onCharacteristicWrite(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic, int status) {
super.onCharacteristicWrite(gatt, characteristic, status);
}
@Override //外设特征值改变回调
public void onCharacteristicChanged(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic) {
byte[] value = characteristic.getValue();
String a = byte2HexStr(value);
Log.i("TAG", a + ":值");
if (value[0] == -86) { //此处-86 打印出-86 转换后得到 AA ,获取到完整数据 AA001FBB,取中间四位 转换16 进制
mlist_bleValue.clear();
for (int i = 0; i < value.length; i++) {
mlist_bleValue.add(value[i]);
}
} else if (value[0] != -86 && mlist_bleValue.size() > 0) {
for (int i = 0; i < value.length; i++) {
mlist_bleValue.add(value[i]);
}
}
if (mlist_bleValue.size() == 4) {
String values = byte2HexStr(mlist_bleValue);
values = values.substring(2, 6);
Integer ble_value = Integer.parseInt(values, 16);
Log.i("TAG", "最终值" + values + ":最终值转换16进制:" + ble_value + "毫米");
if (refresh != null) {
refresh.OnClick_Refresh(ble_value);
}
mlist_bleValue.clear();
//实时显示信号强度
gatt.readRemoteRssi(); //信号强弱回调触发BluetoothGattCallback. onReadRemoteRssi()回调
}
}
@Override //描述写入回调
public void onDescriptorWrite(BluetoothGatt gatt, BluetoothGattDescriptor descriptor, int status) {
super.onDescriptorWrite(gatt, descriptor, status);
}
@Override //设备信号强度回调
public void onReadRemoteRssi(BluetoothGatt gatt, int rssi, int status) {
// Log.i("TAG", "信号强度"+rssi);
if (refresh != null) {
refresh.OnClick_Riis(rssi);
}
}
/**
* 转换成16进制大写字符串
*
* @param b
* @return
*/
public static String byte2HexStr(byte[] b) {
String stmp;
StringBuilder sb = new StringBuilder();
for (int n = 0; n < b.length; n++) {
stmp = Integer.toHexString(b[n] & 0xFF);
sb.append((stmp.length() == 1) ? "0" + stmp : stmp);
}
return sb.toString().toUpperCase().trim();
}
/**
* List集合转换成16进制大写字符串
*
* @param b
* @return
*/
public static String byte2HexStr(List b) {
String stmp = "";
StringBuilder sb = new StringBuilder();
for (int n = 0; n < b.size(); n++) {
byte bb = (byte) b.get(n);
stmp = Integer.toHexString(bb & 0xFF);
sb.append((stmp.length() == 1) ? "0" + stmp : stmp);
}
return sb.toString().toUpperCase().trim();
}
}
继承
extends BluetoothGattCallback:
BluetoothGattCallback是连接后进行的一系列操作的回调,例如连接和断开连接的回调,发现服务的回调,成功写入数据,成功读取数据,信号值的回调等等。
注释都比较详细