我应该何时何地取消注册广播接收器?

时间:2016-02-13 10:52:08

标签: android broadcastreceiver android-broadcast android-broadcastreceiver

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

1 个答案:

答案 0 :(得分:0)

这里有一个重要的事情是&#34;无论你的AsyncTask是否被取消都没关系&#34;。每当您注册 BroadCastReceiver 时,您必须取消注册(无论您的AsyncTask状态如何)

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