Search code examples
androidandroid-intentbroadcastreceiveraccelerometer

Accelerometer seems to only work for a few seconds?


With this in the Android Manifest:

<receiver android:name=".OnBootReceiver">
    <intent-filter>
        <action android:name="android.intent.action.BOOT_COMPLETED" />
        <action android:name="android.intent.action.QUICKBOOT_POWERON" />
    </intent-filter>
</receiver>

And the following as OnBootReceiver.class:

package io.cordova.hellocordova;

import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.hardware.Sensor;
import android.hardware.SensorManager;

public class OnBootReceiver extends BroadcastReceiver {
    @Override
    public void onReceive(Context context, Intent intent) {
        SensorManager sManager = (SensorManager) context.getSystemService(Context.SENSOR_SERVICE);
        Sensor sensor = sManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
        sManager.registerListener(new ShakeEventManager(context), sensor, SensorManager.SENSOR_DELAY_NORMAL);
    }
}

And finally the following ShakeEventManager.class:

package io.cordova.hellocordova;

import android.content.Context;
import android.hardware.Sensor;
import android.hardware.SensorEvent;
import android.hardware.SensorEventListener;
import android.util.Log;

public class ShakeEventManager implements SensorEventListener {
    private Context mContext;

    public ShakeEventManager(Context context) {
        mContext = context;
    }

    @Override
    public void onSensorChanged(SensorEvent sensorEvent) {
        Log.i("testing", "Sensor changed");
    }

    @Override
    public void onAccuracyChanged(Sensor sensor, int accuracy) {

    }
}

Every time I reboot the phone, the "Sensor changed" output is logged repeatedly for a couple of seconds but then stops. It's as though something within Android is detecting an infinite loop and killing the app. Is that possible?

This is Android 5.1.1 on a Samsung Galaxy S6 Edge. Samsung bundle a battery saving system as standard but disabling this seems to have no effect.

Another thing I thought could be happening is that the two actions listed in my Manifest receiver block were conflicting, i.e. the first trigger was creating the listener and the second trigger then crashing it, but all of the examples I'm finding list both and removing either seems again to have no effect.

Any thoughts please?


Solution

  • This is taken from the Android Documentation on BroadcastReceiver.

    A BroadcastReceiver object is only valid for the duration of the call to onReceive(Context, Intent). Once your code returns from this function, the system considers the object to be finished and no longer active.

    This has important repercussions to what you can do in an onReceive(Context, Intent) implementation: anything that requires asynchronous operation is not available, because you will need to return from the function to handle the asynchronous operation, but at that point the BroadcastReceiver is no longer active and thus the system is free to kill its process before the asynchronous operation completes.

    That sounds like what is happening in your case. The BroadcastReceiver is no longer active so the system kills the process.

    To avoid this you can move the SensorChangedListener into a Service and then start the Service from inside the BroadcastReceiver. That way you will continue to receive the events.