AlarmManager nie działa na kilku urządzeniach

85

Moja aplikacja korzysta z AlarmManagera i działa od 4 lat. Ale zauważyłem, że zaczęło zawodzić w niektórych urządzeniach.

Jestem prawie pewien, że kod jest poprawny (używam WakefulBroadcastReceiver i setExactAndAllowWhileIdle dla urządzeń z funkcją Doze), ponieważ działa idealnie na urządzeniach Nexus, ale zawodzi na urządzeniach niektórych producentów (Huawei, Xiaomi ...).

Na przykład urządzenia Huawei mają pewnego rodzaju menedżera baterii, który zabija aplikacje, a kiedy aplikacja zostaje zabita, zaplanowane alarmy są anulowane. Ustawienie aplikacji jako „chronionej” w menedżerze baterii Huawei rozwiązuje problem.

Ale ostatnio zauważyłem, że nie działa z większą liczbą urządzeń: Xiaomi, Samsung (może ma to związek z nowym „Smart Managerem”?) ... Wygląda na to, że takie zachowanie staje się standardem: zabijanie aplikacji działających w tle.

Ktoś wie coś na ten temat? Czy jest jakiś sposób, aby zapewnić uruchomienie alarmu?

EDYCJA: Ten problem jest spowodowany przez „oszczędzanie baterii” dodawane przez różnych producentów. Więcej informacji tutaj: https://dontkillmyapp.com/

Sergio Viudes
źródło
8
Producenci obwiniają aplikacje za zużycie energii i wciąż sprzedają rdzenie Octa, które zużywają więcej baterii w porównaniu z procesorem z mniejszą liczbą rdzeni. Czy myślą, że samo dodanie rdzenia przyspieszyłoby ich telefony?
FrozenFire
1
@AviLevinshtein Może źle zrozumiałem Twoje pytanie. Tworzę alarmy w mojej działalności. Następnie, gdy alarm się włączy, wykonywany jest odbiornik rozgłoszeniowy, a na koniec wykonywana jest WakefulIntentService (klasa z @commonsware).
Sergio Viudes
2
@JFValdes wciąż szukam rozwiązania. AlarmManager działa doskonale na urządzeniach z Vanilla Android. Problem w tym, że producenci próbują "ulepszyć" funkcje Androida i złamali AlarmManagera ... Producenci nie powinni wdrażać własnych "oszczędzaczy baterii", jeśli używają standardowego trybu Doze, wtedy AlarmManager działałby idealnie ... Nadal szukam na rozwiązanie ...
Sergio Viudes
1
Czy jest już jakieś rozwiązanie? Jak inne aplikacje lubią przypomnienia lub coś takiego robią? Musi być inna opcja niż setAlarm, która jest dla alarmów, a nie dla przypomnień
kv1dr
1
@SergioViudes Mam również ten sam problem z urządzeniami Xiomi do śledzenia. i jeśli powstrzymam moją aplikację przed ograniczeniem oszczędzania baterii, to będzie działać poprawnie na 3 z 4 urządzeń, wykonując następujące ustawienia - -> Przejdź do baterii -> Zasilanie -> Oszczędzanie baterii aplikacji -> Twoja aplikacja Teraz wybierz Brak ograniczeń (dla ustawień tła), a następnie Zezwól na opcję lokalizacji w tle
Imran Khan Saifi,

Odpowiedzi:

17

Już od kilku tygodni próbuję go rozwiązać. Nic nie znalazłem. Huawei po pewnym czasie po prostu wyłącza wszystkie alarmy. Jeśli umieszczę aplikację w chronionej aplikacji w oszczędzaniu baterii, to nie pomoże. Ale jeśli zmienię nazwę pakietu mojej aplikacji, aby zawierała słowa takie jak alarm, zegar lub kalendarz, działa to całkowicie normalnie, jak na każdym innym urządzeniu. Nie rozumiem, jak Google może wystawić certyfikat za to gówno. Uważam, że OEM nie powinien w taki sposób modyfikować podstawowej platformy. Rozumiem, że mają własny program do oszczędzania ciasta, który po pewnym czasie zabija aplikację, gdy użytkownik jej nie używa. Ale to zabijanie alarmów również chronionych aplikacji.

Pomocna jest również funkcja setAlarmClock () dla dokładnego czasu alarmów. Ale nie jest możliwe użycie tego do myśli takich jak aktualizacja widżetów.

Aktualizacja: Ochrona za pomocą słów kluczowych nazw pakietów już nie działa na obecnych urządzeniach Huawei, tak było w 2017 roku.

