Search code examples
javaandroidserviceandroid-serviceondestroy

Android accelerometer logging service stops working and onDestroy is not being called


I am trying to create a service which should log accelerometer values and timestamp on disk as fast as possible.

It works fine as long as the Activity is present, but the problem is as soon as I quit the Activity which this service is coming with, the service stops. I put a toast in onCreate, onStartCommand and onDestroy, for first two, it works normally but it never shows anything on onDestroy so I am clue less what is the cause. I also put breakpoints in Android Studio on onDestroy but it does not fire too.

Here is the complete code, please let me know what you think can be the problem:

package com.embedonix.mobilehealth.services.accelerometerlog;

import android.app.Service;
import android.content.Context;
import android.content.Intent;
import android.hardware.Sensor;
import android.hardware.SensorEvent;
import android.hardware.SensorEventListener;
import android.hardware.SensorManager;
import android.os.Environment;
import android.os.IBinder;
import android.widget.Toast;

import com.embedonix.mobilehealth.AppConstants;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class AccelerometerLogService extends Service {

    private boolean mIsServiceStarted = false;
    private Context mContext = null;
    private SensorManager mSensorManager = null;
    private Sensor mSensor;
    private File mLogFile = null;
    private FileOutputStream mFileStream = null;
    private AccelerometerLogService mReference = null;
    private Float[] mValues = null;
    private long mTimeStamp = 0;
    private ExecutorService mExecutor = null;

    /**
     * Default empty constructor needed by Android OS
     */
    public AccelerometerLogService() {
        super();
    }

    /**
     * Constructor which takes context as argument
     *
     * @param context
     */
    public AccelerometerLogService(Context context) {
        super();

        if (context != null)
            mContext = context;
        else
            mContext = getBaseContext();
    }

    @Override
    public void onCreate() {
        super.onCreate();

        Toast.makeText(getBaseContext(), "Service onCreate", Toast.LENGTH_SHORT).show();
    }

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

        if (isServiceStarted() == false) {

            mContext = getBaseContext();
            mReference = this;
            mSensorManager = (SensorManager) mContext.getSystemService(Context.SENSOR_SERVICE);
            mSensor = mSensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
            mValues = new Float[]{0f, 0f, 0f};
            mTimeStamp = 0;
            mExecutor = Executors.newSingleThreadExecutor();

            setupFolderAndFile();
            startLogging();
        }

        //set started to true
        mIsServiceStarted = true;


        Toast.makeText(mContext, "Service onStartCommand", Toast.LENGTH_SHORT).show();
        return Service.START_STICKY;
    }

    private void setupFolderAndFile() {
        mLogFile = new File(Environment.getExternalStorageDirectory().toString()
                + "/" + AppConstants.APP_LOG_FOLDER_NAME + "/test.txt");

        try {
            mFileStream = new FileOutputStream(mLogFile, true);
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        }
    }

    private void startLogging() {

        mExecutor.execute(new Runnable() {
            @Override
            public void run() {
                mSensorManager.registerListener(
                        new SensorEventListener() {
                            @Override
                            public void onSensorChanged(SensorEvent sensorEvent) {
                                mTimeStamp = System.currentTimeMillis();
                                mValues[0] = sensorEvent.values[0];
                                mValues[1] = sensorEvent.values[1];
                                mValues[2] = sensorEvent.values[2];

                                String formatted = String.valueOf(mTimeStamp)
                                        + "\t" + String.valueOf(mValues[0])
                                        + "\t" + String.valueOf(mValues[1])
                                        + "\t" + String.valueOf(mValues[2])
                                        + "\r\n";

                                try {
                                    mFileStream.write(formatted.getBytes());
                                } catch (IOException e) {
                                    e.printStackTrace();
                                }
                            }

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

                            }
                        }, mSensor, SensorManager.SENSOR_DELAY_FASTEST
                );
            }
        });
    }

    @Override
    public void onDestroy() {
        super.onDestroy();

        //Flush and close file stream
        if (mFileStream != null) {
            try {
                mFileStream.flush();
            } catch (IOException e) {
                e.printStackTrace();
            }
            try {
                mFileStream.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }

        Toast.makeText(mContext, "Service onDestroy", Toast.LENGTH_LONG).show();
        mIsServiceStarted = false;
    }

    @Override
    public IBinder onBind(Intent intent) {
        return null;
    }

    /**
     * Indicates if service is already started or not
     *
     * @return
     */
    public boolean isServiceStarted() {
        return mIsServiceStarted;
    }
}

UPDATE 1

I found out that this happens on Nexus 7 tablet. The same code works fine on my phone, MotoG. Both devices have Android 4.4.2 installed....what can be the reason?


Solution

  • None of the above are the answer. Unfortunately this is a known problem with Nexus 7 and propably Nexus 5 products of Google.

    Here is the link to the bugreport (although I think its an intentional feautur!!!)

    https://code.google.com/p/android/issues/detail?id=63793