Я работаю над проектом, который хочет кратко отобразить датчики Android. Здесь коротко около 200-400 миллисекунд (это примерно мгновение ока, буквально).Создать петлитель для датчиков без обратных вызовов?
Я хочу избежать асинхронности Android и использовать ALooper_pollOnce
или ALooper_pollAll
. Избегание этого упрощает программирование и аудит, потому что я могу использовать лестничную диаграмму, а не конечный автомат для моделирования системы. И время настолько кратковременно, что на практике это не должно быть проблемой.
Следующий код:
#include "android_native_app_glue.h"
...
// Should be defined in app_glue
#ifndef LOOPER_ID_USER
# define LOOPER_ID_USER 3
#endif
...
static const int LOOPER_ID_PRNG = LOOPER_ID_USER + 1;
...
ALooper* looper = ALooper_forThread();
if (looper == NULL)
looper = ALooper_prepare(ALOOPER_PREPARE_ALLOW_NON_CALLBACKS);
...
ASensorEventQueue* queue = ASensorManager_createEventQueue(sensorManager,
looper, LOOPER_ID_PRNG, NULL /*SensorEvent*/,
reinterpret_cast<void*>(&context));
Вызывает следующую ошибку в LogCat:
09-03 01:30:00.100: E/Looper(4026): Invalid attempt to set NULL callback but not
allowed for this looper.
Как я могу создать петлитель, что позволяет опрашивать? Или, если существует петлитель, как мне его изменить, чтобы разрешить опрос?
struct Sensor {
Sensor() :
m_type(-1), m_sensor(NULL) {
}
explicit Sensor(int type, string name, const ASensor* sensor) :
m_type(type), m_name(name), m_sensor(sensor) {
}
int m_type;
string m_name;
const ASensor* m_sensor;
};
typedef vector<Sensor> SensorList;
И:
static SensorList s_list;
// Double checked initialization omitted
ASensorList sensorList;
ASensorManager* sensorManager = ASensorManager_getInstance();
int n = ASensorManager_getSensorList(sensorManager, &sensorList);
if(n < 0)
{
LOG_ERROR("SensorList: failed to retrieve list");
}
else if (n == 0)
{
LOG_DEBUG("SensorList: no sensors available");
}
else
{
s_list.reserve(static_cast<size_t>(n));
for (int i = 0; i < n; i++)
{
const ASensor* sensor = sensorList[i];
if (sensor == NULL)
continue;
const char* name = ASensor_getName(sensor);
const char* vendor = ASensor_getVendor(sensor);
int type = ASensor_getType(sensor);
int min_delay = ASensor_getMinDelay(sensor);
float resolution = ASensor_getResolution(sensor);
LOG_DEBUG("SensorList: %s (%s) %d %d %f", name, vendor, type, min_delay, resolution);
// These sensors require callbacks. Avoid them for simplicity.
if (type == ASENSOR_TYPE_LIGHT || min_delay == 0)
continue;
s_list.push_back(Sensor(type, name, sensor));
}
}
Ниже, датчик освещенности требует обратного вызова, потому что его min_delay
0. Он не был добавлен в SensorList
. Другие датчики были добавлены к SensorList
.
Выход был создан с помощью этой линии:
LOG_DEBUG("SensorList: %s (%s) %d %d %f", name, vendor, type, min_delay, resolution);
D/PRNG (3950): SensorList: MPL rotation vector (Invensense) 11 20000 1.000000
D/PRNG (3950): SensorList: MPL linear accel (Invensense) 10 20000 1.000000
D/PRNG (3950): SensorList: MPL gravity (Invensense) 9 20000 1.000000
D/PRNG (3950): SensorList: MPL Gyro (Invensense) 4 20000 1.000000
D/PRNG (3950): SensorList: MPL accel (Invensense) 1 20000 1.000000
D/PRNG (3950): SensorList: MPL magnetic field (Invensense) 2 20000 1.000000
D/PRNG (3950): SensorList: MPL Orientation (Invensense) 3 20000 1.000000
D/PRNG (3950): SensorList: Lite-On al3000a Ambient Light Sensor (Lite-On) 5 0 1.000000
D/PRNG (3950): SensorList: added 7 sensors
По правде говоря, способность избегать ALooper вообще может быть еще приятнее. –