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.