-1

我有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) 
+0

您是否尝试在finish()方法之前调用cancell?通过日志,似乎onCancelled()被称为太迟...尝试将呼叫移动到取消方法onBackPressed方法 – W0rmH0le

+0

@GuilhermeP我试着你建议,但我收到了同样的错误..我的结论是,oncancel ()是异步方法 – LetsamrIt

+0

Humm ..它是有道理的..也许,你应该移动你的注册和取消注册方法的活动..或添加一些逻辑,等到广播被取消... – W0rmH0le

回答

0

一个重要的事情在这里我s“无关紧要你的AsyncTask被取消或不”。当你注册一个的BroadcastReceiver必须取消它(无论您的AsyncTask状态)

@Override 
protected void onDestroy() { 
    super.onDestroy(); 
    //without any condition. 
    unregisterReceiver(mBCR_POWER_STATE_CHANGED); 
} 

Happy_Coding;

+0

好吧,我知道我必须取消注册任何已注册的接收者...但我在onprexecute中注册了接收者,我认为它应该在onPostexecute和oncancelled中注销。 – LetsamrIt