Akcelerometr Androida nie działa, gdy ekran jest wyłączony

Opracowuję aplikację do mojej pracy dyplomowej z informatyki, i muszę zbierać i rejestrować dane z akcelerometru. Muszę go nabyć przez cały dzień, więc są poważne ograniczenia baterii (na przykład, nie mogę zostawić ekran włączony). Ponadto, nie jest to aplikacja ukierunkowana na rynek, więc jest całkiem dopuszczalne, aby zrobić kilka poważnych hacking, nawet niskiego poziomu C/C++ kodowania, jeśli jest to wymagane.

Wiadomo, że na wielu urządzeniach słuchacze zdarzeń akcelerometru zatrzymują generowanie zdarzeń po wyłączeniu ekranu (Niektóre linki dotyczące tego problemu: http://code.google.com/p/android/issues/detail?id=3708 , Akcelerometr przestaje dostarczać próbki, gdy ekran jest wyłączony na Droid/Nexus One, nawet przy użyciu Wakelocka [5]). Dokładnie Szukałem alternatyw, niektóre z nich zawierają obejścia, które nie działają na moje urządzenie (LG P990, stock ROM).

Więc to, co się dzieje, to: Po zarejestrowaniu słuchacza zdarzeń dla czujnika akcelerometru android w usłudze działa dobrze, dopóki ekran nie zostanie wyłączony. Próbowałem już zarejestrować eventListener w Serwisie, na IntentService, próbowałem nabyć WakeLocks. Jeśli chodzi o wakelocks, mogę sprawdzić, czy usługa nadal działa obserwując wyjście LOGcat, ale wydaje się, że akcelerometr jest w trybie uśpienia. Jednym z obejść przedstawionych w niektórych linkach jest okresowe wyrejestrowanie i ponowne zarejestrowanie słuchacza zdarzeń za pomocą wątku Usługi IntentService, takiego jak w tym kodzie snippet bellow

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]);
}

Co rzeczywiście sprawia, że onSensorChange jest wywoływany za każdym razem, gdy wyrejestrujemy / zarejestrujemy słuchacza. Problem polega na tym, że odebrane zdarzenie zawiera zawsze te same wartości, niezależnie od tego, czy potrząsam urządzeniem.

