重力センサーの有効化と取得方法
結論
Androidの重力センサーの有効化と値の取得は、公式サンプルコードのままではうまくいかない。
サンプル: native-activity | Android NDK | Android Developers
先に結論を書くと、以下の過程が必要
(※ASensorEventQueue_enableSensor()は必須だが、ASensorEventQueue_registerSensor()は任意)
//initialize sensors gSensors.gSensorManager = ASensorManager_getInstance(); gSensors.gSensorAccelerometer = ASensorManager_getDefaultSensor(gSensors.gSensorManager, ASENSOR_TYPE_ACCELEROMETER); gSensors.gSensorGravity = ASensorManager_getDefaultSensor(gSensors.gSensorManager, ASENSOR_TYPE_GRAVITY); gSensors.gSensorQueue = ASensorManager_createEventQueue(gSensors.gSensorManager, app->looper, LOOPER_ID_USER, NULL, NULL); __android_log_print(ANDROID_LOG_DEBUG, "register sensor test", std::to_string(ASensorEventQueue_registerSensor(gSensors.gSensorQueue, gSensors.gSensorAccelerometer, 10, 10)).c_str(), 0); __android_log_print(ANDROID_LOG_DEBUG, "register sensor test gravity", std::to_string(ASensorEventQueue_registerSensor(gSensors.gSensorQueue, gSensors.gSensorGravity, 10, 10)).c_str(), 0); __android_log_print(ANDROID_LOG_DEBUG, "sensor test", std::to_string(ASensorEventQueue_enableSensor(gSensors.gSensorQueue, gSensors.gSensorAccelerometer)).c_str(), 0); __android_log_print(ANDROID_LOG_DEBUG, "sensor test gravity", std::to_string(ASensorEventQueue_enableSensor(gSensors.gSensorQueue, gSensors.gSensorGravity)).c_str(), 0); //main loop part do { if ((ident = ALooper_pollAll(IsVulkanReady() ? 160 : -1, nullptr, &events, (void**)&source)) >= 0) { if (source != NULL) source->process(app, source); if(ident == LOOPER_ID_USER) { __android_log_print(ANDROID_LOG_DEBUG, "gravity event count in loop = ", std::to_string(ASensorEventQueue_hasEvents(gSensors.gSensorQueue)).c_str(), 0); while(ASensorEventQueue_getEvents(gSensors.gSensorQueue, tempSensorEvent, 1) > 0) { gravityData.x = tempSensorEvent->vector.x; gravityData.y = tempSensorEvent->vector.y; gravityData.z = tempSensorEvent->vector.z; __android_log_print(ANDROID_LOG_DEBUG, "gravity2 : ", (std::to_string(gravityData.x) + " " + std::to_string(gravityData.y) + " " + std::to_string(gravityData.z)).c_str(), 0); } } } __android_log_print(ANDROID_LOG_DEBUG, "gravity event count = ", std::to_string(ASensorEventQueue_hasEvents(gSensors.gSensorQueue)).c_str(), 0); // render if vulkan is ready if (IsVulkanReady()) { VulkanDrawFrame(currentFrame, isTouched, isFocused, touchPositions); currentFrame = (currentFrame + 1) % MAX_IN_FLIGHT; } } while (app->destroyRequested == 0);
Androidのセンサーについて
使えるセンサーの一覧などがまとめられている。
モーション センサー | Android デベロッパー | Android Developers
ただNDKの観点では書かれていないので、C++で実装したい場合には別にまとめられているページを参照する。
Androidセンサー NDK
NDKの関数などが書かれている。
Sensor | Android NDK | Android Developers
注意事項
- ASensorEventQueue_registerSensor()を用いる場合は、GradleのminSdkVersionが26以上であることが必要。
c++ - Android NDK undefined reference to ASensorEventQueue_registerSensor - Stack Overflow
The other possibility is that your minSdkVersion is lower than 26. ASensorEventQueue_registerSensor was not added until O, so it can't be linked unless your minSdkVersion is at least 26.
- includeファイルは<android/sensor.h>
雑感とか
まとめるとたったこれだけのことなのだが、公式のコードでうまく動かないので、たどり着くまでにかなり時間がかかってしまった。
本当はlooperなど、色々調べたことも残したいが、とりあえずはこれで良いか。
公式を参照した後に、このメモを見てサクッとセンサーが使える人が増えることを願っています。