Atom
źródło
Tak jak ja, też próbuję, ale nie ma sposobu, aby rozwiązać ten problem na niektórych markach Xiaomi, Oppo, Huawei. Czasami zabijają proces w tle i alarm, aby oszczędzać baterię.
Andi Susilo
1
Mam telefon huawei, zmiana nazwy pakietu na alarm / kalendarz nic nie daje. Jedyny sposób, aby ominąć to dodanie aplikacji do listy chronionych aplikacji z menedżera telefonu
Ashish Pardhiye
9

Problemem jest Smart Manager. Samsung ma menedżera baterii, który czasami wyłącza działanie niektórych aplikacji w tle. Próbował „wznowić” po powrocie do aplikacji, ale całkowicie ją wyłącza lub może wznawiać się co około 5 minut (w zależności od tego, jak ma to Samsung).

To działałoby na standardowych wersjach Androida, ponieważ nie ma Samsung Manager. Możesz także zainstalować niestandardową wersję Androida, która ma pewne funkcje umożliwiające obsługę SM (w zależności od romu).

SA
źródło
Szaleję, bo nie mam urządzenia Samsunga, żeby to przetestować. Wiem tylko, co mówią mi użytkownicy mojej aplikacji. Czy wiesz, czy problem polega na tym, że AlarmManager nie działa, ponieważ aplikacja zostaje zabita? A może problem polega na tym, że urządzenie nie może się obudzić, gdy włączy się alarm z powodu tego menedżera?
Sergio Viudes
@SergioViudes Ostatnio wiele firm wdrażało własne. Na przykład LG ma taki, który działa podobnie do Samsunga, może Twój telefon ma taki? Problemem nie jest alarm, aplikacja alarmowa jest przenoszona do stanu, w którym jest całkowicie nieaktywna. Smart Manager uważa, że ​​to tylko przypadkowa aplikacja, której nie potrzebujesz. Zauważyłem, że niektóre aplikacje mogą go ominąć, być może niektóre aplikacje są akceptowane przez inteligentnego menedżera.
SA
1
@SergioViudes Mam Samsunga do przetestowania i mogę powiedzieć, że niewiele można z niego uzyskać. Kiedy inteligentny menedżer optymalizuje aplikację, nie ma błędu ani niczego, po prostu umiera, podobnie jak wymuszone zatrzymanie. Nadal jest na liście ostatnich aplikacji
Tim,
Dzięki Tim. Byłoby wspaniale, gdybyśmy rozwiązali ten problem bez konieczności wykluczania aplikacji z „Inteligentnego” Menedżera.
Sergio Viudes
urządzenia takie jak xiaomi (miui), vivo i htc domyślnie ustawiają całą gamę uprawnień jako fałszywe, chyba że jest to aplikacja na liście „zaufanych” aplikacji, które wydają się same określać (whatsapp, truecaller itp. są domyślnie zaufane ). To staje się koszmarem programistów
desidigitalnomad
3

Większość nowoczesnych urządzeń z Androidem jest wyposażona w aplikację lub mechanizm, który automagicznie próbuje dowiedzieć się, jak oszczędzać baterię, aw rezultacie może zabić niektóre aplikacje innych firm. Może to spowodować usunięcie zaplanowanych zadań i zadań (np. Nie włączają się alarmy, nie działają powiadomienia push itp.). W wielu przypadkach dzieje się to całkowicie niezależnie od mechanizmów oszczędzania baterii w Androidzie, w moim przypadku nie mogłem dokonać większej optymalizacji baterii po wykryciu modelu jakiegoś urządzenia, przekierowuję użytkownika do menadżera uruchamiania, aby dodać moją aplikację do białej listy

W tym linku dla każdego modelu znalazłeś zamiar wywołania https://android-arsenal.com/details/1/6771

baderkhane
źródło
2

Użyj AlarmManager dla urządzeń <5.0 i JobScheduler dla urządzeń 5.0+. Nie mogę powiedzieć na pewno, że na JobScheduler nie wpłyną oszustwa producentów, ale wydaje mi się to znacznie mniej prawdopodobne, biorąc pod uwagę, że Android próbuje przenieść ludzi z AlarmManager do JobScheduler.

EDYCJA: Google opracowało własne rozwiązanie tego problemu o nazwie WorkManager . Oddziela wiele ram planowania i używa najbardziej odpowiedniego dla urządzenia.