Więc w zasadzie moje pytania to: (bear with me, I ' m almost finishing :P)

  1. Czy możliwy jest dostęp niskiego poziomu (podejście C/C++) do sprzętu akcelerometru bez rejestracji zdarzenia słuchacz?

  2. Czy Jest jakieś inne obejście lub włamanie?

  3. Czy ktoś z bardziej aktualnym telefonem mógłby sprawdzić czy problem utrzymuje się w firmware 3.0 i nowszych?

[UPDATE]

Niestety, wydaje się, że jest to błąd z niektórymi telefonami komórkowymi. Więcej szczegółów w mojej odpowiedzi.

Author: Community, 2012-04-02

6 answers

Zasadniczo jest to problem z moim telefonem. Inni użytkownicy zgłaszali, że dzieje się to również z ich telefonami, z różnych marek, ale tej samej wersji Androida. Inne osoby nie mają żadnego problemu - mocno wskazując, że nie jest to problem z wersją zapasową Androida, ale z implementacji każdej firmy dla swoich sterowników sprzętowych.

Potrzebuję stałych danych akcelerometru i nie mogę mieć klucza mierzącego te dane dla mnie-mam Arduino z Bluetooth i akcelerometr, więc mogłem wdrożyć to rozwiązanie. Postanowiłem więc, że tymczasowym rozwiązaniem dla mojego telefonu komórkowego jest włączenie ekranu (przyciemnione) i zignorowanie zużycia baterii. Później przeprowadzę testy zużycia baterii za pomocą innego telefonu z Androidem, który działa z wyłączonym ekranem.

Więcej informacji o błędzie

Zbadałem trochę więcej i znalazłem raporty od innych użytkowników Androida i myślę, że może rozumiem, co się dzieje. Biblioteka libsensors.so który ma sterowniki do czujników telefonu nie jest rozwijany przez Google, ale przez każdego dostawcę telefonów komórkowych-oczywiście, ponieważ każdy telefon ma swój własny specyficzny sprzęt. Google udostępnia tylko plik nagłówkowy C, aby Programiści wiedzieli, co mają do wdrożenia. W niektórych implementacjach tych sterowników Programiści po prostu wyłączają akcelerometr, gdy ekran gaśnie, zapobiegając w ten sposób odbieraniu nowych zdarzeń przez odbiornik zdarzeń czujnika.

Testowałem też to z CyanogenMod RC7. 2 ale też nie zadziałał, bo sterowniki akcelerometru są oryginalne od LG.

E-maile wymieniane z działem HR LG

Wysłałem maila do twórców LG P990 i w końcu dostałem konkretne odpowiedzi! Może to być bardzo pomocne dla niektórych osób takich jak ja, które doświadczają tych problemów z Androidem. Napisałem następujące pytanie

Witam! Rozwijam pracę magisterską z informatyki i obecnie am pobieranie danych ze sprzętu akcelerometru. Od teraz, dowiedziałem się że akcelerometry nie wysyłają zdarzeń, gdy ekran jest wyłączony, więc nawet gdy łapię wakelocka z jednego z moich programów, mogę sprawdź, czy mój program nadal działa (poprzez wyjście LOGcat), ale nie pojawia się akcelerometr. Muszę przyciemnić ekran (który nie stać, bateria rozładowuje się zbyt szybko), aby zacząć odbierać znowu zdarzenia akcelerometru. Próbowałem też uzyskać dostęp przez natywne C kod, rejestracja na zdarzenia akcelerometru, ale wynik był podobnie, akcelerometr nie rzucał żadnych wartości, mimo że byłem obracam moje urządzenie. Zastanawiałem się, czy mogę mieć bezpośredni dostęp. do sprzętu, z natywnym kodem, bez konieczności rejestracji do słuchacz. Czy to możliwe? Jeśli tak, czy mógłby Pan uprzejmie podać dalsze Rady? Byłbym wdzięczny za każdą pomoc! Martin

Za to co otrzymałem odpowiedź:

Drogi Martinie, otrzymaliśmy odpowiedź od Dev. Drużynowo Powiedzieli, że ty nie można uzyskać zdarzenia akcelerometru, gdy ekran telefonu jest wyłączony. Ponieważ Warstwa HAL nie zaimplementowała ścieżki sysFS, aby uzyskać Zdarzenie H / w, takie jak akcelerometr i nie ma publicznego API, aby uzyskać Zdarzenie. Dziękuję. Najlepsze Pozdrawiam. (Sean Kim)

Następnie wysłałem e-mail z powrotem, mówiąc między innymi, że uznałem to za błąd, ponieważ powinno się mieć dostęp do całego sprzętu podczas uzyskiwania wake lock:

[...] Zadałem to pytanie, ponieważ Mam przyjaciół, którzy również mają Telefony z Androidem w tej samej wersji gingerbread ale z innych marki telefonów komórkowych, a część z nich zgłosiła, że odbierają wydarzenia z akcelerometry po wyłączeniu ekranu. Czytałem na niektórych forum, że ten błąd-uważam go za błąd, od kiedy nabywam Wakelock spodziewałbym się, że będzie jakieś przetwarzanie-zależy od sterowniki czujników, które dostawcy wdrażają do swoich telefonów komórkowych. Na istnieje możliwość, że te sterowniki może być aktualizowana lub będzie to błąd zostanie poprawiony w pewnym momencie? To by mi ogromnie pomogło z moim prace w toku [...]

I wtedy otrzymałem odpowiedź:

Z mojej wiedzy od Dev. Drużyno, to nie jest bug. To jest nieograniczone ten telefon ze względu na architekturę H/W. Musimy przeprojektować HAL architektura i sterownik urządzenia do obsługi Twojego żądania. Ale, jak ty wiedz, że jest to zbyt trudne z powodu braku zasobów. Staramy się pomóc ci z naszych wszystkich wysiłki, ale nie możemy poprzeć TWOJEJ prośby, ponieważ wspominany. (Sean Kim)

Więc najwyraźniej wiedzą o tym, ale nie próbują tego poprawić, ponieważ albo nie uważają, że jest to błąd - który nadal mocno wierzę, że jest logiczną wadą-albo nie mają czasu/zasobów, aby go poprawić.

Bottom line Jeśli masz telefon komórkowy, który nie wysyła zdarzeń akcelerometru z wyłączonym ekranem, spróbuj zaktualizować oprogramowanie układowe. Jeśli to nie rozwiąże i naprawdę chcesz aby zrobić jakiś poważny hacking, ponownie zaimplementować warstwę sprzętową-podpowiedź: to prawdopodobnie ma coś wspólnego z libsensors.so.

 62
Author: martin,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-05-07 22:12:55

Nie jestem pewien, czy to rzeczywiście pomoże ci, ale znalazłem obejście (Nie wiem, jak dobrze, jeśli pomoże to oszczędzać baterię).

Używając Basha mam pętlę while cat-ing /sys/devices/virtual/accelerometer/accelerometer/acc_file, a po wyłączeniu ekranu za pomocą przycisku zasilania wyjście jest kontynuowane, ale jest zamrożone. (Miałem SSHD uruchomiony w chroot stąd jest w stanie go zobaczyć.)

Jednak w ECHA 0 > /sys/devices/platform/msm_fb.196609/leds/lcd-backlight/brightness. Ekran wyłącza się, a wyjście jest ciągłe.

To jest na SGH-T589W, z systemem android wersja 2.3.6.
 6
Author: fu-fu,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-05-07 22:14:03

Zastosowałem PARTIAL_WAKE_LOCK i zadziałało jak urok dla mnie. Testowane na OS 5.0, 6.0 i 7.0. Oto Mój kod do uzyskania i zwolnienia blokady budzenia. Należy uważać, aby zwiększyć drenaż baterii, więc nabyć i zwolnić go inteligentnie.

public void acquireWakeLock() {
    final PowerManager powerManager = (PowerManager) mContext.getSystemService(Context.POWER_SERVICE);
    releaseWakeLock();
    //Acquire new wake lock
    mWakeLock = powerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "PARTIAL_WAKE_LOCK");
    mWakeLock.acquire();
}

