简体   繁体   中英

Unregistering Broadcast Receiver error

I want to get the available bluetooth devices in my android app so as i can pair or unfair a device through my app. I am registering a broadcast receiver to inform my list of new devices. I do this in an activity, but when i destroy my activity with finish() even though i am unregistering the receiver it keeps giving me the following error.

Exception:

03-10 10:24:48.790 25219-25219/com.vidame E/ActivityThread: Activity com.vidame.Activities.BloodPressureActivity has leaked IntentReceiver com.vidame.HelperClasses.Bluetooth$mPairReceiver@37341ff5 that was originally registered here. Are you missing a call to unregisterReceiver()?
android.app.IntentReceiverLeaked: Activity com.vidame.Activities.BloodPressureActivity has leaked IntentReceiver com.vidame.HelperClasses.Bluetooth$mPairReceiver@37341ff5 that was originally registered here. Are you missing a call to unregisterReceiver()?
    at android.app.LoadedApk$ReceiverDispatcher.<init>(LoadedApk.java:904)
    at android.app.LoadedApk.getReceiverDispatcher(LoadedApk.java:705)
    at android.app.ContextImpl.registerReceiverInternal(ContextImpl.java:1685)
    at android.app.ContextImpl.registerReceiver(ContextImpl.java:1665)
    at android.app.ContextImpl.registerReceiver(ContextImpl.java:1659)
    at android.content.ContextWrapper.registerReceiver(ContextWrapper.java:495)
    at com.vidame.HelperClasses.Bluetooth.registerBluetoothBroadcast(Bluetooth.java:83)
    at com.vidame.Activities.BloodPressureActivity$2.onClick(BloodPressureActivity.java:119)
    at android.view.View.performClick(View.java:4789)
    at android.view.View$PerformClick.run(View.java:19881)
    at android.os.Handler.handleCallback(Handler.java:739)
    at android.os.Handler.dispatchMessage(Handler.java:95)
    at android.os.Looper.loop(Looper.java:135)
    at android.app.ActivityThread.main(ActivityThread.java:5292)
    at java.lang.reflect.Method.invoke(Native Method)
    at java.lang.reflect.Method.invoke(Method.java:372)
    at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:904)
    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:699)

My have my broadcast receiver method in Bluetooth.java class with other useful methods i use in my app and call it in BloodPressureActivity . Below i have code for both these classes

This is where i register the receiver in BloodPressureActivity

devices_list.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View view) {
            bluetooth.registerBluetoothBroadcast(BloodPressureActivity.this, mAdapter, list, mProgressDlg, mListView);
            device_find.setVisibility(View.GONE);
            devices_list.setVisibility(View.GONE);
            list_view.setVisibility(View.VISIBLE);
            bluetooth.bAdapter().startDiscovery();
        }
    });

and i unregister it in my onDestroy() and onStop()

@Override
public void onDestroy() {
    bluetooth.unRegisterReceiver();
    super.onDestroy();
}

@Override
protected void onStop() {
    bluetooth.unRegisterReceiver();
    super.onStop();
}

Now in the Bluetooth.class my broadcast receiver

 public void registerBluetoothBroadcast (Activity parent, DeviceListAdapter mAdapter, ArrayList<BluetoothDevice> list, ProgressDialog mProgressDlg, ListView mListView){
    this.activity=parent;
    this.mAdapter=mAdapter;
    this.list=list;
    this.mProgressDlg=mProgressDlg;
    this.mListView=mListView;

    IntentFilter filter = new IntentFilter();
    filter.addAction(BluetoothAdapter.ACTION_STATE_CHANGED);
    filter.addAction(BluetoothDevice.ACTION_FOUND);
    filter.addAction(BluetoothAdapter.ACTION_DISCOVERY_STARTED);
    filter.addAction(BluetoothAdapter.ACTION_DISCOVERY_FINISHED);
    //filter.addAction(BluetoothDevice.ACTION_BOND_STATE_CHANGED);
    activity.registerReceiver(mPairReceiver, filter);
}


public final BroadcastReceiver mPairReceiver = new BroadcastReceiver() {
    public void onReceive(Context context, Intent intent) {
        String action = intent.getAction();

        if (BluetoothDevice.ACTION_BOND_STATE_CHANGED.equals(action)) {
            final int state = intent.getIntExtra(BluetoothDevice.EXTRA_BOND_STATE, BluetoothDevice.ERROR);
            final int prevState = intent.getIntExtra(BluetoothDevice.EXTRA_PREVIOUS_BOND_STATE, BluetoothDevice.ERROR);

            if (state == BluetoothDevice.BOND_BONDED && prevState == BluetoothDevice.BOND_BONDING) {
                ShowMessage("Paired");
            } else if (state == BluetoothDevice.BOND_NONE && prevState == BluetoothDevice.BOND_BONDED){
                ShowMessage("Unpaired");
            }
            mAdapter.notifyDataSetChanged();
        }else if (BluetoothAdapter.ACTION_DISCOVERY_STARTED.equals(action)) {
            list = new ArrayList<>();
            mProgressDlg.show();
        } else if (BluetoothAdapter.ACTION_DISCOVERY_FINISHED.equals(action)) {
            mProgressDlg.dismiss();
            showDevicesList(list);
        } else if (BluetoothDevice.ACTION_FOUND.equals(action)) {
            BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
            list.add(device);
            ShowMessage("Found device " + device.getName());
        }
    }
};

public void unRegisterReceiver(){
    if(mPairReceiver!=null){
        LocalBroadcastManager.getInstance(activity).unregisterReceiver(mPairReceiver);
    }
}

Is there something the i am missing about unregistered the receiver?

You are unregistering it twice, in your onDestroy() and in onStop() . If you are registering your broadcast in your onCreate method, you must unregister it in onDestroy and if you are registering it in onStart you must unregister it in onStop . In your case, you are registering the broadcast in a clickListener, so if the user doesn't click on this button, the broadcast is not registered and you are trying to unregister it after that. so you must do a test if the broadcast is registered. I advise you to add a boolean attribute and when the user click on this button you set this attribute to true once you are in onDestroy you test on this boolean if it is true you unregister your broadcast.

devices_list.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View view) {
            bluetooth.registerBluetoothBroadcast(BloodPressureActivity.this, mAdapter, list, mProgressDlg, mListView);
            registred = true;
            device_find.setVisibility(View.GONE);
            devices_list.setVisibility(View.GONE);
            list_view.setVisibility(View.VISIBLE);
            bluetooth.bAdapter().startDiscovery();
        }
    });

onDestroy{
...//your code
if(registred){
unregisterBroadcast(your broadcast);
}

}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM