Diminuiu o BLE startScan detectados dispositivos no Android 5.0 Lollipop

Versão curta:

Nos meus testes com o Android 5.0 Lollipop eu noteiandroid.bluetooth.le.BluetoothLeScanner detecta dispositivos BLE com menos frequência do que o Android 4.4 KitKat. Por que isso e existe uma alternativa?

Versão longa:

Estou desenvolvendo um aplicativo Android, especificamente para o tablet Nexus 7, focado na detecção de dispositivos Bluetooth Low Energy (BLE). O aplicativo está interessado principalmente no valor RSSI dos faróis, para determinar sua proximidade com o tablet. Isso significa que não precisarei me conectar ao dispositivo BLE, pois o valor RSSI é passado para o retorno de chamada da varredura quando o dispositivo é detectado.

No Android 4.4 KitKat, quando ligoBluetoothAdapter.startLeScan(LeScanCallback), meu retorno de chamada é chamado apenas UMA VEZ para cada dispositivo BLE detectado. (Eu tenho vistoalgumas discussões (afirmo que esse comportamento pode variar de acordo com o dispositivo) No entanto, estou interessado na constante mudança do valor RSSI, portanto, a maneira atualmente recomendada é continuamente iniciar startLeScan e stopLeScan com um intervalo definido (250ms no meu caso):

public class TheOldWay {

    private static final int SCAN_INTERVAL_MS = 250;

    private Handler scanHandler = new Handler();
    private boolean isScanning = false;

    public void beginScanning() {
        scanHandler.post(scanRunnable);
    }

    private Runnable scanRunnable = new Runnable() {
        @Override
        public void run() {
            BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter();

            if (isScanning) {
                adapter.stopLeScan(leScanCallback);
            } else if (!adapter.startLeScan(leScanCallback)) {
                // an error occurred during startLeScan
            }

            isScanning = !isScanning;

            scanHandler.postDelayed(this, SCAN_INTERVAL_MS);
        }
    };

    private BluetoothAdapter.LeScanCallback leScanCallback = new BluetoothAdapter.LeScanCallback() {
        @Override
        public void onLeScan(BluetoothDevice device, int rssi, byte[] scanRecord) {
            // use the RSSI value
        }
    };

}

Essencialmente, isso me fornece os resultados necessários, mas esse processo consome muitos recursos e, eventualmente, leva a um adaptador bluetooth que não responde.

Por esses motivos, atualizei meu Nexus 7 para o Android 5.0 Lollipop para verificar se meus problemas com o BLE seriam corrigidos. No Lollipop, o BluetoothAdapter.startLeScan (LeScanCallback) foi descontinuado e substituído poruma nova API isso permite um pouco mais de controle sobre o processo de digitalização. Nos meus primeiros testes, parece que o startScan não chama continuamente meu retorno de chamada (no meu Nexus 7) quando os valores do RSSI mudam, então ainda preciso usar a implementação startScan / stopScan:

@TargetApi(21)
public class TheNewWay {

    private static final int SCAN_INTERVAL_MS = 250;

    private Handler scanHandler = new Handler();
    private List<ScanFilter> scanFilters = new ArrayList<ScanFilter>();
    private ScanSettings scanSettings;
    private boolean isScanning = false;

    public void beginScanning() {
        ScanSettings.Builder scanSettingsBuilder = new ScanSettings.Builder();
        scanSettingsBuilder.setScanMode(ScanSettings.SCAN_MODE_LOW_LATENCY);
        scanSettings = scanSettingsBuilder.build();

        scanHandler.post(scanRunnable);
    }

    private Runnable scanRunnable = new Runnable() {
        @Override
        public void run() {
            BluetoothLeScanner scanner = BluetoothAdapter.getDefaultAdapter().getBluetoothLeScanner();

            if (isScanning) {
                scanner.stopScan(scanCallback);
            } else {
                scanner.startScan(scanFilters, scanSettings, scanCallback);
            }

            isScanning = !isScanning;

            scanHandler.postDelayed(this, SCAN_INTERVAL_MS);
        }
    };

    private ScanCallback scanCallback = new ScanCallback() {
        @Override
        public void onScanResult(int callbackType, ScanResult result) {
            super.onScanResult(callbackType, result);

            int rssi = result.getRssi();

            // do something with RSSI value
        }

        @Override
        public void onScanFailed(int errorCode) {
            super.onScanFailed(errorCode);

            // a scan error occurred
        }
    };

}

Como você pode ver, eu configurei o scanner usando a classe ScanSettings, que permite definir oscanMode. eu usoScanSettings.SCAN_MODE_LOW_LATENCY, que possui a seguinte documentação: "Digitalize usando o ciclo de trabalho mais alto. Recomenda-se usar esse modo apenas quando o aplicativo estiver sendo executado em primeiro plano". Parece exatamente o que eu quero, mas infelizmente só recebo um sinalizador a cada 15 a 30 segundos, onde a versão KitKat me mostra o mesmo sinal a cada 1 ou 2 segundos nesse intervalo de verificação.

Você tem alguma idéia de qual poderia ser o motivo dessa diferença? Estou faltando alguma coisa, talvez algumas novas configurações? Existem maneiras alternativas de fazer o acima?

Muito obrigado antecipadamente!

Abel

PS: Eu queria incluir mais links para os recursos que usei, mas ainda não tenho os pontos de representante.

questionAnswers(5)

yourAnswerToTheQuestion