Я разрабатываю приложение для моего последнего тезиса по информатике, и мне нужно собирать и регистрировать данные акселерометра. Мне нужно приобрести его целый день, поэтому существуют серьезные ограничения батареи (например, я не могу оставить экран включенным). Кроме того, это не приложение, ориентированное на рынок, поэтому вполне допустимо совершать серьезные хакерские и даже низкоуровневые C/С++-коды, если это необходимо.
Хорошо известно, что на многих устройствах слушатели событий акселерометра прекращают генерировать события при выключении экрана (некоторые ссылки на эту проблему: http://code.google.com/p/android/issues/detail?id=3708, Акселерометр останавливает доставку образцов, когда экран выключен на Droid/Nexus One даже с WakeLock). Я тщательно искал некоторые альтернативы, некоторые из них включают обходные пути, которые не работают на моем устройстве (LG P990, складское ROM).
Итак, что происходит: Когда вы регистрируете прослушиватель событий для датчика акселерометра андроида в Сервисе, он работает нормально до тех пор, пока экран не будет отключен. Я уже пытался зарегистрировать eventListener на службе, в IntentService, попытался приобрести WakeLocks. Что касается wakelocks, я могу проверить, что служба все еще работает, наблюдая за выходом LOGcat, но кажется, что акселерометр переведен в спящий режим. Одним из обходных решений, представленным в некоторых ссылках, является отмена регистрации и повторная регистрация прослушивателя событий периодически, используя поток IntentService, как в этом фрагменте кода ниже.
synchronized private static PowerManager.WakeLock getLock(Context context) {
if (lockStatic==null) {
PowerManager mgr=(PowerManager)context.getSystemService(Context.POWER_SERVICE);
lockStatic = mgr.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK,NAME);
lockStatic.setReferenceCounted(true);
}
return(lockStatic);
}
@Override
protected void onHandleIntent(Intent intent) {
sensorManager=(SensorManager) getSystemService(SENSOR_SERVICE);
sensorManager.unregisterListener(this);
sensorManager.registerListener(this, sensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER), SensorManager.SENSOR_DELAY_NORMAL);
synchronized (this) {
boolean run = true;
while (run){
try {
wait(1000);
getLock(AccelerometerService.this).acquire();
sensorManager=(SensorManager) getSystemService(SENSOR_SERVICE);
sensorManager.unregisterListener(this);
sensorManager.registerListener(this, sensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER), SensorManager.SENSOR_DELAY_NORMAL);
Log.d("Accelerometer service", "tick!");
} catch (Exception e) {
run = false;
Log.d("Accelerometer service", "interrupted; cause: " + e.getMessage());
}
}
}
}
@Override
public void onSensorChanged(SensorEvent event) {
Log.d("accelerometer event received", "xyz: "+ event.values[0] + "," + event.values[1] + "," + event.values[2]);
}
что действительно заставляет onSensorChange вызываться каждый раз, когда мы отменим регистрацию/регистрацию слушателя. Проблема в том, что полученное событие всегда содержит одни и те же значения, независимо от того, как я встряхиваю устройство.
Итак, в основном, мои вопросы: (медведь со мной, я почти заканчиваю: P)
-
Возможно ли получить доступ к низкоуровневому доступу (подход C/С++) к аппарату акселерометра БЕЗ регистрации на прослушиватель событий?
-
Есть ли другой способ обхода или взлома?
-
может ли кто-нибудь с более современным телефоном пройти тест, если проблема не исчезнет в прошивке 3.0 и выше?
[ОБНОВЛЕНИЕ]
К сожалению, это похоже на ошибку с некоторыми сотовыми телефонами. Подробнее в моем ответе.