本文是关于Android的BLE蓝牙连接以及 获取蓝牙RSSI的基本实现 , 基于SDK中的Sample略作修改
效果图
关于RSSI
-
什么是RSSI
Received Signal Strength Indicator , 接收的信号强度指示 , 单位是dbm , 无线发送层的可选部分 , 用来判定链接质量,以及是否增大广播发送强度。它的实现是在反向通道基带接收滤波器之后进行的。百度百科
-
关于接收率
一般为负值,反映的是信号的衰减程度,理想状态下(无衰减)Rssi值为0dBm,实际情况是,即使蓝牙设备挨得非常近,Rssi也只有-50dBm的强度,在传输过程中,不可避免要损耗。
一般情况下,经典蓝牙强度
信号强 0dBm ~ -50dBm
信号中 -50dBm ~ -70dBm
信号弱 -70dBm ~ dBm低功耗蓝牙分四级
4 0 ~ -60
3 -60 ~ -70
2 -70 ~ -80
1 -80 ~ -
Android中BLE蓝牙获取RSSI
Android平台中,通过蓝牙设备扫描回调和蓝牙设备连接监听两种方式可以获取到每个蓝牙设备的RSSI。
-
测距理论
通过接收到的信号强弱测定信号点与接收点的距离,进而根据相应数据进行定位计算的一种定位技术。
获取蓝牙RSSI
-
蓝牙权限
<uses-feature android:name="android.hardware.bluetooth_le" android:required="true"/> <uses-permission android:name="android.permission.BLUETOOTH"/> <uses-permission android:name="android.permission.BLUETOOTH_ADMIN"/>
-
检查是否支持BLE和蓝牙
// Use this check to determine whether BLE is supported on the device. Then you can // selectively disable BLE-related features. if (!getPackageManager().hasSystemFeature(PackageManager.FEATURE_BLUETOOTH_LE)) { Toast.makeText(this, R.string.ble_not_supported, Toast.LENGTH_SHORT).show(); finish(); } // Initializes a Bluetooth adapter. For API level 18 and above, get a reference to // BluetoothAdapter through BluetoothManager. final BluetoothManager bluetoothManager = (BluetoothManager) getSystemService(Context.BLUETOOTH_SERVICE); mBluetoothAdapter = bluetoothManager.getAdapter(); // Checks if Bluetooth is supported on the device. if (mBluetoothAdapter == null) { Toast.makeText(this, R.string.error_bluetooth_not_supported, Toast.LENGTH_SHORT).show(); finish(); return; }
-
获取RSSI方法一: 蓝牙设备扫描回调
/** * 扫描蓝牙设备 * @param enable 开始/停止扫描 */ private void scanLeDevice(final boolean enable) { if (enable) { // Stops scanning after a pre-defined scan period. mHandler.postDelayed(() -> { mScanning = false; mBluetoothAdapter.stopLeScan(mLeScanCallback); invalidateOptionsMenu(); }, SCAN_PERIOD); mScanning = true; mBluetoothAdapter.startLeScan(mLeScanCallback); } else { mScanning = false; mBluetoothAdapter.stopLeScan(mLeScanCallback); } }
// 设备扫描回调 private BluetoothAdapter.LeScanCallback mLeScanCallback = (device, rssi, scanRecord) -> { Log.i(TAG, "rssi: " + rssi); };
-
获取RSSI方法二: 连接蓝牙设备后读取
- 先通过方法一的扫描设备拿到DeviceAddress
- 在服务中注册监听
- 通过绑定服务(BindService)管理生命周期
- 连接蓝牙设备
- 循环读取Rssi
//Service中注册监听 // Implements callback methods for GATT events that the app cares about. For example, // connection change and services discovered. private final BluetoothGattCallback mGattCallback = new BluetoothGattCallback() { @Override public void onConnectionStateChange(BluetoothGatt gatt, int status, int newState) { String intentAction; if (newState == BluetoothProfile.STATE_CONNECTED) { ``` } else if (newState == BluetoothProfile.STATE_DISCONNECTED) { ``` } } @Override public void onServicesDiscovered(BluetoothGatt gatt, int status) { if (status == BluetoothGatt.GATT_SUCCESS) { broadcastUpdate(ACTION_GATT_SERVICES_DISCOVERED); } else { Log.w(TAG, "onServicesDiscovered received: " + status); } } @Override public void onReadRemoteRssi(BluetoothGatt gatt, int rssi, int status) { Log.i(TAG, "gatt: " + gatt.toString() + ", rssi: " + rssi + ", status: " + status); super.onReadRemoteRssi(gatt, rssi, status); if (status == BluetoothGatt.GATT_SUCCESS) { final Intent intent = new Intent(ACTION_READ_RSSI); intent.putExtra(EXTRA_DATA, String.valueOf(rssi)); sendBroadcast(intent); } } };
//绑定Service Intent gattServiceIntent = new Intent(this, BluetoothLeService.class); bindService(gattServiceIntent, mServiceConnection, BIND_AUTO_CREATE); // Code to manage Service lifecycle. private final ServiceConnection mServiceConnection = new ServiceConnection() { @Override public void onServiceConnected(ComponentName componentName, IBinder service) { mBluetoothLeService = ((BluetoothLeService.LocalBinder) service).getService(); if (!mBluetoothLeService.initialize()) { Log.e(TAG, "Unable to initialize Bluetooth"); finish(); } mBluetoothLeService.connect(mDeviceAddress); } @Override public void onServiceDisconnected(ComponentName componentName) { mBluetoothLeService = null; } };
private boolean isReadRssi = true; private Thread readRSSI; /** * 读取蓝牙RSSi线程 */ private void startReadRssi() { isReadRssi = true; int Rssi=0; readRSSI = (Thread)run() -> { while (isReadRssi){ try { sleep(200); } catch (InterruptedException e) { e.printStackTrace(); } //如果读取蓝牙RSSi回调成功 if(mBluetoothLeService != null && mBluetoothLeService.getRssiVal()){ //获取已经读到的RSSI值 // Rssi=BluetoothLeService.getBLERSSI(); // mHandler.obtainMessage(READRSSI, Rssi).sendToTarget(); } } }; readRSSI.start(); } //停止读取 private void stopReadRssi() { if (readRSSI != null) { isReadRssi = false; readRSSI = null; } }
源码地址
项目源码, 新增了距离计算
https://github.com/ElvisGuozs/BluetoothLeGatt