Tomek
źródło
2
Niestety, w przeciwieństwie do klasy AlarmManager, synchronizacja nie jest dokładna podczas korzystania z JobScheduler. W mojej aplikacji czas powinien być dokładny :(
Sergio Viudes,
Spróbowałem i niektórzy optymalizatorzy (przynajmniej Samsung) zabijają wszystkie oczekujące zadania w JobScheduler, gdy ekran zgaśnie. Więc też jest zepsuty. Dzieje się to w wersji 5.0. Po aktualizacji do 6.0 działa dobrze, myślę, że naprawili to. Nie mogłem jeszcze tego przetestować z innymi producentami.
Sloy
Aby uzyskać dokładny czas, nie możesz korzystać z usługi działającej w tle ani usługi zaplanowanej. Możesz wypróbować usługę pierwszoplanową, ale spowoduje to trwałe powiadomienie dla użytkownika (prawdopodobnie niepożądane), a niektóre telefony mają wbudowane funkcje zabijania zadań, które automatycznie niszczą usługę pierwszoplanową. WorkManager jest najlepszym rozwiązaniem, ale niestety nie poda dokładnych czasów.
Tom,
1

Mam też aplikację, która ustawia alarmy. Rozwiązaniem jest użycie AlarmManager.setAlarmClock () na api> = 21. Nie ma na to wpływu drzemka afaik i ma dodatkową zaletę polegającą na umieszczeniu ikony budzika w zasobniku systemowym.

Tyler Pfaff
źródło
Dzięki za odpowiedź. Czy jest jakiś sposób na usunięcie ikony budzika?
Sergio Viudes
Niestety setAlarmClock czasami nie działa. Przetestowałem to na urządzeniu Oreo z małą ilością pamięci.
Boris Salimov
0

większość nowych telefonów jest obecnie wyposażona w pewnego rodzaju menedżera oszczędzania baterii / energii, który robi to samo, co opisałeś. nie licząc duboosterów i czystych mistrzów.

Myślę, że musisz umieścić zrzeczenie się lub często zadawane pytania na liście aplikacji / Sklepu Play, stwierdzając, że ta aplikacja musi zostać umieszczona z wyjątkiem aplikacji do zarządzania baterią, aby działała poprawnie.

eriuzo
źródło
Powinien być inny sposób, aby to zrobić ... Użytkownicy nie przeczytają zastrzeżenia. Nie mogę myśleć, że telefony Samsung nie pozwalają aplikacjom na korzystanie z AlarmManagera ...
Sergio Viudes
Alarmy nie zadziałają „na czas”, ale ostatecznie będą
Gavriel
To (niestety) najbardziej pomocna odpowiedź, powiedziałbym. Żałuję, że nie było lepszego rozwiązania, ale producenci sprzętu psują doskonale działającego waniliowego Androida.
krakaj
0

przestałem używać AlarmManager jakiś czas temu ... lepsza i stabilniejsza alternatywa

  1. stworzyć usługę
  2. zarejestruj BroadcastReceiver dla BOOT_COMPLETED
  3. odpalić usługę z odbiornika
  4. uruchom nową procedurę obsługi w usłudze, która zapętla się co X minut ( Android - uruchamianie metody okresowo za pomocą wywołania postDelayed () )
  5. sprawdź, czy nadszedł czas na wykonanie zadania: teraz - czas wykonania> 0 ( Jak znaleźć czas trwania różnicy między dwiema datami w java? )
  6. jeśli tak, wykonaj zadanie i zatrzymaj program obsługi

tak .. to jest uciążliwe .. ale praca jest wykonana NIEZALEŻNIE OD CO

ymz
źródło
3
Dziękuję za sugestię, ale chciałbym uniknąć tego podejścia, ponieważ używanie AlarmManagera nie zużywa pamięci RAM ani żadnych zasobów. A jeśli Twoja aplikacja zostanie zabita, usługa zostanie zatrzymana, prawda?
Sergio Viudes
nie powiedziałem, że to podejście jest BOOLETPROOF, ale przynajmniej składa się z różnych wersji API :)
ymz
Aby działać niezawodnie, to rozwiązanie prawdopodobnie wymagałoby również użycia blokad budzenia, a to pochłonęłoby ogromne ilości baterii.
Paweł Nadolski
myślę, że masz rację w tej sprawie… jedyne pytanie brzmi: co byłoby najgorsze - zawodny kod lub słaba wydajność? w każdym razie osobiście uważam, że istnieją alternatywne sposoby na blokadę, które mogą być odpowiednie w niektórych przypadkach (na przykład: stackoverflow.com/questions/5346694/ ... )
ymz
0

Czy słuchasz BOOT_COMPLETED? Musisz ponownie ustawić alarmy po ponownym uruchomieniu urządzenia.

