unregisterReceiver (получатель) в onPause заставляет получателя не регистрироваться

1

Привет товарищи по цветам. У меня есть проблема с BroadcastReciever - есть, я знаю, что существует множество вопросов и ответов, потому что я пробовал каждый из них в течение последних 2 дней, поэтому, пожалуйста, если вы хотите пометить это как дублирующую проверку, что код не ' не соответствует тому, что я уже написал (поскольку я почти наверняка скопировал его из SO-ответа).

И вот мы здесь:

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

public abstract class BaseActivity extends AppCompatActivity{////

здесь у меня есть переменные-члены

BroadcastReceiver receiver;
IntentFilter filter;

который я назначаю так:

receiver = new BroadcastReceiver() {
                @Override
                public void onReceive(Context context, Intent intent) {
                    if (intent.getAction() != null && intent.getAction().equals(Intent.ACTION_SCREEN_OFF)) {
                        //do some code
                    } else {
                       //do something else
                    }
                }
            };


filter = new IntentFilter(Intent.ACTION_SCREEN_ON);
filter.addAction(Intent.ACTION_SCREEN_OFF);

Это работает, как и ожидалось, если я поместил его в onCreate() или onResume() и я могу успешно вызвать registerReceiver(receiver, filter) либо создать, либо возобновить, и это работает нормально.

Я не хочу, чтобы это было активным, когда приложение приостановлено, так как все различные ответы и руководства предлагают мне отменить его регистрацию в onPause

     @Override
        protected void onPause() {
//I have commented both out to demonstrate that I have tried both before and after the calling the superclass
      //    this.unregisterReceiver(receiver);
            super.onPause();
    //      unregisterReceiver(receiver);

        }

Когда я включаю этот незарегистрированный звонок, регистрация прекращается. Я попытался зарегистрироваться в OnCreate, OnResume и оба. Я могу перемещаться по комбинации в течение всего действия, но как только я ввожу отмену регистрации, она вообще не работает - даже ошибка или сбой (в противном случае я бы включил здесь трассировку стека).

Закрытие, которое я смог достичь, это:

receiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
  if (intent.getAction() != null && intent.getAction().equals(Intent.ACTION_SCREEN_OFF)) {
  //do some code 
  unregisterReceiver(receiver);

поместив незарегистрированную запись в onRecieve, я могу отменить регистрацию получателя и перерегистрировать его правильно, за исключением того, что, если у меня есть несколько действий в стеке для моего приложения, я получаю ошибку утечки памяти и запросы трассировки, скорее, если я забыли добавить незарегистрированный звонок.

Так есть ли у кого-нибудь идеи, почему добавление незарегистрированного вызова в onPause() приведет к полной отмене получателя?

Теги:
broadcastreceiver
android-intent

2 ответа

1

Я предлагаю отложить отмену регистрации на несколько раз, и я попытался в течение 1 секунды, и это работает.

override fun onResume() {
    super.onResume()

    registerReceiver(broadcast, IntentFilter().apply {
        addAction(Intent.ACTION_SCREEN_ON)
        addAction(Intent.ACTION_SCREEN_OFF)
    })
}


override fun onPause() {
    super.onPause()

    Handler().postDelayed({
        unregisterReceiver(broadcast)
    }, 1000)
}
0

Как я и думал, у вас есть эта проблема, потому что система отправляет ACTION_SCREEN_OFF после onStop(), поэтому вы не можете обработать его, потому что вы уже зарегистрировали его. Не знаю, почему вы не можете обработать событие SCREEN_ON, потому что, когда я проверял это, я вижу, что система отправляет его после onResume(). Вот что у меня в журналах:

D/TEST: onPause:
D/TEST: onStop:
D/TEST: onReceive: action = android.intent.action.SCREEN_OFF
D/TEST: onStart:
D/TEST: onResume:
D/TEST: onReceive: action = android.intent.action.SCREEN_ON

Я думаю, оно было отправлено раньше, чем onResume, но доставлено после него.

Итак, мое решение состоит в том, чтобы зарегистрировать получатель в onCreate(@Nullable Bundle savedInstanceState) и onDestroy() регистрацию в onDestroy(), вот как я получил эти журналы.

Обновление 1: так я зарегистрировал получателя в onCreate(@Nullable Bundle savedInstanceState)

IntentFilter filter = new IntentFilter();
filter.addAction(Intent.ACTION_SCREEN_ON);
filter.addAction(Intent.ACTION_SCREEN_OFF);
registerReceiver(new TestReceiver(), filter);

Обновление 2: я пропустил, что вам не нужно получать события, если ваша активность приостановлена. Если есть какой-то код, который вы не хотите выполнять, когда действие приостановлено, я могу предложить вам создать простой enum:

enum ActivityState {НАЧИНАЕТСЯ, ВОЗОБНОВЛЕНО, ПРИОСТАНОВЛЕНО, ОСТАНОВЛЕНО}

и закрытая переменная ActivityState currentState. Затем в методах жизненного цикла присваивайте правильное состояние currentState. Затем в onReceive() вашего приемника вы можете проверить текущее состояние и сделать то, что вы хотите, в зависимости от состояния. Журналы, когда приложение активно:

D/TEST: onReceive: action = android.intent.action.SCREEN_OFF, current Activity state = STOPED
D/TEST: onReceive: action = android.intent.action.SCREEN_ON, current Activity state = RESUMED

И логи, когда приложение не было активным:

D/TEST: onReceive: action = android.intent.action.SCREEN_OFF, current Activity state = STOPED
D/TEST: onReceive: action = android.intent.action.SCREEN_ON, current Activity state = STOPED

Я надеюсь, что это помогает!

Ещё вопросы

Сообщество Overcoder
Наверх
Меню