Android NDK Sensor странный интервал отчета в очередь событий - PullRequest
0 голосов
/ 03 ноября 2018

Я пытаюсь получить доступ к акселерометру из NDK. Пока это работает. Но способ записи событий в очередь событий кажется немного странным.

См. Следующий код:

ASensorManager* AcquireASensorManagerInstance(void) {
    typedef ASensorManager *(*PF_GETINSTANCEFORPACKAGE)(const char *name);
    void* androidHandle = dlopen("libandroid.so", RTLD_NOW);
    PF_GETINSTANCEFORPACKAGE getInstanceForPackageFunc = (PF_GETINSTANCEFORPACKAGE) dlsym(androidHandle, "ASensorManager_getInstanceForPackage");
    if (getInstanceForPackageFunc) {
        return getInstanceForPackageFunc(kPackageName);
    }

    typedef ASensorManager *(*PF_GETINSTANCE)();
    PF_GETINSTANCE getInstanceFunc = (PF_GETINSTANCE) dlsym(androidHandle, "ASensorManager_getInstance");

    return getInstanceFunc();
}

void init() {
    sensorManager = AcquireASensorManagerInstance();
    accelerometer = ASensorManager_getDefaultSensor(sensorManager, ASENSOR_TYPE_ACCELEROMETER);

    looper = ALooper_prepare(ALOOPER_PREPARE_ALLOW_NON_CALLBACKS);

    accelerometerEventQueue = ASensorManager_createEventQueue(sensorManager, looper, LOOPER_ID_USER, NULL, NULL);

    auto status = ASensorEventQueue_enableSensor(accelerometerEventQueue,
                                                 accelerometer);
    status = ASensorEventQueue_setEventRate(accelerometerEventQueue,
                                            accelerometer,
                                            SENSOR_REFRESH_PERIOD_US);
}

Вот как я все инициализирую. Мой SENSOR_REFRESH_PERIOD_US - 100.000, поэтому 10 обновлений в секунду. Теперь у меня есть следующий метод для получения событий очереди событий.

vector<sensorEvent> update() {
    ALooper_pollAll(0, NULL, NULL, NULL);

    vector<sensorEvent> listEvents;
    ASensorEvent event;

    while (ASensorEventQueue_getEvents(accelerometerEventQueue, &event, 1) > 0) {
        listEvents.push_back(sensorEvent{event.acceleration.x, event.acceleration.y, event.acceleration.z, (long long) event.timestamp});
    }

    return listEvents;
}

sensorEvent на данный момент это пользовательская структура, которую я использую. Этот update метод вызывается через JNI из Android каждые 10 секунд из IntentService (чтобы убедиться, что он работает, даже если само приложение убито). Теперь я ожидаю получить 100 значений (10 в секунду * 10 секунд). В разных тестах я получил около 130, что также вполне нормально для меня, даже если немного. Затем я прочитал в документации ASensorEventQueue_setEventRate, что он не обязан следовать заданному периоду обновления. Так что, если бы я получил больше, чем хотел, все было бы прекрасно.

Но теперь проблема: иногда я получаю 13 значений за 10 секунд, а когда я продолжаю вызывать update 10 секунд спустя, я получаю 130 значений + пропущенные 117 прогонов до этого. Это происходит совершенно случайно, и иногда это не следующий прогон, а четвертый после или что-то в этом роде.

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

1 Ответ

0 голосов
/ 13 ноября 2018

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

Также вы можете попробовать работать с акселерометром в сервисе переднего плана.

...