[Android BLE扫描20分钟后冻结UI线程

问题描述 投票:0回答:1

我正在尝试为研究项目连续扫描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进行此类长时间操作会有所帮助吗?任何指南将不胜感激。谢谢。

android bluetooth-lowenergy android-bluetooth android-ble
1个回答
0
投票

使用AsyncTask进行这种长时间的操作不会有帮助。 Android 7.0引入了BLE扫描超时,其中有效运行30分钟或更长时间的任何扫描都会自动停止:https://stackoverflow.com/a/44488991/2068732

此外,BLE扫描会耗尽电池电量,因此应避免长时间运行BLE扫描。

如果您的应用确实需要频繁扫描,则您可以考虑根据用户的操作停止并重新启动BLE扫描。但是请记住,Android 7可以在30秒内阻止扫描启动-停止超过5次。


0
投票

您应使用后台线程进行此过程,因为在扫描时,您的ui线程可能被阻止,这是ui冻结的原因。为此,请使用任务调度程序或任何其他后台进程。

© www.soinside.com 2019 - 2024. All rights reserved.