Click here to Skip to main content
14,601,122 members
Rate this:
Please Sign up or sign in to vote.
See more:
I’m trying to develop an app for Android in which I pick up data from several sensors (if available on the device) and write it down to a file which will later be analyzed for certain uses.
I’m facing several problems, a minor one which I can kind of ignore and a major one that I haven’t been able to solve and makes the app not work properly.

- Minor problem

I’m gathering data from: Accelerometer, Linear Accelerometer, Gyroscope and Magnetometer and also from the GPS but that works quite differently and can only be sampled at much lower frequencies, so I’ll ignore it for now.
I gather the data by implementing a listener for each sensor:

public class AccelerometerWatcher implements SensorEventListener 
    {
        private SensorManager sm;
        private Sensor accelerometer;
    
        AccelerometerWatcher(Context context) {
    
            sm = (SensorManager)context.getSystemService(Context.SENSOR_SERVICE);
    
            assert sm != null;
            if (sm.getDefaultSensor(Sensor.TYPE_ACCELEROMETER) != null) {
                accelerometer = sm.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
            }
        }
    }


And I’m setting the frequency to ~50Hz by using:

sm.registerListener(this, accelerometer, SensorManager.SENSOR_DELAY_GAME);


When gathering data, I understand the frequency can’t be 100% stable, but the weird thing is it stays more or less stable on every sensor (at around 50Hz) except on the Accelerometer, where most of the time it samples at 100Hz and sometimes drops down to 50Hz.

Is there something I might be doing wrong or any way to control this? So far it’s happened in every device I tried, although they don’t all behave in exactly the same way.

- Major problem

I’m writing down the info to a file by first writing everything I pick up from the sensors to a string and then every X seconds, writing what’s on the string to a file and clearing it so the sensor listeners can keep on writing on it but it doesn’t become infinitely long.

I write on the string like this:

@Override
        public void onSensorChanged(SensorEvent event) {
    
            if (event.sensor.getType() != Sensor.TYPE_ACCELEROMETER)
                return;
    
    
                if(initTime == -1)
                    initTime = event.timestamp;
    
                MyConfig.SENSOR_ACCEL_READINGS += ((event.timestamp - initTime) / 1000000L) + MyConfig.DELIMITER + event.values[0] + MyConfig.DELIMITER + event.values[1] + MyConfig.DELIMITER + event.values[2] + "\n";
    }


And then save it to a file using this:

public class Utils {
    
        private static Timer timer;
        private static TimerTask timerTask;
    
        public static void startRecording() {
            timer = new Timer();
            timerTask = new TimerTask()
            {
                @Override
                public void run()
                {
                    // THIS CODE RUNS EVERY x SECONDS
                    writeDataToFile();
                }
            };
            timer.scheduleAtFixedRate(timerTask, 0, MyConfig.SAVE_TIMER_PERIOD);
        }
    
        public static void stopRecording()
        {
            if(timer != null)
                timer.cancel();
            if(timerTask != null)
                timerTask.cancel();
    
            writeDataToFile();
        }
    
        private static void writeDataToFile()
        {
            String temp_accel = String.copyValueOf(MyConfig.SENSOR_ACCEL_READINGS.toCharArray());
            WriteData.write(MyConfig.RECORDING_FOLDER, MyConfig.FILENAME_ACCEL, temp_accel);
            MyConfig.SENSOR_ACCEL_READINGS = MyConfig.SENSOR_ACCEL_READINGS.replaceFirst(temp_accel, ""); 
        }


In the listener, every time I stop listening, I set “initTime” to -1 so the samples always start at 0 and go up to the duration of the listening period in miliseconds. (Ignore the DELIMITER it’s just a matter of formatting).

My main app-breaking problem, is the following:

In most phones (a few lucky ones work flawlessly) 1 or 2 things fail.

In some, after being idle for a while (locked and in your pocket for example) the sensors stop recording data so the app just writes blank values until I wake the phone up again.

In others, it’s even worse, not only do the sensors stop recording data, but the timer / writing to file, seems to stop working too, and when the phone wakes up again, it tries to write what it should’ve written while it wasn’t working and messes up all the timestamps, writing the same samples at different points “in the past” until it catches up to the current time. (If you visualize it as a graph, it basically looks as if the data gathering travelled back in time).

Is there any way in which I can make sure that the app keeps on working no matter what, whether the phone is locked, dozing, the app is minimized, on the background, foreground, etc.?

I tried a method I googled that consists of setting and alarm to "wake up the process" every X seconds (no matter what time I set to it, it only worked max once per minute).
I saw how for a few miliseconds every time the alarm went off, it captured samples again but then went to sleep right away, it didn't keep the phone "awake" for a longer period of time.
It solved nothing and even for the brief period it forced the sensors to gather data, it only helped wake up the sensors, the problem with the timer / writing to file still persisted.

Hope someone can shed some light on how to keep the phone gathering data no matter what, I've been trying everything I could think of and I'm not getting anywhere. Sorry for the brick of text, but I didn't really know how to explain it in a shorter way.


P.S: I saw that having the Battery Saver ON made it even worse, even on the phones where it usually worked properly, it started messing things up. So another question would be... How can I stop it from interfering?

What I have tried:

I've tried running it on many devices and the behaviour is quite inconsistent amongst them.
Posted
Updated 10-Feb-20 2:23am
Comments
Gerry Schmitz 10-Feb-20 8:01am
   
If the device "knows" it's not "moving", why should it sample at a constant rate? Makes sense from a power saving point of view.
Louen 10-Feb-20 8:17am
   
It doesn't stop sampling when it's not moving. Even when it moves, if it's locked, it doesn't sample.

If it only happened when there's no movement it would be totally fine for the purpose we wanna give it, as long as it still registered new entries in our "log". If the new entry came empty, we could just repeat the last sampled entry.

1 solution

Rate this:
Please Sign up or sign in to vote.

Solution 1

It may be connected to what happens to app when the device status changes. See Understand the Activity Lifecycle  |  Android Developers[^]
   

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)




CodeProject, 503-250 Ferrand Drive Toronto Ontario, M3C 3G8 Canada +1 416-849-8900 x 100