Android BLE Scan

Creative Commons
本作品采用知识共享署名

本文简要介绍如何在Android中进行BLE device的Scan,实验平台Android 7, 编译SDK 28(android 9).

增加权限

manifest 修改

在AndroidManifest.xml中增加

1
2
3
4
5
<uses-feature android:name="android.bluetooth.le" android:required="true"/>
<uses-permission android:name="android.permission.BLUETOOTH"/>
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN"/>
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/>
<uses-permission android:name="andriod.permission.ACCESS_FINE_LOCATION"/>

APK中请求位置权限

Android5以上版本必须要ACCESS_COARSE_LOCATION权限,否则无法scan到device, 在scan device前调用mayRequestLocation请求ACCESS_COARSE_LOCATION权限

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
private static final int REQUEST_COARSE_LOCATION = 0;

private void mayRequestLocation() {
if (Build.VERSION.SDK_INT >= 23) {
int checkCallPhonePermission = ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION);
if (checkCalldePhonePermission != PackageManager.PERMISSION_GRANTED) {
ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.ACCESS_COARSE_LOCATION}, REQUEST_COARSE_LOCATION);
return;
}
}
}

@Override
public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
if (requestCode == REQUEST_COARSE_LOCATION) {
if (grantResults[0] == PackageManager.PERMISSION_GRANTED) {
Toast.makeText(this, "权限被授予", Toast.LENGTH_SHORT).show();
} else if (grantResults[0] != PackageManager.PERMISSION_GRANTED) {
Toast.makeText(this, "权限被拒绝", Toast.LENGTH_SHORT).show();
}
} else {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
}
}

扫描过程

检查SDK是否支援BLE

1
2
3
if(!getPackageManager().hasSystemFeature(PackageManager.FEATURE_BLUETOOTH_LE)){
Toast.makeText(MainActivity.this, R.string.noble, Toast.LENGTH_LONG);
}

检查HW是否有蓝牙

1
2
3
4
5
BluetoothManager bluetoothManager = (BluetoothManager) getSystemService(Context.BLUETOOTH_SERVICE);
BluetoothAdapter mBluetoothAdapter = bluetoothManager.getAdapter();
if(mBluetoothAdapter == null){
Toast.makeText(MainActivity.this, R.string.nobleerr, Toast.LENGTH_LONG);
}

检查是否开启蓝牙

1
2
3
4
5
if(!mBluetoothAdapter.isEnabled()){
//未开启蓝牙,询问是否开启蓝牙
Intent enableBLE = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
startActivity(enableBLE);
}

扫描BLE Device

实现扫描Callback

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
ScanCallback mScanCB = new ScanCallback() {
@Override
public void onScanResult(int callbackType, ScanResult result) {
super.onScanResult(callbackType, result);
BluetoothDevice device = result.getDevice();
if(!mDeviceList.contains(device)) {
mDeviceList.add(device);
}
}

@Override
public void onScanFailed(int errorCode) {
super.onScanFailed(errorCode);
Log.e(TAG, "Scan Fail " + errorCode);
}
};

启动扫描

将实现的扫描callback注册启动扫描,如果由扫到device会回调到onScanResult,在onScanResult中处理扫描到的device

1
2
BluetoothLeScanner mScanner = mBluetoothAdapter.getBluetoothLeScanner();
mScanner.startScan(mScanCB);

停止扫描

1
mScanner.stopScan(mScanCB);