0

I want to use the accelerometer sensor to keep track when a user makes sudden moves.

This service should be started via activity and keep running indefinitely even if application is terminated (exits). Currently everything works fine while app is alive, once the app closed, i can still see the service runs but i don't get any signals from him anymore. Can someone help keep the service alive with signals?

Please look at the code i have.

MainActivity.java

public class MainActivity extends ActionBarActivity implements CordovaInterface {
private boolean mAlternateTitle = false;
private boolean bound;
private boolean volumeupBound;
private boolean volumedownBound;

String TAG = "MainActivity-ActionBarTest";
private IPlugin activityResultCallback;
private Object activityResultKeepRunning;
private Object keepRunning;

CordovaWebView mainView;

public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.main);

    //startService(new Intent(getBaseContext(), FirstService.class));
    startService(new Intent(getApplicationContext(), MainAccelerometer.class));

    mainView = (CordovaWebView) findViewById(R.id.mainView);
    mainView.loadUrl("file:///android_asset/www/index.html");
}

MainAccelerometer.java

    public class MainAccelerometer extends Service implements AccelerometerListener{

    public int onStartCommand(Intent intent, int flags, int startId) {

        return START_NOT_STICKY;
    }

    public IBinder onBind(Intent arg0) 
    {
          return null;
    }

    public void onCreate() {
        super.onCreate();
        //Check device supported Accelerometer senssor or not
        if (AccelerometerManager.isSupported(getApplicationContext())) {

            //Start Accelerometer Listening
            AccelerometerManager.startListening(this);
        }
    }



    public void onAccelerationChanged(float x, float y, float z) {
        // TODO Auto-generated method stub
    }

    public void onShake(float force) {

        // Called when Motion Detected
        //Toast.makeText(getBaseContext(), "Motion detected", Toast.LENGTH_SHORT).show();
        Log.d("Test", "shake");
    }


    @Override
    public void onDestroy() {
        super.onDestroy();
        Log.i("Sensor", "Service  distroy");

        //Check device supported Accelerometer senssor or not
        if (AccelerometerManager.isListening()) {

            //Start Accelerometer Listening
            AccelerometerManager.stopListening();

            //Toast.makeText(getBaseContext(), "onDestroy Accelerometer Stoped", Toast.LENGTH_LONG).show();
        }
    }
}