public void releaseWakeLock() {
    if (mWakeLock != null && mWakeLock.isHeld()) {
        mWakeLock.release();
        mWakeLock = null;
    }
}

Ref: https://developer.android.com/training/scheduling/wakelock.html#cpu

Pracuję nad prediction sdk, który wykorzystuje dane czujników urządzenia (akcelerometr/żyroskop) i przewiduje zdarzenia użytkownika. Doświadczyłem tego samego problemu.

 2
Author: Farhan,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-11-21 09:10:15

Napotkałem podobne problemy z Samsung Nexus uruchomiony Android 4.0.2 przy użyciu innych usług systemowych, które zatrzymują/wstrzymują, gdy ekran jest wyłączony, mimo że PARTIAL_WAKE_LOCK został nabyty. Moim rozwiązaniem było użycie SCREEN_DIM_WAKE_LOCK jak w:

 lockStatic = mgr.newWakeLock(PowerManager.SCREEN_DIM_WAKE_LOCK,NAME);

Byłoby o wiele lepiej mieć całkowicie wyłączony ekran, ale przynajmniej To rozwiązanie działa, chociaż byłoby jeszcze lepiej, gdybym mógł ograniczyć używanie SCREEN_DIM_WAKE_LOCK Tylko do tych urządzeń / systemów operacyjnych, które tego wymagają.

 2
Author: Greg Martin,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-12-28 02:35:40

Nienawidzę cię rozczarować, ale niektóre urządzenia po prostu nie trzymać akceleromet włączone, gdy są w trybie uśpienia. Niektóre tak, inne nie. możesz sprawdzić każdy krokomierz Weight loss app w sklepie większość z nich wyraźnie stwierdzić, że to nie będzie działać na niektórych urządzeniach.

 0
Author: EvilDuck,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-05-02 08:38:38

Jeśli opcja częściowej blokady budzenia nie jest dostępna dla telefonu, oznacza to, że Sterownik czujnika jest włączony early_suspend.

Są dwie opcje.

1: Wyłączenie EARLY_SUSPEND w sterowniku

2: Dodaj flagę czasu wykonywania, która może enable/disable early_suspend funkcjonalność na poziomie sterownika.

Ex. cat / sys/module/earlysuspend / sensor 1/0

IMO druga opcja powinna być tam od początku.
 0
Author: boosth,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-12-28 02:36:31