【问题标题】:Bluetoothlescanner stop scanning or scan less often when screen is turned offBluetoothlescanner 在屏幕关闭时停止扫描或减少扫描频率
【发布时间】:2019-11-29 10:24:32
【问题描述】:

我为扫描 BLE 设备创建了简单的前台服务。它应该一直扫描设备。我创建了自己的 BLE 设备,每 0.5 秒传输一帧。我有两台调试设备,一台使用 Android 9,另一台使用 Android 6。

首先我注意到我没有得到所有的 BLE 帧。我应该每 10 秒得到大约 20 帧,但是:

  • 搭载 Android 9 的设备大约有 6-7 帧,
  • 搭载 Android 6 的设备获得大约 15-17 帧,但设备以特定间隔扫描(扫描 10 秒,然后停止 5-7 秒)。

其次,我注意到当设备屏幕关闭时,它的扫描效果更差(或完全停止扫描):

  • Android 9 设备在屏幕关闭 1 分钟后停止扫描 BLE 设备,

  • 装有 Android 6 的设备在关闭屏幕后会获得大约 6 帧。

服务代码:

public class DeviceScan extends Service {

    BluetoothLeScanner btScanner;
    public static final String CHANNEL_ID = "ForegroundServiceChannel";
    List<ScanFilter> filterList = new ArrayList<>();
    {
        filterList.add(new ScanFilter.Builder().setDeviceName("MYBEACON").build());
    }

    private ScanCallback leScanCallback = new ScanCallback() {
        @Override
        public void onScanResult(int callbackType, ScanResult result) {
                Log.e("Adress: ",result.getDevice().getAddress());
                Log.e("RSSI: ", " rssi: " + result.getRssi());
        }
    };

    public void startScanning(){
        btScanner = mBluetoothAdapter.getBluetoothLeScanner();
        AsyncTask.execute(new Runnable() {
            @Override
            public void run() {
                btScanner.startScan(filterList, new ScanSettings.Builder()
                        .setScanMode(ScanSettings.SCAN_MODE_LOW_LATENCY)
                        .setReportDelay(0) //when I use different value than 0, stop scanning
                        .build(),leScanCallback);
            }
        });
    }

    public void stopScanning() {
        btScanner = mBluetoothAdapter.getBluetoothLeScanner();
        AsyncTask.execute(new Runnable() {
            @Override
            public void run() {
                btScanner.stopScan(leScanCallback);
            }
        });
    }

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {

        createNotificationChannel();
        Intent notificationIntent = new Intent(this, AlbumActivity.class);
        PendingIntent pendingIntent = PendingIntent.getActivity(this,
                0, notificationIntent, 0);

        Notification notification = new NotificationCompat.Builder(this, CHANNEL_ID)
                .setContentTitle("Foreground Service")
                .setContentText("Scanning")
                .setPriority(Notification.PRIORITY_MAX)
                .setSmallIcon(R.mipmap.ic_launcher)
                .setContentIntent(pendingIntent)
                .build();

        startForeground(1, notification);


        startScanning();
        return START_STICKY;
    }

    private void createNotificationChannel()
    {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O)
        {
            NotificationChannel serviceChannel = new NotificationChannel(
                    CHANNEL_ID,
                    "Foreground Service Channel",
                    NotificationManager.IMPORTANCE_DEFAULT
            );

            NotificationManager manager = getSystemService(NotificationManager.class);
            manager.createNotificationChannel(serviceChannel);
        }
    }
}

【问题讨论】:

  • 您使用的是哪些手机?这里有几个因素在起作用,但对于初学者来说,每个设备制造商(和手机)的 BLE 结果大相径庭(但它们正在慢慢收敛到相似的品质)。此外,您必须检查 LOW_LATENCY 扫描时间是多少,并尝试找出这些扫描时间与您的广告间隔重叠的概率。 iOS 的广告推荐是如何最大化发现概率的一个很好的例子forums.developer.apple.com/thread/9834
  • 关于设备屏幕关闭,屏幕关闭时前台服务是否被杀死?
  • @SJoshi 设备:小米 mi 6 (Android 9)、三星 Galaxy Tab S SM-T700 (Android 6)。根据 android.developers 关于 LOW_LATENCY "Scan using highest duty cycle. It's recommended to only use this mode when the application is running in the foreground." 的说法,找不到具体的扫描时间,但三星几乎可以获取所有帧,所以这应该不是问题。我认为该服务没有被杀死,因为当我打开屏幕时,设备的行为就像屏幕关闭之前一样。

标签: java android service bluetooth-lowenergy foreground-service


【解决方案1】:

试试下面的代码,它对我有用。 您需要添加空的ScanFilter并设置ScanSettings.SCAN_MODE_LOW_LATENCY

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
                ScanFilter.Builder builder = new ScanFilter.Builder();
                builder.setManufacturerData(0x004c, new byte[]{});// apply iBeacon Filter
                filters.add(builder.build());
            }

            ScanSettings.Builder scanSettingBuilder = new ScanSettings.Builder();
            scanSettingBuilder.setScanMode(ScanSettings.SCAN_MODE_LOW_LATENCY);

【讨论】:

  • 但是我需要使用 ScanFilter 那是什么?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-03-13
  • 1970-01-01
  • 1970-01-01
  • 2012-01-04
  • 2011-03-03
相关资源
最近更新 更多