Utrzymać działanie usługi nawet wtedy, gdy telefon śpi?

Mam Usługę w mojej aplikacji, która jest zaprojektowana do uruchamiania co 10 minut. Zasadniczo sprawdza się na naszych serwerach, aby sprawdzić, czy wszystko działa poprawnie i powiadamia użytkownika o wszelkich problemach. Aplikację stworzyłem do użytku wewnętrznego w naszej firmie.

[2]}mój współpracownik korzystał z aplikacji przez długi weekend i zauważył, że nie przeprowadzono kontroli, gdy urządzenie poszło spać. Miałem wrażenie, że serwis miał działać w tle dopóki nie wywołam stopService() w moim kodzie.

Więc ostatecznie, moim celem jest, aby usługa była uruchomiona, dopóki użytkownik nie naciśnie przycisku off w aplikacji lub zabije proces.

Słyszałem o czymś, co nazywa się WakeLock, co ma na celu powstrzymanie wyłączania ekranu, co nie jest tym, czego chcę. Wtedy usłyszałem o innej rzeczy zwanej częściowym Wakelockiem , która utrzymuje procesor uruchomiony nawet wtedy, gdy urządzenie jest uśpione. To drugie brzmi bliżej tego, czego potrzebuję.

Jak nabyć ten WakeLock i kiedy powinienem go zwolnić i czy są inne sposoby na obejście tego?

Author: Octavian Damiean, 2012-01-03

3 answers

Uwaga: Ten post został zaktualizowany o API JobScheduler Android Lollipop release. Poniższy sposób jest nadal realny, ale można go uznać za przestarzały, jeśli celujesz w Androida lizaka i nie tylko. Zobacz drugą połowę alternatywy JobScheduler.

Jednym ze sposobów wykonywania powtarzających się zadań jest:

  • Utwórz klasę AlarmReceiver

    public class AlarmReceiver extends BroadcastReceiver 
    {
        @Override
        public void onReceive(Context context, Intent intent) 
        {
            Intent myService = new Intent(context, YourService.class);
            context.startService(myService);
        }
    }
    

    Z YourService byciem Twoją służbą; -)

Jeśli do wykonania zadania potrzebujesz blokady budzenia, jest to wskazane jest rozciągnięcie od WakefulBroadcastReceiver. Nie zapomnij dodać WAKE_LOCK pozwolenia w manifeście w tym przypadku!

  • Utwórz intencję oczekującą

Aby rozpocząć powtarzające się ankiety, wykonaj ten kod w swojej aktywności:

Intent myAlarm = new Intent(getApplicationContext(), AlarmReceiver.class);
//myAlarm.putExtra("project_id", project_id); //Put Extra if needed
PendingIntent recurringAlarm = PendingIntent.getBroadcast(getApplicationContext(), 0, myAlarm, PendingIntent.FLAG_CANCEL_CURRENT);
AlarmManager alarms = (AlarmManager) this.getSystemService(Context.ALARM_SERVICE);
Calendar updateTime = Calendar.getInstance();
//updateTime.setWhatever(0);    //set time to start first occurence of alarm 
alarms.setInexactRepeating(AlarmManager.RTC_WAKEUP, updateTime.getTimeInMillis(), AlarmManager.INTERVAL_DAY, recurringAlarm); //you can modify the interval of course

Ten kod ustawia alarm i anulowalny pendingIntent. alarmManager dostaje zadanie powtarzania recurringAlarm każdego dnia (trzeci argument), ale inexact więc procesor budzi się mniej więcej po interwale, ale nie do końca (Pozwala systemowi wybrać optymalny czas, co zmniejsza zużycie baterii). Przy pierwszym uruchomieniu alarmu (a tym samym usługi) będzie to czas, w którym zdecydujesz się być updateTime.

  • Ostatni, ale nie mniej ważny: oto jak zabić powtarzający się alarm

    Intent myAlarm = new Intent(getApplicationContext(), AlarmReceiver.class);
    //myAlarm.putExtra("project_id",project_id); //put the SAME extras
    PendingIntent recurringAlarm = PendingIntent.getBroadcast(getApplicationContext(), 0, myAlarm, PendingIntent.FLAG_CANCEL_CURRENT);
    AlarmManager alarms = (AlarmManager) getApplicationContext().getSystemService(Context.ALARM_SERVICE);
    alarms.cancel(recurringAlarm);
    

Ten kod tworzy kopię Twojego (prawdopodobnie) istniejącego alarmu i mówi alarmManager aby anulował wszystkie alarmy tego typu.

  • oczywiście jest też coś do zrobienia w Manifest:

Dołącz te dwie linie

  < receiver android:name=".AlarmReceiver"></receiver>
  < service android:name=".YourService"></service>

Wewnątrz znacznika < application>. Bez niego system nie akceptuje uruchomienia cyklicznego alarmu usługi.


Począwszy od wydania Android Lollipop , pojawia się nowy sposób eleganckiego rozwiązania tego zadania. Ułatwia to również wykonywanie akcji tylko wtedy, gdy spełnione są określone kryteria, takie jak stan sieci.

// wrap your stuff in a componentName
ComponentName mServiceComponent = new ComponentName(context, MyJobService.class);
// set up conditions for the job
JobInfo task = JobInfo.Builder(mJobId, mServiceComponent)
   .setPeriodic(mIntervalMillis)
   .setRequiresCharging(true) // default is "false"
   .setRequiredNetworkCapabilities(JobInfo.NetworkType.UNMETERED) // Parameter may be "ANY", "NONE" (=default) or "UNMETERED"
   .build();
// inform the system of the job
JobScheduler jobScheduler = (JobScheduler) context.getSystemService(Context.JOB_SCHEDULER_SERVICE);
jobScheduler.schedule(task);

Możesz również podać termin z setOverrideDeadline(maxExecutionDelayMillis).

Aby pozbyć się takie zadanie, wystarczy zadzwonić jobScheduler.cancel(mJobId); lub jobScheduler.cancelAll();.

 59
Author: stefan,
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-02-02 11:07:57

Poleciłbym, gdyby budowa tej aplikacji Od początku wykorzystywała komponent po stronie serwera (tak, wymagałoby to również monitorowania!) i wysyłać powiadomienia push, ankieta nigdy nie jest niezawodnym rozwiązaniem.

 5
Author: Lee Hambley,
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-01-03 14:05:34

Z Dokumentacji Androida w trybie doze dzieje się tak: ( https://developer.android.com/training/monitoring-device-state/doze-standby):

The system ignores wake locks.

The system does not allow JobScheduler to run.

Android również ignoruje Alarmmanagera, chyba że jest w setAndAllowWhileIdle() or setExactAndAllowWhileIdle().

Network access is suspended.

Więc jedynym sposobem jest użycie FCM na wysokim priorytecie lub Menedżerze alarmów za pomocą setAndAllowWhileIdle() lub setExactAndAllowWhileIdle ().

 2
Author: Saba Jafarzadeh,
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
2018-08-14 13:07:58