2014-09-03 3 views
1

Я работаю над проектом, который хочет кратко отобразить датчики 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 
+0

По правде говоря, способность избегать ALooper вообще может быть еще приятнее. –

ответ

1

Эта часть

ALooper* looper = ALooper_forThread(); 
if (looper == NULL) 
    looper = ALooper_prepare(ALOOPER_PREPARE_ALLOW_NON_CALLBACKS); 

может быть упрощено до

ALooper* looper = ALooper_prepare(ALOOPER_PREPARE_ALLOW_NON_CALLBACKS); 

как ALooper_prepare возвращает петлителя, связанных с Чет ead, если он существует, в соответствии с документом в looper.h Это может даже решить вашу проблему b/c, это может изменить петлитель, чтобы он допускал не-обратные вызовы, но я не уверен.

Несмотря на то, что вы должны полностью контролировать петлитель самостоятельно, то есть если петлеучет уже опрошен где-то в другом месте, я думаю, что вы не можете опросить один и тот же петлитель самостоятельно, не вмешиваясь. Поэтому либо вы модифицируете петлитель в android_native_app_glue, либо напишите новый петлитель, в новую тему. Это мое понимание.

Смежные вопросы