AlarmManager funktioniert nicht in mehreren Geräten


85

Meine App verwendet AlarmManager und funktioniert seit 4 Jahren. Aber ich bemerkte, dass es bei einigen Geräten zu Fehlern kam.

Ich bin mir ziemlich sicher, dass der Code richtig ist (ich verwende WakefulBroadcastReceiver und setExactAndAllowWhileIdle für Geräte mit Doze), da er auf Nexus-Geräten einwandfrei funktioniert, bei Geräten einiger Hersteller (Huawei, Xiaomi ...) jedoch fehlschlägt.

Huawei-Geräte verfügen beispielsweise über eine Art Batteriemanager, mit dem Apps beendet werden. Wenn eine App beendet wird, werden geplante Alarme abgebrochen. Das Einstellen einer App als "geschützt" im Huawei-Akkumanager löst das Problem.

Aber kürzlich habe ich festgestellt, dass es nicht mit mehr Geräten funktioniert: Xiaomi, Samsung (vielleicht hängt es mit dem neuen "Smart Manager" zusammen?) ... Es scheint, dass dieses Verhalten zum Standard wird: Hintergrund-Apps zu töten.

Weiß jemand etwas darüber? Wie kann sichergestellt werden, dass ein Alarm ausgelöst wird?

BEARBEITEN: Dieses Problem wird durch "Batteriesparer" verursacht, die von verschiedenen Herstellern hinzugefügt wurden. Weitere Informationen hier: https://dontkillmyapp.com/


8
Hersteller machen Apps für den Stromverbrauch verantwortlich und vermarkten weiterhin die Octa-Kerne, die im Vergleich zur CPU mit weniger Kernen mehr Batterie verbrauchen. Denken sie, dass das Hinzufügen eines Kerns ihre Telefone beschleunigen würde?
FrozenFire

1
@AviLevinshtein Vielleicht habe ich deine Frage falsch verstanden. Ich erstelle die Alarme in meiner Aktivität. Wenn der Alarm ausgelöst wird, wird ein Rundfunkempfänger ausgeführt und schließlich ein WakefulIntentService (Klasse von @commonsware) ausgeführt.
Sergio Viudes

2
@JFValdes Ich suche noch nach einer Lösung. AlarmManager funktioniert perfekt auf Geräten mit Vanilla Android. Das Problem ist, dass Hersteller versuchen, Android-Funktionen zu "verbessern", und AlarmManager kaputt gemacht haben ... Hersteller sollten ihre eigenen "Batteriesparer" nicht implementieren. Wenn sie den Standard-Doze-Modus verwenden, funktioniert AlarmManager perfekt ... Sieht immer noch aus für eine Lösung ...
Sergio Viudes

1
Gibt es schon eine Lösung? Wie machen andere Apps wie Erinnerungen oder ähnliches das? Es muss eine andere Option als setAlarm geben, die für Alarme und nicht für Erinnerungen vorgesehen ist
kv1dr

1
@SergioViudes Ich habe auch das gleiche Problem mit Xiomi-Geräten für die Verfolgung. und wenn ich meine App von der Einschränkung des Batteriesparens fernhalte, funktioniert sie in 3 von 4 Geräten korrekt, indem Sie die folgenden Einstellungen vornehmen: -> Gehen Sie zum Akku -> Stromversorgung -> App-Batteriesparmodus -> Ihre App Wählen Sie nun Keine Einschränkungen (für Hintergrundeinstellungen), dann Option für Hintergrundposition zulassen
Imran Khan Saifi

Antworten:


17

Ich versuche es schon einige Wochen zu lösen. Ich habe nichts gefunden Huawei beendet nach einiger Zeit alle Alarme. Wenn ich die App in die geschützte App in ihrem Batteriesparmodus lege, hilft das nicht. Wenn ich jedoch den Paketnamen meiner App so ändere, dass er Wörter wie Wecker, Uhr oder Kalender enthält, funktioniert dies wie auf allen anderen Geräten ganz normal. Ich verstehe nicht, wie Google diesen Mist zertifizieren kann. Ich denke, dass OEM die Kernplattform nicht so modifizieren sollte. Ich verstehe, dass sie einen eigenen Batter Saver haben, der die App nach einiger Zeit beendet, wenn der Benutzer sie nicht benutzt. Aber dieses Töten alarmiert auch geschützte Apps.