Tyler Pfaff
źródło
Tak. Jak powiedziałem, alarmy działały od 2012 roku do teraz. Po ponownym uruchomieniu urządzenia zmieniam harmonogram alarmów w odbiorniku transmisji BOOT_COMPLETED.
Sergio Viudes
1
Wymagające ponownego uruchomienia swojej aplikacji do pracy znowu nie jest nawet w połowie rozwiązanie
Tim
1
@TimCastelijns to wcale nie to, co mówię. JEŚLI urządzenie zostanie zrestartowane, wszystkie alarmy ustawione w menedżerze alarmów muszą zostać ponownie ustawione.
Tyler Pfaff,
@TylerPfaff tak, ale ponowne uruchomienie urządzenia nie jest związane z problemem w tym pytaniu
Tim
0

W jakiej wersji Androida działają te urządzenia?

Począwszy od API 23, sam system operacyjny przejdzie w tryb bezczynności o niskim poborze mocy, gdy nie będzie używany przez jakiś czas, iw tym trybie alarmy nie będą dostarczane. Istnieje jednak sposób, aby aplikacje wyraźnie powiedziały: „Chcę, aby ten alarm włączył się w tym momencie, niezależnie od zużycia baterii”; nowe metody AlarmManager o nazwie setAndAllowWhileIdle()i setExactAndAllowWhileIdle().

Z twojego opisu wynika, że ​​może to nie być konkretną przyczyną twoich problemów na niektórych urządzeniach OEM, ale jest to coś, o czym wszyscy programiści używający Menedżera alarmów powinni być świadomi.

Wreszcie, wiele zastosowań Menedżera alarmów można lepiej rozwiązać za pomocą mechanizmów Harmonogramu zadań. Ze względu na kompatybilność wsteczną „Menedżer sieci GCM” usług Play jest w rzeczywistości bardzo zbliżony funkcjonalnie do Harmonogramu zadań - korzysta z tego narzędzia wewnętrznie w nowszych wersjach systemu Android - i nie zawsze dotyczy sieci, pomimo nazwy klasy.

ctate
źródło
Na urządzeniach Samsung ze Smart Managerem działa Lollipop. Używam już setExactAndAllowWhileIdle dla urządzeń Marshmallow. Rzucę okiem na JobScheduler i GCM. W każdym razie nie wiem, czy problem polega na tym, że alarm się nie włączy, czy też to urządzenie nie jest budzone, gdy włącza się alarm.
Sergio Viudes
0

Nie sądzę, aby zabicie aplikacji uniemożliwiło menedżerowi alarmów obudzenie aplikacji.

Tylko wtedy, gdy „wymusisz zatrzymanie” lub wyłączysz aplikację, nie otrzymasz oddzwonień od menedżera alarmów.

Przyczyną może być coś innego.

Również w M ... setExactAndAllowWhileIdle ogranicza przepustowość ... to znaczy, jeśli zaplanujesz alarm co 2 minuty, nie zostanie on wyzwolony. ..Musi być 15-minutowe okno. .

rupesh jain
źródło
1
Dzięki za odpowiedź. Ale jeśli nie, dlaczego aplikacja działa idealnie, gdy „optymalizacja baterii” jest wyłączona w Smart Managerze?
Sergio Viudes
ty uruchamiając aplikację na zakorzenione device..if tak menedżerze aplikacji można wyłączyć aplikację zbyt ..
Rupesh Jain
Nie, nie uruchamiam go na zrootowanym urządzeniu.
Sergio Viudes
@rupeshjain "to znaczy, jeśli zaplanujesz alarm co 2 minuty, nie będzie on wyzwalany. ..Musi być 15-minutowe okno." to nie jest do końca prawdą, to prawdziwy problem, jeśli to prawda. Możesz dokładnie przeczytać, jaki jest limit czasu planowania w dokumentacji systemu Android dla metody setExactAndAllowWhileIdle. Istnieją ograniczenia dotyczące częstotliwości uruchamiania tych alarmów dla określonej aplikacji. Podczas normalnej pracy systemu alarmy te będą wysyłane nie częściej niż co minutę, gdy w trybie bezczynności o niskim poborze mocy ten czas może być znacznie dłuższy niż 15 minut.
eyadMhanna
0

W przypadku Xiaomi może być konieczne włączenie funkcji AutoStart dla aplikacji. Próbuję zrobić listę modyfikacji Androida (zwykle od producenta telefonu), które mogą wpływać na proces w tle. Jeśli masz coś nowego, dodaj odpowiedź tutaj Lista zabójców zadań Androida

Andrei Ciuca
źródło
0

Musimy włączyć naszą aplikację w menedżerze autostartu w menedżerze aplikacji, niektóre telefony, takie jak vivo v5,

