Android NDK Sensor奇怪的报告间隔到事件队列

Phi*_*hil 6 c++ java-native-interface android sensor android-ndk

我尝试从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);
}
Run Code Online (Sandbox Code Playgroud)

这就是我初始化一切的方式.我的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;
}
Run Code Online (Sandbox Code Playgroud)

sensorEvent此时是我使用的自定义结构.这个update方法每隔10秒就会通过JNI从Android调用一次IntentService(以确保它在应用程序本身被杀死时运行).现在我希望收到100个值(每秒10个*10秒).在不同的测试中,我收到了大约130个,对我来说也完全没问题,即使它有点偏.然后我在文档中读到ASensorEventQueue_setEventRate它没有被强制遵循给定的刷新周期.因此,如果我得到的比我想要的更多,那就完全没问题了.

但现在问题是:有时候我会在10秒钟内收到13个值,当我继续调用update10个秒后,我会得到130个值+之前运行的117个值.这完全随机发生,有时它不是下一次运行,而是第四次跟随或类似的事情.

通过拥有更多的价值,我可以完全摆脱刷新期.但有人可以解释为什么会发生这么多的值丢失并且它们会在下一次运行10秒后出现吗?或者有没有办法确保我在他们想要的运行中收到它们?

小智 0

您的代码是正确的,据我所知,只有一个原因可能导致这种行为。它是 Android 系统,为了避免耗尽电池,在应用程序进入后台或设备进入睡眠状态后的一段时间内降低加速度计事件流的频率。需要修改所有轴测相关逻辑,并根据 Doze和App Standby进行优化

您也可以尝试在前台服务中使用轴测仪。