Auch setAlarmClock () für genaue Timing-Alarme hilft. Es ist jedoch nicht möglich, dies für Gedanken wie ein Widget-Update zu verwenden.

Update: Der Schutz durch Schlüsselwörter für Paketnamen funktioniert auf aktuellen Huawei-Geräten bereits nicht, dies war 2017 der Fall.


Genau wie ich versuche ich es auch, aber es gibt keine Möglichkeit, dieses Problem bei einigen Marken wie Xiaomi, Oppo, Huawei zu lösen. Sie beenden manchmal den Hintergrundprozess und den Alarm, um Batterie zu sparen.
Andi Susilo

1
Ich habe ein Huawei-Telefon, das Ändern des Paketnamens in Alarm / Kalender bewirkt nichts. Nur so können Sie dies umgehen.
Fügen

9

Das Problem ist Smart Manager. Samsung verfügt über einen Akku-Manager, der bestimmte Apps manchmal daran hindert, im Hintergrund ausgeführt zu werden. Es wurde versucht, beim Zurückkehren zur App "fortzufahren", deaktiviert die Anwendung jedoch vollständig oder wird möglicherweise alle 5 Minuten fortgesetzt (je nachdem, wie Samsung sie hat).

Dies würde auf Standardversionen von Android funktionieren, da es keinen Samsung Manager gibt. Sie können auch eine benutzerdefinierte Version von Android installieren, die einige Funktionen zum Aktivieren von SM bietet (abhängig von der Rom).


Ich werde verrückt, weil ich kein Samsung-Gerät habe, um es zu testen. Ich weiß nur, was mir Benutzer meiner App sagen. Wissen Sie, ob das Problem darin besteht, dass AlarmManager nicht funktioniert, weil die App getötet wird? Oder ist das Problem, dass das Gerät aufgrund dieses Managers nicht aktiviert werden kann, wenn der Alarm ausgelöst wird?
Sergio Viudes

@SergioViudes In letzter Zeit haben viele Unternehmen ihre eigenen implementiert. Wie LG hat eine, die ähnlich wie Samsung funktioniert, vielleicht hat Ihr Telefon eine? Das Problem ist nicht der Alarm, die Alarm-App wird in einen Zustand versetzt, in dem sie vollständig inaktiv ist. Smart Manager ist der Meinung, dass es sich nur um eine zufällige App handelt, die Sie nicht benötigen. Ich habe festgestellt, dass bestimmte Apps daran vorbeikommen können. Möglicherweise werden einige Apps vom Smart Manager akzeptiert.
SA

1
@SergioViudes Ich muss ein Samsung testen und ich kann Ihnen sagen, dass Sie nicht viel davon bekommen können. Wenn der Smart Manager Ihre App optimiert, gibt es keinen Fehler oder irgendetwas, er stirbt einfach, ähnlich wie beim erzwungenen Stoppen. Es ist immer noch in der Liste der letzten Apps
Tim

Danke Tim. Es wäre großartig, dieses Problem zu lösen, ohne Apps vom "Smart" Manager ausschließen zu müssen.
Sergio Viudes

Geräte wie xiaomi (miui), vivo und htc setzen eine ganze Reihe von Berechtigungen standardmäßig auf false, es sei denn, es handelt sich um eine App in der Liste der "vertrauenswürdigen" Apps, die sie selbst zu bestimmen scheinen (WhatsApp, TrueCaller usw. sind standardmäßig vertrauenswürdig ). Dies wird ein Alptraum für
Programmierer

3

Die meisten modernen Android-Geräte verfügen über eine App oder einen Mechanismus, mit dem automatisch versucht wird, den Akku zu schonen, wodurch bestimmte Apps von Drittanbietern möglicherweise zerstört werden. Dies kann dazu führen, dass geplante Aufgaben und Jobs entfernt werden (z. B. Alarme werden nicht ausgelöst, Push-Benachrichtigungen funktionieren nicht usw.). In vielen Fällen geschieht dies völlig unabhängig von den Batteriesparmechanismen von Android. In meinem Fall konnte ich keine Batterieoptimierung mehr vornehmen, wenn ich ein Gerätemodell erkenne. Ich leite den Benutzer zum Startmanager um, um meine Anwendung auf die Whitelist zu setzen