In vivo v5 menu to znajdziemy w iManager -> App Manager -> Auto Start Manager. Włącz naszą aplikację tutaj.

Następnie twój menedżer alarmów / alarmów uruchomi alarm, jeśli aplikacja zostanie zabita lub zamknięta.

Aneesh NN
źródło
0

Szukałem odpowiedzi i po kilku godzinach znalazłem to:

https://stackoverflow.com/a/35220476/3174791

W wznowieniu można dowiedzieć się, czy Twoja aplikacja została zabita przez „Chronione aplikacje” i działa to tylko na urządzeniach Huawei. daj mi znać, jeśli jest jakieś rozwiązanie dla innych urządzeń (Samsung, Sony, Xiaomi itp.).

Edgar
źródło
0

To może być późno, ale mam nadzieję, że to komuś pomoże.

Tak długo tkwiłem w tym samym problemie. Ale teraz wiem, jak rozwiązać ten problem. To jest dla każdego, kto może mieć ten sam problem. Ludzie ciągle mówią, że musisz włączyć AutoStart, ale udało mi się to bez użycia automatycznego startu.

Po pierwsze, WakeFullBroadcastaReceiver jest teraz przestarzały i powinieneś używać BroadcastReceiver. Po drugie, musisz użyć ForegroudService zamiast BackgroundService.

Poniżej podam przykład:

IntentService.class

public class NotificationService extends IntentService {


//In order to send notification when the app is close
//we use a foreground service, background service doesn't do the work.



public NotificationService() {
    super("NotificationService");
}

@Override
public void onCreate() {
    super.onCreate();

}

@Override
public int onStartCommand(@Nullable Intent intent, int flags, int startId) {
    super.onStartCommand(intent, flags, startId);

    //There is no difference in the result between start_sticky or start_not_sticky at the moment
    return START_NOT_STICKY;
}

@Override
protected void onHandleIntent(@Nullable Intent intent) {

    //TODO check if the app is in foreground or not, we can use activity lifecyclecallbacks for this

    startForegroundServiceT();
    sendNotification(intent);
    stopSelf();
}


/***
 * you have to show the notification to the user when running foreground service
 * otherwise it will throw an exception
 */
private void startForegroundServiceT(){

    if (Build.VERSION.SDK_INT >= 26) {
        String CHANNEL_ID = "my_channel_01";
        NotificationChannel channel = new NotificationChannel(CHANNEL_ID,
                "Channel human readable title",
                NotificationManager.IMPORTANCE_DEFAULT);

        ((NotificationManager) 
   getSystemService(Context.NOTIFICATION_SERVICE)).createNotificationChannel(channel);

        Notification notification = new Notification.Builder(this, CHANNEL_ID)
                .setContentTitle("")
                .setContentText("").build();

        startForeground(1, notification);
    }
}

private void sendNotification(Intent intent){

    //Send notification
    //Use notification channle for android O+
}
}

uruchom usługę pierwszoplanową w BroadcastReceiver.class

public class AlarmReceiver extends BroadcastReceiver {


@Override
public void onReceive(Context context, Intent intent) {


    Intent service = new Intent(context, NotificationService.class);
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
        context.startForegroundService(service);
    } else {
        context.startService(service);
    }

}
}

A setAlarmy takie jak ten:

 public static void setAlarm(Context context, int requestCode, int hour, int minute){


    AlarmManager alarmManager =( AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
    Intent intent = new Intent(context//same activity should be used when canceling the alarm
            , AlarmReceiver.class);
    intent.setAction("android.intent.action.NOTIFY");

    //setting FLAG_CANCEL_CURRENT makes some problems. and doest allow the cancelAlarm to work properly
    PendingIntent pendingIntent = PendingIntent.getBroadcast(context, 1001, intent, 0);

    Calendar time = getTime(hour, minute);

    //set Alarm for different API levels
    if (Build.VERSION.SDK_INT >= 23){
        alarmManager.setExactAndAllowWhileIdle(AlarmManager.RTC_WAKEUP,time.getTimeInMillis(),pendingIntent);
    }
    else{
        alarmManager.set(AlarmManager.RTC_WAKEUP,time.getTimeInMillis(),pendingIntent);
    }

Następnie musisz zadeklarować odbiorcę i usługę pierwszoplanową w manifeście.

       <receiver android:name=".AlarmReceiver"
        android:enabled="true"
        android:exported="true">
        <intent-filter>
            <action android:name="android.intent.action.NOTIFY">

            </action>
        </intent-filter>
    </receiver>
    <service
        android:name=".NotificationService"
        android:enabled="true"
        android:exported="true"></service>

Mam nadzieję, że to komuś pomoże.

Keivan.k
źródło