BroadcastReceiver with a Listener drains battery w

2019-02-20 11:42发布

问题:

I have a receiver which waits for TelephonyManager.ACTION_PHONE_STATE_CHANGED:

public void onReceive(Context context, Intent intent) {
String theAction = intent.getAction();  
if (theAction != null && theAction.equals(TelephonyManager.ACTION_PHONE_STATE_CHANGED)) {
        CONTEXT = context;
        startListening();   
}

When it gets it, I register the listener (for orientation sensor):

public void startListening() {  
    sensorManager = (SensorManager) CONTEXT.getSystemService(Context.SENSOR_SERVICE);
    List<Sensor> sensors = sensorManager.getSensorList(Sensor.TYPE_ORIENTATION);
    if (sensors.size() > 0) {
        sensor = sensors.get(0);
        running = sensorManager.registerListener(sensorEventListener, sensor, SensorManager.SENSOR_DELAY_FASTEST);
    }
}   

And then, in the Listener's onSensorChanged() method:

public void onSensorChanged(SensorEvent event) {
    if(running) {   
        sensorManager.unregisterListener(this);
        // do some not significant stuff here
    }

And now the problem: I get a phone call, receiver starts, then listener starts and everything works as designed. But, later on, when I look at the battery stats, my app is listed as the one with 2-3% of drain. And this percentage is increasing even though there are no calls - hence the receiver is not working.

Where does this battery drain come from? The activity which starts the receiver is not working (and it is single checkbox anyway). I suppose, that the listener may not get unregistered by sensorManager.unregisterListener(this);, but it shoudl work - I unregister the listener when it received the first event, it makes sense.

How could I solve the problem?

回答1:

Where does this battery drain come from?

Never never never never never never never never have something in a manifest-registered BroadcastReceiver live beyond onReceive(). IOW, you cannot safely register a SensorListener from a manifest-registered BroadcastReceiver.

Please have your BroadcastReceiver delegate work to a Service (via startService()), where in onStartCommand() you register the SensorListener. When you get a sensor reading, or after a timeout (hint: phones don't always change orientation), or in onDestroy() (if Android decides to shut down your service), unregister the listener and call stopSelf() to shut down the service.