Sie haben in diesem Link für jedes Modell die Absicht gefunden, https://android-arsenal.com/details/1/6771 aufzurufen


2

Verwenden Sie AlarmManager für <5.0-Geräte und JobScheduler für 5.0+ Geräte. Ich kann nicht sicher sagen, dass JobScheduler von den Spielereien der Hersteller nicht betroffen sein wird, aber es scheint mir viel weniger wahrscheinlich, da Android versucht, Menschen von AlarmManager auf JobScheduler zu verlagern.

BEARBEITEN: Google hat eine Erstanbieter -Lösung für dieses Problem namens WorkManager herausgebracht . Es abstrahiert mehrere Planungsframeworks und verwendet das für das Gerät am besten geeignete.


2
Im Gegensatz zur AlarmManager-Klasse ist das Timing bei Verwendung von JobScheduler leider nicht genau. In meiner App sollte das Timing genau sein :(
Sergio Viudes

Ich habe es ausprobiert und einige Optimierer (zumindest Samsung) beenden alle ausstehenden Aufgaben in JobScheduler, wenn der Bildschirm ausgeht. Also ist es auch kaputt. Dies geschieht am 5.0. Nach dem Update auf 6.0 funktioniert es einwandfrei, ich denke, sie haben das behoben. Ich konnte es noch nicht mit anderen Herstellern testen.
Sloy

Für ein genaues Timing können Sie keinen Hintergrunddienst oder geplanten Dienst verwenden. Sie können einen Vordergrunddienst ausprobieren, dies führt jedoch zu einer dauerhaften Benachrichtigung des Benutzers (wahrscheinlich unerwünscht), und in einigen Telefonen sind Task-Killer integriert, die den Vordergrunddienst automatisch zerstören. WorkManager ist die beste Lösung, gibt Ihnen jedoch leider keine genauen Zeitangaben.
Tom

1

Hören Sie auf BOOT_COMPLETED? Sie müssen Alarme erneut einstellen, wenn ein Gerät neu gestartet wird.


Ja. Wie gesagt, Alarme funktionierten seit 2012 bis jetzt. Wenn das Gerät neu gestartet wird, plane ich Alarme im Broadcast-Empfänger BOOT_COMPLETED neu.
Sergio Viudes

1
Ein Neustart erforderlich, damit Ihre App wieder funktioniert, ist nicht einmal eine halbe Lösung
Tim

1
@ TimCastelijns das ist überhaupt nicht was ich sage. Wenn das Gerät neu gestartet wird, müssen alle mit dem Alarmmanager eingestellten Alarme erneut eingestellt werden.
Tyler Pfaff

@ TylerPfaff ja, aber der Neustart des Geräts hat nichts mit dem Problem in dieser Frage zu tun
Tim

1

Ich habe auch eine App, die Alarme setzt. Die Lösung besteht darin, AlarmManager.setAlarmClock () auf api> = 21 zu verwenden. Dies wird von doze afaik nicht beeinflusst und hat den zusätzlichen Bonus, ein Weckersymbol in die Taskleiste zu legen.


Danke für deine Antwort. Gibt es eine Möglichkeit, das Weckersymbol zu entfernen?
Sergio Viudes

Leider funktioniert setAlarmClock manchmal nicht. Ich habe es auf einem Oreo-Gerät mit wenig Speicher getestet.
Boris Salimov

0

Die meisten neuen Telefone sind heutzutage mit einer Art Batterie- / Energiesparmanager ausgestattet, die dasselbe tun, was Sie beschrieben haben. Dubooster und saubere Meister nicht mitgerechnet.

Ich denke, Sie müssen einen Haftungsausschluss oder eine FAQ in Ihre App / Play Store-Liste aufnehmen, aus der hervorgeht, dass diese App in Ausnahme Ihrer Batteriemanager-App aufgenommen werden muss, damit sie ordnungsgemäß funktioniert.


Es sollte einen anderen Weg geben ... Benutzer werden den Haftungsausschluss nicht lesen. Ich kann nicht glauben, dass Samsung-Handys Apps nicht erlauben, AlarmManager zu verwenden ...
Sergio Viudes

Die Alarme werden nicht "pünktlich" ausgelöst, aber sie werden schließlich
Gavriel

Dies ist (leider) die hilfreichste Antwort, würde ich sagen. Ich wünschte, es gäbe eine bessere Lösung, aber Hardwarehersteller beschädigen das perfekt funktionierende Vanille-Android.
Caw

0

Auf welcher Android-Version laufen diese Geräte?

Ab API 23 wechselt das Betriebssystem selbst in einen Leerlaufmodus mit geringem Stromverbrauch, wenn es eine Weile nicht verwendet wurde, und in diesem Modus werden keine Alarme ausgegeben. Es gibt jedoch eine Möglichkeit für Apps, explizit zu sagen: "Ich muss diesen Alarm zu diesem Zeitpunkt unabhängig vom Batterieverbrauch auslösen". Die neuen AlarmManager-Methoden heißen setAndAllowWhileIdle()und setExactAndAllowWhileIdle().

Aus Ihrer Beschreibung geht hervor, dass dies möglicherweise nicht die besondere Ursache für Ihre Probleme auf bestimmten OEM-Geräten ist. Dies sollten jedoch alle Entwickler, die den Alarm Manager verwenden, berücksichtigen.

Schließlich werden viele Verwendungen des Alarmmanagers mithilfe der Mechanismen des Job Schedulers besser behandelt. Aus Gründen der Abwärtskompatibilität ist der Play Services "GCM Network Manager" in seiner Funktionalität dem Job Scheduler sehr ähnlich - er verwendet den Job Scheduler intern in neueren Versionen von Android - und es geht trotz des Klassennamens nicht unbedingt um Netzwerk.


Auf Samsung-Geräten mit Smart Manager wird Lollipop ausgeführt. Ich verwende bereits setExactAndAllowWhileIdle für Marshmallow-Geräte. Ich werde einen Blick auf JobScheduler und GCM werfen. Wie auch immer, ich weiß nicht, ob das Problem darin besteht, dass der Alarm nicht ausgelöst wird oder ob das Gerät nicht aktiviert wird, wenn der Alarm ausgelöst wird.
Sergio Viudes

0

Ich glaube nicht, dass das Beenden der App den Alarmmanager daran hindert, Ihre App zu aktivieren.

Nur wenn Sie die App "erzwingen" oder deaktivieren, erhalten Sie keine Rückrufe vom Alarmmanager.

Die Grundursache könnte etwas anderes sein.

Auch auf M ... setExactAndAllowWhileIdle wird gedrosselt ... das heißt, wenn Sie alle 2 Minuten einen Alarm einplanen, wird dieser nicht ausgelöst. ..Es muss 15 Minuten Fenster sein. .


1
Danke für deine Antwort. Wenn nicht, warum funktioniert die App dann einwandfrei, wenn die "Batterieoptimierung" in Smart Manager deaktiviert ist?
Sergio Viudes

Führen Sie die App auf einem gerooteten
Gerät aus?

Nein, ich führe es nicht auf einem gerooteten Gerät aus.
Sergio Viudes

@rupeshjain "Das heißt, wenn Sie alle 2 Minuten einen Alarm einplanen, wird dieser nicht ausgelöst. Es muss ein 15-Minuten-Fenster vorhanden sein." Das ist nicht ganz richtig, es ist ein echtes Problem, wenn es wahr ist. Sie können genau das Zeitlimit für die Planung in den Android Docs für die setExactAndAllowWhileIdle-Methode lesen. Es gibt Einschränkungen, wie oft diese Alarme für eine bestimmte Anwendung ausgelöst werden. Im normalen Systembetrieb werden diese Alarme nicht mehr als etwa jede Minute ausgelöst, wenn im Leerlaufmodus mit geringem Stromverbrauch diese Dauer erheblich länger als 15 Minuten sein kann.
eyadMhanna

0

Für Xiaomi müssen Sie möglicherweise AutoStart für Ihre App aktivieren. Ich versuche, eine Liste von Android-Änderungen (normalerweise vom Hersteller des Telefons) zu erstellen, die einen Hintergrundprozess beeinflussen können. Wenn Sie etwas Neues haben, fügen Sie bitte hier eine Antwort hinzu. Liste der Android-Task-Killer


0

Wir müssen unsere App im Autostart-Manager im App-Manager aktivieren, einige Handys wie vivo v5,

In vivo v5 finden Sie dieses Menü unter iManager -> App Manager -> Auto Start Manager. Aktivieren Sie unsere App hier.

Dann löst Ihr Alarm / Alarmmanager einen Alarm aus, wenn die App beendet oder geschlossen wird.


0

Ich suchte nach einer Antwort und fand nach einigen Stunden Folgendes:

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

Im Lebenslauf können Sie feststellen, ob Ihre App von "Geschützten Apps" getötet wurde. Dies funktioniert nur auf Huawei-Geräten. Lassen Sie mich wissen, ob es eine Lösung für andere Geräte gibt (Samsung, Sony, Xiaomi usw.).


0

Das mag spät sein, aber ich hoffe, es hilft jemandem.

Ich war so lange mit dem gleichen Problem beschäftigt. Aber jetzt weiß ich, wie ich dieses Problem lösen kann. Dies ist für alle, die das gleiche Problem haben könnten. Die Leute sagen immer wieder, dass Sie AutoStart aktivieren müssen, aber ich habe es ohne automatischen Start geschafft.

Zunächst einmal ist WakeFullBroadcastaReceiver jetzt veraltet und Sie sollten BroadcastReceiver verwenden. Zweitens müssen Sie den ForegroudService anstelle des BackgroundService verwenden.

Ich werde Ihnen das folgende Beispiel geben:

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+
}
}