AccelerometerManager.java

    public class AccelerometerManager {

    private static Context aContext=null;


    /** Accuracy configuration */
    private static float threshold  = 20.0f; 
    private static int interval     = 2000;

    private static Sensor sensor;
    private static SensorManager sensorManager;
    // you could use an OrientationListener array instead
    // if you plans to use more than one listener
    private static AccelerometerListener listener;

    /** indicates whether or not Accelerometer Sensor is supported */
    private static Boolean supported;
    /** indicates whether or not Accelerometer Sensor is running */
    private static boolean running = false;

    /**
     * Returns true if the manager is listening to orientation changes
     */
    public static boolean isListening() {
        return running;
    }

    /**
     * Unregisters listeners
     */
    public static void stopListening() {
        running = false;
        try {
            if (sensorManager != null && sensorEventListener != null) {
                sensorManager.unregisterListener(sensorEventListener);
            }
        } catch (Exception e) {}
    }

    /**
     * Returns true if at least one Accelerometer sensor is available
     */
    public static boolean isSupported(Context context) {
        aContext = context;
        if (supported == null) {
            if (aContext != null) {


                sensorManager = (SensorManager) aContext.
                        getSystemService(Context.SENSOR_SERVICE);

                // Get all sensors in device
                List<Sensor> sensors = sensorManager.getSensorList(
                        Sensor.TYPE_ACCELEROMETER);

                supported = new Boolean(sensors.size() > 0);



            } else {
                supported = Boolean.FALSE;
            }
        }
        return supported;
    }

    /**
     * Configure the listener for shaking
     * @param threshold
     *             minimum acceleration variation for considering shaking
     * @param interval
     *             minimum interval between to shake events
     */
    public static void configure(int threshold, int interval) {
        AccelerometerManager.threshold = threshold;
        AccelerometerManager.interval = interval;
    }

    /**
     * Registers a listener and start listening
     * @param accelerometerListener
     *             callback for accelerometer events
     */
    public static void startListening( AccelerometerListener accelerometerListener ) 
    {

        sensorManager = (SensorManager) aContext.
                getSystemService(Context.SENSOR_SERVICE);

        // Take all sensors in device
        List<Sensor> sensors = sensorManager.getSensorList(
                Sensor.TYPE_ACCELEROMETER);

        if (sensors.size() > 0) {

            sensor = sensors.get(0);

            // Register Accelerometer Listener
            running = sensorManager.registerListener(
                    sensorEventListener, sensor, 
                    SensorManager.SENSOR_DELAY_GAME);

            listener = accelerometerListener;
        }


    }

    /**
     * Configures threshold and interval
     * And registers a listener and start listening
     * @param accelerometerListener
     *             callback for accelerometer events
     * @param threshold
     *             minimum acceleration variation for considering shaking
     * @param interval
     *             minimum interval between to shake events
     */
    public static void startListening(
            AccelerometerListener accelerometerListener, 
            int threshold, int interval) {
        configure(threshold, interval);
        startListening(accelerometerListener);
    }

    /**
     * The listener that listen to events from the accelerometer listener
     */
    private static SensorEventListener sensorEventListener = 
        new SensorEventListener() {

        private long now = 0;
        private long timeDiff = 0;
        private long lastUpdate = 0;
        private long lastShake = 0;

        private float x = 0;
        private float y = 0;
        private float z = 0;
        private float lastX = 0;
        private float lastY = 0;
        private float lastZ = 0;
        private float force = 0;

        public void onAccuracyChanged(Sensor sensor, int accuracy) {}

        public void onSensorChanged(SensorEvent event) {
            // use the event timestamp as reference
            // so the manager precision won't depends 
            // on the AccelerometerListener implementation
            // processing time
            now = event.timestamp;

            x = event.values[0];
            y = event.values[1];
            z = event.values[2];

            // if not interesting in shake events
            // just remove the whole if then else block
            if (lastUpdate == 0) {
                lastUpdate = now;
                lastShake = now;
                lastX = x;
                lastY = y;
                lastZ = z;
                Toast.makeText(aContext,"No Motion detected", Toast.LENGTH_SHORT).show();

            } else {
                timeDiff = now - lastUpdate;

                if (timeDiff > 0) { 

                    /*force = Math.abs(x + y + z - lastX - lastY - lastZ) 
                                / timeDiff;*/ 
                    //force = Math.abs(x + y + z - lastX - lastY - lastZ);
                    force = Math.abs(x - lastX);

                    if (Float.compare(force, threshold) >0 ) {
                        //Toast.makeText(Accelerometer.getContext(), (now-lastShake)+"  >= "+interval, 1000).show();
                        if (now - lastShake >= interval) { 

                            // trigger shake event
                            listener.onShake(force);
                        }
                        else
                        {
                            //Toast.makeText(aContext,"No Motion detected", Toast.LENGTH_SHORT).show();

                        }
                        lastShake = now;
                    }
                    lastX = x;
                    lastY = y;
                    lastZ = z;
                    lastUpdate = now; 
                }
                else
                {
                    //Toast.makeText(aContext,"No Motion detected", Toast.LENGTH_SHORT).show();

                }
            }
            // trigger change event
            listener.onAccelerationChanged(x, y, z);
        }

    };

}

AccelerometerListener.java

public interface AccelerometerListener {

public void onAccelerationChanged(float x, float y, float z);

public void onShake(float force);


}
Harshad Pansuriya
  • 20,189
  • 8
  • 67
  • 95
elimiz
  • 1
  • Try returning `START_STICKY` instead of `START_NOT_STICKY`. Also you should possibly call [`startForeground`](http://developer.android.com/reference/android/app/Service.html) for your service to eliminate a chance the system will unload your service on its own. – Stan Dec 30 '13 at 13:00
  • switched to `START_STICKY` didn't seems to do a lot. – elimiz Dec 30 '13 at 13:14
  • `startForeground` did the work but also kept my app alive. When i check the running apps i can see: 1 proccess and 1 service. Basically i want to see: 0 process and 1 service. – elimiz Dec 30 '13 at 13:21
  • You can't do that. The service is running in the same process. You can destroy the activity though. – Stan Dec 30 '13 at 13:21
  • I have modified the androidManifest.xml so that the service will use seperate proccess: `` Still it doesn't help. – elimiz Dec 30 '13 at 13:52
  • What do you mean "doesn't help"? You can't have a service without a process for running it. So you'll always see 1 process and 1 service as minimum statistics for a background service. There can't be 0 processes. Otherwise you'll have 0 services as well, that is no service. – Stan Dec 30 '13 at 18:02
  • So if i open my app, and from there i call my service (with it's own process), would i expect to see: 2 process and 1 service on the running apps? Currently i see: 1 process and 1 service even though the have separate processes. – elimiz Dec 31 '13 at 06:53
  • I think this may be related to the fact that the additional process is private. Try removing the colon in front of process name. Though this may require specific permissions. – Stan Jan 01 '14 at 11:05

0 Answers0