我有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 com.example.com.onprepareoptionsmenu_01.MainActivity$1@3f2f9d 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 com.example.com.onprepareoptionsmenu_01.MainActivity$1@3f2f9d 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: com.example.com.onprepareoptionsmenu_01.MainActivity$1@3f2f9d
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)
答案 0 :(得分:0)
这里有一个重要的事情是&#34;无论你的AsyncTask是否被取消都没关系&#34;。每当您注册 BroadCastReceiver 时,您必须取消注册(无论您的AsyncTask状态如何)
@Override
protected void onDestroy() {
super.onDestroy();
//without any condition.
unregisterReceiver(mBCR_POWER_STATE_CHANGED);
}