我正在尝试为研究项目连续扫描BLE设备。我使用BLE扫描的LOW_LATENCY模式。但是,大约20分钟后,我的UI冻结了。
基本上,我按下按钮应该开始扫描BLE设备,再次按下按钮应该停止扫描。我想连续扫描至少2个小时。以下是我的代码。
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
toggle = (ToggleButton) findViewById(R.id.toggleButton); // initiate a toggle button
tv = (TextView) findViewById(R.id.tv);
EasyPermissions.requestPermissions(this, "need permission", 1001, Manifest.permission.ACCESS_FINE_LOCATION, Manifest.permission.WRITE_EXTERNAL_STORAGE,Manifest.permission.ACCESS_COARSE_LOCATION,Manifest.permission.BLUETOOTH,Manifest.permission.BLUETOOTH_ADMIN);
// Check BLE support for the device
if (!getPackageManager().hasSystemFeature(PackageManager.FEATURE_BLUETOOTH_LE)) {
Toast.makeText(getApplicationContext(),"no bluetooth LE functionality", Toast.LENGTH_SHORT).show();
finish();
}
btManager = (BluetoothManager)getSystemService(Context.BLUETOOTH_SERVICE);
btAdapter = btManager.getAdapter();
bLEScanner = btAdapter.getBluetoothLeScanner();
settings = new ScanSettings.Builder()
.setScanMode(SCAN_MODE_LOW_LATENCY)
.setCallbackType(ScanSettings.CALLBACK_TYPE_ALL_MATCHES)
.build();
toggle.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
@TargetApi(Build.VERSION_CODES.N)
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
if (isChecked) {
Toast.makeText(getApplicationContext(), "Scanning started",
Toast.LENGTH_SHORT).show();
// The toggle is enabled
bFileName = getBluetoothFileName("Bluetooth");
bLEScanner.startScan(null,settings,bluetoothLeScanCallback);
} else {
// The toggle is disabled
Toast.makeText(getApplicationContext(), "Scanning stopped",
Toast.LENGTH_SHORT).show();
bLEScanner.stopScan(bluetoothLeScanCallback);
}
}
});
}
扫描回叫代码
private ScanCallback bluetoothLeScanCallback = new ScanCallback() {
@Override
public void onScanResult(int callbackType, android.bluetooth.le.ScanResult result) {
byte[] scanRecord = result.getScanRecord().getBytes();
int startByte = 2;
boolean patternFound = false;
while (startByte <= 5)
{
if ( ((int) scanRecord[startByte + 2] & 0xff) == 0x02 && //Identifies an iBeacon
((int) scanRecord[startByte + 3] & 0xff) == 0x15)
{ //Identifies correct data length
patternFound = true;
break;
}
startByte++;
}
if (patternFound)
{
//Convert to hex String
byte[] uuidBytes = new byte[16];
System.arraycopy(scanRecord, startByte + 4, uuidBytes, 0, 16);
String hexString = bytesToHex(uuidBytes);
//UUID detection
String uuid = hexString.substring(0,8) + "-" +
hexString.substring(8,12) + "-" +
hexString.substring(12,16) + "-" +
hexString.substring(16,20) + "-" +
hexString.substring(20,32);
// major
final int major = (scanRecord[startByte + 20] & 0xff) * 0x100 + (scanRecord[startByte + 21] & 0xff);
// minor
final int minor = (scanRecord[startByte + 22] & 0xff) * 0x100 + (scanRecord[startByte + 23] & 0xff);
Log.i("BLE","UUID: " +uuid + " nmajor : " +major +" nminor " +minor+" time "+getCompleteDate(System.currentTimeMillis())+" rssi "+result.getRssi());
StringBuilder bStringBuilder = new StringBuilder();
long sysTime = System.currentTimeMillis();
bStringBuilder.append(imei+","+sysTime+","+uuid+","+major+","+minor+","+result.getRssi()+","+getCompleteDate(sysTime)+","+"\n");
String finalString = bStringBuilder.toString();
exportBluetoothData(finalString, finalString.length(), "Bluetooth");
}
}
@Override
public void onScanFailed(int errorCode) {
super.onScanFailed(errorCode);
Log.i("BLE", "error");
}
};
使用AsyncTask进行此类长时间操作会有所帮助吗?任何指南将不胜感激。谢谢。
使用AsyncTask进行这种长时间的操作不会有帮助。 Android 7.0引入了BLE扫描超时,其中有效运行30分钟或更长时间的任何扫描都会自动停止:https://stackoverflow.com/a/44488991/2068732
此外,BLE扫描会耗尽电池电量,因此应避免长时间运行BLE扫描。
如果您的应用确实需要频繁扫描,则您可以考虑根据用户的操作停止并重新启动BLE扫描。但是请记住,Android 7可以在30秒内阻止扫描启动-停止超过5次。
您应使用后台线程进行此过程,因为在扫描时,您的ui线程可能被阻止,这是ui冻结的原因。为此,请使用任务调度程序或任何其他后台进程。