我有aAsyncTask
如下面的代码所示,它的任务是启用蓝牙适配器。在onPreExecute我注册了动作ACTION_STATE_CHANGED
以获得有关蓝牙适配器电源状态的通知(开,关,开机,关机)。这个接收器在onPreexecute
“未注册”,以便当asynctask完成注销接收器“并取消”,这样如果后退按钮被按下,任务将被取消并且接收器应该是未注册的“ ”。何时何地我应该取消注册广播接收机?
但是,当任务正在运行并按下后退按钮取消正在运行的任务时,尽管接收器未在onCancelled
中注册,我仍会收到以下logcat错误。
为什么会发生这种情况,以及如何解决它?
代码:
@Override
protected void onDestroy() {
super.onDestroy();
Log.w(TAG, "onDestroy");
if (this.mATEnableBT != null && this.mATEnableBT.getStatus() != AsyncTask.Status.FINISHED) {
this.mATEnableBT.cancel(true);
}
}
@Override
public void onBackPressed() {
super.onBackPressed();
Log.w(TAG, "onBackPressed");
finish();
}
..
..
..
private BroadcastReceiver mBCR_POWER_STATE_CHANGED = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
Log.w(TAG, SubTag.msg("mBCR_STATE_CHANGED"));
final int prevPowState = intent.getIntExtra(BluetoothAdapter.EXTRA_PREVIOUS_STATE, BluetoothAdapter.ERROR);
switch (prevPowState) {
case BluetoothAdapter.STATE_ON:
Log.v(TAG, SubTag.msg("mBCR_STATE_CHANGED", "prevPowState: STATE_ON"));
break;
case BluetoothAdapter.STATE_TURNING_ON:
Log.v(TAG, SubTag.msg("mBCR_STATE_CHANGED", "prevPowState: STATE_TURNING_ON"));
break;
case BluetoothAdapter.STATE_TURNING_OFF:
Log.v(TAG, SubTag.msg("mBCR_STATE_CHANGED", "prevPowState: STATE_TURNING_OFF"));
break;
case BluetoothAdapter.STATE_OFF:
Log.v(TAG, SubTag.msg("mBCR_STATE_CHANGED", "prevPowState: STATE_OFF"));
break;
case BluetoothAdapter.ERROR:
Log.e(TAG, SubTag.msg("mBCR_STATE_CHANGED", "NO_PREVIOUS_POWER_STATE"));
break;
}
final int currPowState = intent.getIntExtra(BluetoothAdapter.EXTRA_STATE, BluetoothAdapter.ERROR);
switch (currPowState) {
case BluetoothAdapter.STATE_ON:
Log.v(TAG, SubTag.msg("mBCR_STATE_CHANGED", "currPowState: STATE_ON"));
break;
case BluetoothAdapter.STATE_TURNING_ON:
Log.v(TAG, SubTag.msg("mBCR_STATE_CHANGED", "currPowState: STATE_TURNING_ON"));
break;
case BluetoothAdapter.STATE_TURNING_OFF:
Log.v(TAG, SubTag.msg("mBCR_STATE_CHANGED: currPowState: STATE_TURNING_OFF"));
break;
case BluetoothAdapter.STATE_OFF:
Log.v(TAG, SubTag.msg("mBCR_STATE_CHANGED: currPowState: STATE_OFF"));
break;
case BluetoothAdapter.ERROR:
Log.e(TAG, SubTag.msg("mBCR_STATE_CHANGED", "NO_CURRENT_POWER_STATE"));
break;
}
if ((prevPowState == BluetoothAdapter.STATE_TURNING_ON) && (currPowState == BluetoothAdapter.STATE_ON)) {
Log.i(TAG, SubTag.msg("mBCR_STATE_CHANGED: BT-Power ON"));
}
if ((prevPowState == BluetoothAdapter.STATE_TURNING_OFF) && (currPowState == BluetoothAdapter.STATE_OFF)) {
Log.i(TAG, SubTag.msg("mBCR_STATE_CHANGED: BT-Power OFF"));
finish();
}
}
};
的AsyncTask:
private class ATEnableBT extends AsyncTask<Void,Void,Void> {
private int mWaitTime = getApplicationContext().getResources().getInteger(R.integer.int_max_wait_time);
private int mSleepTime = getApplicationContext().getResources().getInteger(R.integer.int_sleep_time);
@Override
protected void onPreExecute() {
super.onPreExecute();
Log.w(TAG, "onPreExecute");
registerReceiver(mBCR_POWER_STATE_CHANGED, new IntentFilter(BluetoothAdapter.ACTION_STATE_CHANGED));
}
@Override
protected Void doInBackground(Void... params) {
Log.w(TAG, "doInBackground");
mBTAdapter.enable();
while(!isCancelled() && mBTAdapter.getState() != BluetoothAdapter.STATE_ON && this.mWaitTime > 0) {
SystemClock.sleep(2000);
this.mWaitTime -= this.mSleepTime;
}
return null;
}
@Override
protected void onPostExecute(Void aVoid) {
super.onPostExecute(aVoid);
Log.w(TAG, "onPostExecute");
unregisterReceiver(mBCR_POWER_STATE_CHANGED);
}
@Override
protected void onCancelled(Void aVoid) {
super.onCancelled(aVoid);
Log.w(TAG, "onCancelled");
unregisterReceiver(mBCR_POWER_STATE_CHANGED);
}
}
logcat的
02-13 11:45:44.948 25978-25978/com.example.com.bt_11 E/ActivityThread: Activity com.example.com.onprepareoptionsmenu_01.MainActivity has leaked IntentReceiver [email protected] that was originally registered here. Are you missing a call to unregisterReceiver()?
02-13 11:45:44.948 25978-25978/com.example.com.bt_11 E/ActivityThread: android.app.IntentReceiverLeaked: Activity com.example.com.onprepareoptionsmenu_01.MainActivity has leaked IntentReceiver [email protected] that was originally registered here. Are you missing a call to unregisterReceiver()?
02-13 11:45:44.948 25978-25978/com.example.com.bt_11 E/ActivityThread: at android.app.LoadedApk$ReceiverDispatcher.<init>(LoadedApk.java:960)
02-13 11:45:44.948 25978-25978/com.example.com.bt_11 E/ActivityThread: at android.app.LoadedApk.getReceiverDispatcher(LoadedApk.java:761)
02-13 11:45:44.948 25978-25978/com.example.com.bt_11 E/ActivityThread: at android.app.ContextImpl.registerReceiverInternal(ContextImpl.java:2002)
02-13 11:45:44.948 25978-25978/com.example.com.bt_11 E/ActivityThread: at android.app.ContextImpl.registerReceiver(ContextImpl.java:1982)
02-13 11:45:44.948 25978-25978/com.example.com.bt_11 E/ActivityThread: at android.app.ContextImpl.registerReceiver(ContextImpl.java:1976)
02-13 11:45:44.948 25978-25978/com.example.com.bt_11 E/ActivityThread: at android.content.ContextWrapper.registerReceiver(ContextWrapper.java:503)
02-13 11:45:44.948 25978-25978/com.example.com.bt_11 E/ActivityThread: at com.example.com.onprepareoptionsmenu_01.MainActivity$ATEnableBT.onPreExecute(MainActivity.java:36)
02-13 11:45:44.948 25978-25978/com.example.com.bt_11 E/ActivityThread: at android.os.AsyncTask.executeOnExecutor(AsyncTask.java:587)
02-13 11:45:44.948 25978-25978/com.example.com.bt_11 E/ActivityThread: at android.os.AsyncTask.execute(AsyncTask.java:535)
02-13 11:45:44.948 25978-25978/com.example.com.bt_11 E/ActivityThread: at com.example.com.onprepareoptionsmenu_01.MainActivity.onOptionsItemSelected(MainActivity.java:108)
02-13 11:45:44.948 25978-25978/com.example.com.bt_11 E/ActivityThread: at android.app.Activity.onMenuItemSelected(Activity.java:3024)
02-13 11:45:44.948 25978-25978/com.example.com.bt_11 E/ActivityThread: at android.support.v4.app.FragmentActivity.onMenuItemSelected(FragmentActivity.java:325)
02-13 11:45:44.948 25978-25978/com.example.com.bt_11 E/ActivityThread: at android.support.v7.app.AppCompatActivity.onMenuItemSelected(AppCompatActivity.java:147)
02-13 11:45:44.948 25978-25978/com.example.com.bt_11 E/ActivityThread: at android.support.v7.internal.view.WindowCallbackWrapper.onMenuItemSelected(WindowCallbackWrapper.java:100)
02-13 11:45:44.948 25978-25978/com.example.com.bt_11 E/ActivityThread: at android.support.v7.app.AppCompatDelegateImplV7.onMenuItemSelected(AppCompatDelegateImplV7.java:609)
02-13 11:45:44.948 25978-25978/com.example.com.bt_11 E/ActivityThread: at android.support.v7.internal.view.menu.MenuBuilder.dispatchMenuItemSelected(MenuBuilder.java:811)
02-13 11:45:44.948 25978-25978/com.example.com.bt_11 E/ActivityThread: at android.support.v7.internal.view.menu.MenuItemImpl.invoke(MenuItemImpl.java:153)
02-13 11:45:44.948 25978-25978/com.example.com.bt_11 E/ActivityThread: at android.support.v7.internal.view.menu.MenuBuilder.performItemAction(MenuBuilder.java:958)
02-13 11:45:44.948 25978-25978/com.example.com.bt_11 E/ActivityThread: at android.support.v7.internal.view.menu.MenuBuilder.performItemAction(MenuBuilder.java:948)
02-13 11:45:44.948 25978-25978/com.example.com.bt_11 E/ActivityThread: at android.support.v7.widget.ActionMenuView.invokeItem(ActionMenuView.java:619)
02-13 11:45:44.948 25978-25978/com.example.com.bt_11 E/ActivityThread: at android.support.v7.internal.view.menu.ActionMenuItemView.onClick(ActionMenuItemView.java:139)
02-13 11:45:44.948 25978-25978/com.example.com.bt_11 E/ActivityThread: at android.view.View.performClick(View.java:5184)
02-13 11:45:44.948 25978-25978/com.example.com.bt_11 E/ActivityThread: at android.view.View$PerformClick.run(View.java:20893)
02-13 11:45:44.948 25978-25978/com.example.com.bt_11 E/ActivityThread: at android.os.Handler.handleCallback(Handler.java:739)
02-13 11:45:44.948 25978-25978/com.example.com.bt_11 E/ActivityThread: at android.os.Handler.dispatchMessage(Handler.java:95)
02-13 11:45:44.948 25978-25978/com.example.com.bt_11 E/ActivityThread: at android.os.Looper.loop(Looper.java:145)
02-13 11:45:44.948 25978-25978/com.example.com.bt_11 E/ActivityThread: at android.app.ActivityThread.main(ActivityThread.java:5938)
02-13 11:45:44.948 25978-25978/com.example.com.bt_11 E/ActivityThread: at java.lang.reflect.Method.invoke(Native Method)
02-13 11:45:44.948 25978-25978/com.example.com.bt_11 E/ActivityThread: at java.lang.reflect.Method.invoke(Method.java:372)
02-13 11:45:44.948 25978-25978/com.example.com.bt_11 E/ActivityThread: at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1400)
02-13 11:45:44.948 25978-25978/com.example.com.bt_11 E/ActivityThread: at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1195)
02-13 11:45:46.158 25978-25978/com.example.com.bt_11 W/MainActivity: onCancelled
02-13 11:45:46.168 25978-25978/com.example.com.bt_11 D/AndroidRuntime: Shutting down VM
02-13 11:45:46.178 25978-25978/com.example.com.bt_11 E/AndroidRuntime: FATAL EXCEPTION: main
02-13 11:45:46.178 25978-25978/com.example.com.bt_11 E/AndroidRuntime: Process: com.example.com.bt_11, PID: 25978
02-13 11:45:46.178 25978-25978/com.example.com.bt_11 E/AndroidRuntime: java.lang.IllegalArgumentException: Receiver not registered: [email protected]
02-13 11:45:46.178 25978-25978/com.example.com.bt_11 E/AndroidRuntime: at android.app.LoadedApk.forgetReceiverDispatcher(LoadedApk.java:822)
02-13 11:45:46.178 25978-25978/com.example.com.bt_11 E/AndroidRuntime: at android.app.ContextImpl.unregisterReceiver(ContextImpl.java:2025)
02-13 11:45:46.178 25978-25978/com.example.com.bt_11 E/AndroidRuntime: at android.content.ContextWrapper.unregisterReceiver(ContextWrapper.java:528)
02-13 11:45:46.178 25978-25978/com.example.com.bt_11 E/AndroidRuntime: at com.example.com.onprepareoptionsmenu_01.MainActivity$ATEnableBT.onCancelled(MainActivity.java:65)
02-13 11:45:46.178 25978-25978/com.example.com.bt_11 E/AndroidRuntime: at com.example.com.onprepareoptionsmenu_01.MainActivity$ATEnableBT.onCancelled(MainActivity.java:26)
02-13 11:45:46.178 25978-25978/com.example.com.bt_11 E/AndroidRuntime: at android.os.AsyncTask.finish(AsyncTask.java:630)
02-13 11:45:46.178 25978-25978/com.example.com.bt_11 E/AndroidRuntime: at android.os.AsyncTask.access$600(AsyncTask.java:177)
02-13 11:45:46.178 25978-25978/com.example.com.bt_11 E/AndroidRuntime: at android.os.AsyncTask$InternalHandler.handleMessage(AsyncTask.java:645)
02-13 11:45:46.178 25978-25978/com.example.com.bt_11 E/AndroidRuntime: at android.os.Handler.dispatchMessage(Handler.java:102)
02-13 11:45:46.178 25978-25978/com.example.com.bt_11 E/AndroidRuntime: at android.os.Looper.loop(Looper.java:145)
02-13 11:45:46.178 25978-25978/com.example.com.bt_11 E/AndroidRuntime: at android.app.ActivityThread.main(ActivityThread.java:5938)
02-13 11:45:46.178 25978-25978/com.example.com.bt_11 E/AndroidRuntime: at java.lang.reflect.Method.invoke(Native Method)
02-13 11:45:46.178 25978-25978/com.example.com.bt_11 E/AndroidRuntime: at java.lang.reflect.Method.invoke(Method.java:372)
02-13 11:45:46.178 25978-25978/com.example.com.bt_11 E/AndroidRuntime: at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1400)
02-13 11:45:46.178 25978-25978/com.example.com.bt_11 E/AndroidRuntime: at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1195)
您是否尝试在finish()方法之前调用cancell?通过日志,似乎onCancelled()被称为太迟...尝试将呼叫移动到取消方法onBackPressed方法 – W0rmH0le
@GuilhermeP我试着你建议,但我收到了同样的错误..我的结论是,oncancel ()是异步方法 – LetsamrIt
Humm ..它是有道理的..也许,你应该移动你的注册和取消注册方法的活动..或添加一些逻辑,等到广播被取消... – W0rmH0le