onPause中的unregisterReceiver(receiver)导致receiver不注册
unregisterReceiver(receiver) in onPause causes the receiver not to register
各位溢出者大家好。我有一个 BroadcastReciever 的问题 - 我知道存在大量的问题和答案,因为我在过去 2 天里一直在尝试每一个问题,所以如果你确实想将其标记为重复,请检查代码是否'与我已经写过的内容不符(因为我几乎肯定是从 SO 答案中复制的)。
我们开始吧:
我想检测在我的基地中打开或关闭的锁定屏幕 activity - 我的所有其他活动都从这里延伸
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 和两者中注册。我可以在整个 activity 中移动组合,但是一旦我引入取消注册,它就根本不起作用 - 甚至没有错误或崩溃(否则我会在此处包含堆栈跟踪)。
我能完成的事情是:
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() 会导致接收方完全取消吗?
正如我所料,你有这个问题是因为系统在 onStop()
方法之后发送 ACTION_SCREEN_OFF,所以你无法处理它,因为你已经注销了它。不知道为什么你不能处理 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()
中注销,这就是我得到这些日志的方式。
更新 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: 我错过了,如果您的 activity 已暂停,则您不需要接收事件。如果有一些你不想在 activity 暂停时执行的代码,我建议你创建简单的枚举:
枚举 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
希望对您有所帮助!
我建议延迟取消注册一段时间,我尝试了 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)
}
各位溢出者大家好。我有一个 BroadcastReciever 的问题 - 我知道存在大量的问题和答案,因为我在过去 2 天里一直在尝试每一个问题,所以如果你确实想将其标记为重复,请检查代码是否'与我已经写过的内容不符(因为我几乎肯定是从 SO 答案中复制的)。
我们开始吧:
我想检测在我的基地中打开或关闭的锁定屏幕 activity - 我的所有其他活动都从这里延伸
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 和两者中注册。我可以在整个 activity 中移动组合,但是一旦我引入取消注册,它就根本不起作用 - 甚至没有错误或崩溃(否则我会在此处包含堆栈跟踪)。
我能完成的事情是:
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() 会导致接收方完全取消吗?
正如我所料,你有这个问题是因为系统在 onStop()
方法之后发送 ACTION_SCREEN_OFF,所以你无法处理它,因为你已经注销了它。不知道为什么你不能处理 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()
中注销,这就是我得到这些日志的方式。
更新 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: 我错过了,如果您的 activity 已暂停,则您不需要接收事件。如果有一些你不想在 activity 暂停时执行的代码,我建议你创建简单的枚举:
枚举 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
希望对您有所帮助!
我建议延迟取消注册一段时间,我尝试了 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)
}