Louen Ответов: 1

Датчики Android не собирают данные, когда телефон простаивает


Я пытаюсь разработать приложение для Android, в котором я собираю данные с нескольких датчиков (если они доступны на устройстве) и записываю их в файл, который позже будет проанализирован для определенных целей.
Я столкнулся с несколькими проблемами, незначительной, которую я могу игнорировать, и серьезной, которую я не смог решить и которая не позволяет приложению работать должным образом.

- Незначительная проблема

Я собираю данные с: акселерометра, линейного акселерометра, гироскопа и магнитометра, а также с GPS, но это работает совсем по-другому и может быть отобрано только на гораздо более низких частотах, поэтому я пока проигнорирую его.
Я собираю данные, реализуя прослушиватель для каждого датчика:

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);
            }
        }
    }


И я устанавливаю частоту ~50 Гц с помощью:

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


При сборе данных я понимаю, что частота не может быть стабильной на 100%, но странно то, что она остается более или менее стабильной на каждом датчике (около 50 Гц), за исключением акселерометра, где большую часть времени она дискретизируется на 100 Гц, а иногда падает до 50 Гц.

Есть ли что-то, что я могу сделать неправильно или как-то контролировать это? До сих пор это происходило в каждом устройстве, которое я пробовал, хотя они не все ведут себя точно так же.

- Серьезная проблема

Я записываю информацию в файл, сначала записывая все, что я получаю от датчиков, в строку, а затем каждые X секунд записываю то, что находится на строке, в файл и очищаю его, чтобы слушатели датчиков могли продолжать писать на нем, но это не становится бесконечно длинным.

Я пишу на струне вот так:

@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";
    }


А затем сохраните его в файл, используя это:

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, ""); 
        }


В прослушивателе каждый раз, когда я перестаю слушать, я устанавливаю “initTime” на -1, поэтому сэмплы всегда начинаются с 0 и доходят до продолжительности периода прослушивания в миллисекундах. (Не обращайте внимания на разделитель, это просто вопрос форматирования).

Моя главная проблема взлома приложений заключается в следующем:

В большинстве телефонов (несколько счастливчиков работают безупречно) 1 или 2 вещи терпят неудачу.

В некоторых случаях после некоторого простоя (например, запертые и в кармане) датчики перестают записывать данные, поэтому приложение просто записывает пустые значения, пока я снова не разбужу телефон.

В других случаях все еще хуже: не только датчики перестают записывать данные, но и таймер / запись в файл, похоже, тоже перестает работать, и когда телефон снова просыпается, он пытается написать то, что должен был написать, пока не работал, и путает все временные метки, записывая одни и те же образцы в разных точках “в прошлом”, пока не догонит текущее время. (Если вы визуализируете его в виде графика, он в основном выглядит так, как будто сбор данных переместился назад во времени).

Есть ли какой-нибудь способ, которым я могу убедиться, что приложение продолжает работать независимо от того, заблокирован ли телефон, дремлет ли приложение, свернуто ли оно на заднем плане, переднем плане и т. д.?

Я попробовал метод, который я погуглил, который состоит из установки и будильника, чтобы "разбудить процесс" каждые X секунд (независимо от того, какое время я установил на него, он работал максимум один раз в минуту).
Я видел, как в течение нескольких миллисекунд каждый раз, когда срабатывал будильник, он снова захватывал образцы, но затем сразу же засыпал, он не держал телефон "бодрствующим" в течение более длительного периода времени.
Это ничего не решало, и даже в течение короткого периода времени это заставляло датчики собирать данные, это только помогало разбудить датчики, проблема с таймером / записью в файл все еще сохранялась.

Надеюсь, кто-нибудь сможет пролить свет на то, как сохранить телефон, собирающий данные, несмотря ни на что, я перепробовал все, что мог придумать, и ничего не добился. Извините за кирпич текста, но я действительно не знал, как объяснить это короче.


P. S: Я видел, что наличие экономии заряда батареи сделало его еще хуже, даже на телефонах, где он обычно работал должным образом, он начал все портить. Так что еще один вопрос будет... Как я могу помешать ему вмешаться?

Что я уже пробовал:

Я пробовал запускать его на многих устройствах, и поведение среди них довольно противоречиво.

Gerry Schmitz

Если устройство "знает", что оно не "движется", почему оно должно пробовать с постоянной скоростью? Это имеет смысл с точки зрения энергосбережения.

Louen

Он не прекращает отбор проб, когда он не движется. Даже когда он движется, если он заблокирован, он не пробует.

Если бы это происходило только тогда, когда нет никакого движения, это было бы совершенно нормально для той цели, которую мы хотим ему дать, пока он все еще регистрировал новые записи в нашем "журнале". Если новая запись была пуста, мы могли бы просто повторить последнюю выборку записи.

1 Ответов

Рейтинг:
0

Richard MacCutchan

Это может быть связано с тем, что происходит с приложением при изменении состояния устройства. Видеть Понимание жизненного цикла деятельности  |  Разработчики Android[^]