Starten Sie den Vordergrunddienst in 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);
    }

}
}

Und die setAlarms mögen das:

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

Dann müssen Sie den Empfänger und den Vordergrundservice im Manifest deklarieren.

       <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>

Ich hoffe das hilft jemandem.


-1

Ich habe vor einiger Zeit aufgehört, AlarmManager zu verwenden ... eine bessere und stabilere Alternative

  1. einen Service erstellen
  2. Registrieren Sie einen BroadcastReceiver für BOOT_COMPLETED
  3. Feuern Sie Ihren Dienst vom Empfänger aus ab
  4. Starten Sie einen neuen Handler in Ihrem Dienst, der sich alle X Minuten wiederholt ( Android - Führen Sie eine Methode regelmäßig mit dem Aufruf postDelayed () aus ).
  5. Überprüfen Sie, ob die Zeit für die Ausführung der Aufgabe gekommen ist: jetzt - Ausführungszeit> 0 ( Wie wird die Dauer der Differenz zwischen zwei Daten in Java ermittelt? )
  6. Wenn ja, führen Sie die Aufgabe aus und stoppen Sie den Handler

Ja ... es ist ein Schmerz ... aber die Arbeit wird erledigt, egal was


3
Vielen Dank für Ihren Vorschlag, aber ich möchte diesen Ansatz vermeiden, da die Verwendung von AlarmManager weder RAM noch Ressourcen verbraucht. Und wenn Ihre App beendet wird, wird der Dienst beendet, oder?
Sergio Viudes

Ich habe nicht gesagt, dass dieser Ansatz BOOLETPROOF ist, aber zumindest besteht er aus verschiedenen API-Versionen :)
ymz

Um zuverlässig zu arbeiten, müsste diese Lösung wahrscheinlich auch Wake-Locks verwenden, und das würde enorme Mengen an Batterie verbrauchen.
Paweł Nadolski

Ich denke, dass Sie in diesem Punkt Recht haben. Die einzige Frage ist: Was wäre das Schlimmste - unzuverlässiger Code oder schlechte Leistung? Jedenfalls denke ich persönlich, dass es alternative Möglichkeiten für die Sperre gibt , die in einigen Fällen geeignet sein können (zum Beispiel: stackoverflow.com/questions/5346694/… )
ymz
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.