Как мне запустить BLE-сканирование в фоновом режиме, только если мое приложение работает и в фоновом режиме, а не уничтожено?

#java #android #bluetooth #background #bluetooth-lowenergy

#java #Android #bluetooth #фон #bluetooth-lowenergy

Вопрос:

Мое приложение сканирует устройства BLE, находясь в фоновом режиме, чтобы пользователю можно было отправлять уведомления, если устройства перестают рекламировать или их RSSI падает ниже установленного предела.

Однако я заметил, что, хотя мое приложение закрыто и больше не работает в фоновом режиме, мое приложение иногда все равно будет сканировать устройства BLE. Как я могу сделать так, чтобы эти фоновые проверки BLE выполнялись в фоновом режиме только тогда, когда мое приложение работает и работает в фоновом режиме?

В настоящее время я отключаю сканирование в обратном вызове onDestroy, но я прочитал, что это не рекомендуется, поскольку код там не всегда выполняется. Это также причина, по которой мое приложение все равно иногда будет сканироваться в фоновом режиме.

Ниже приведен обратный вызов onDestroy и код, который я использую для запуска или остановки сканирования.

 @Override
public void onDestroy() {
    super.onDestroy();
    scanLeDevice(false); //stop scanning and stop notification from showing when app closed
    try {
        unregisterReceiver(mReceiverOn);
        unregisterReceiver(mReceiverOff);
        //Register or UnRegister your broadcast receiver here

    } catch(IllegalArgumentException e) {

        e.printStackTrace();
    }
    stopService();
    Log.d("lifecycle", "onDestroy: isAppRunning in on destroy");
}

 private void scanLeDevice(final boolean enable) { //need to update to non deprecated code
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M amp;amp; PackageManager.PERMISSION_GRANTED != getApplicationContext().checkCallingOrSelfPermission(Manifest.permission.ACCESS_FINE_LOCATION))
    {
        Toast.makeText(DeviceScanActivity.this, R.string.location_permission_needed, Toast.LENGTH_SHORT).show();
        requestPermissions(new String[]{Manifest.permission.ACCESS_FINE_LOCATION}, 9); //get fine location, needed for android 10
    }
    else if (enable amp;amp; !scanRunning) { //starting a scan that is currently not running
        mHandler.postDelayed(new Runnable() {
            @Override
            public void run() { //Stops scanning after a pre-defined scan period. This is required if you are to scan indefinitely
                mBluetoothAdapter.stopLeScan(mLeScanCallback );
                scanRunning = false;
                if(mScanning)
                    mHandler2.postDelayed(new Runnable() {
                        @Override
                        public void run() {
                            scanLeDevice(true);
                        }
                    }, 650);
                invalidateOptionsMenu();
            }
        }, 8000);
        mScanning = true;
        scanRunning = true;
        boolean onScanner = mBluetoothAdapter.startLeScan(uuid, mLeScanCallback);
        Log.d(TAG, "scanLeDevice: onScanner "   onScanner   " isDiscovering "   mBluetoothAdapter.isDiscovering());
    } else if (enable amp;amp; appNotDestroyed){ //scanRunning is true
        mScanning = true;
        mBluetoothAdapter.startLeScan(uuid, mLeScanCallback);
        Log.d(TAG, "scanLeDevice: mScanning "   mScanning   " isDiscovering "   mBluetoothAdapter.isDiscovering());
    } else { //enable is false
        mScanning = false;
        mBluetoothAdapter.stopLeScan(mLeScanCallback);
        if(!clearHandlerHasRunnable) {
            clearHandlerHasRunnable = true;
            clearHandler.postDelayed(new Runnable() {
                @Override
                public void run() {
                    if (!mScanning)
                        clearUnsavedDevices(mLeDevices);
                    clearHandlerHasRunnable = false;
                }
            }, 3000);
        }
    }
    invalidateOptionsMenu();
    if(!mScanning){ //clear indicators for all cells so that user isn't confused by certain indicators being on/off
        for (int i = 0; i < mLeDevices.size(); i  ){
            updateViewScanFor(i);
        }
    }
}
  

Комментарии:

1. просто отключите сканирование в onPause() ?

2. Я хочу, чтобы мое приложение продолжало сканирование, когда оно работает в фоновом режиме и работает.

3. приложение автоматически уничтожается системой Android при нехватке ресурсов, в других случаях приложение будет работать в фоновом режиме. чтобы явно уничтожить вашу активность, вы можете вызвать finish() и установить scanLeDevice(false);

Ответ №1:

Я больше не запускаю фоновое сканирование в своей onPause(), а затем останавливаю его в onDestroy() в своей основной деятельности.

Вместо этого я запускаю службу переднего плана, в которой выполняется мое сканирование. Это позволяет моему приложению останавливать службу и, следовательно, сканирование, когда мое приложение уничтожается, поскольку в фоновом режиме ничего не происходит.