Absicht - Wenn eine Aktivität ausgeführt wird, bringen Sie sie in den Vordergrund, andernfalls starten Sie eine neue (ab Benachrichtigung).

129

Meine App verfügt über Benachrichtigungen, die - offensichtlich - ohne Flaggen jedes Mal eine neue Aktivität starten, sodass mehrere gleiche Aktivitäten übereinander ausgeführt werden, was einfach falsch ist.

Ich möchte, dass die in den anstehenden Absichten für Benachrichtigungen angegebene Aktivität nach vorne gebracht wird, wenn sie bereits ausgeführt wird, andernfalls wird sie gestartet.

Bisher ist die Absicht / ausstehende Absicht für diese Benachrichtigung, die ich habe,

private static PendingIntent prepareIntent(Context context) {
    Intent intent = new Intent(context, MainActivity.class);
    intent.setFlags(Intent.FLAG_ACTIVITY_REORDER_TO_FRONT);

    return PendingIntent.getActivity(context, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT);
}

und seltsamerweise funktioniert es manchmal, manchmal nicht ... Ich habe das Gefühl, ich habe bereits jede einzelne Kombination von Flaggen ausprobiert.

urSus
quelle

Antworten:

131

Sie können dies verwenden:

<activity 
   android:name=".YourActivity"
   android:launchMode="singleTask"/>

Das wird ähnlich funktionieren, "singleInstance"aber es wird nicht diese seltsame Animation haben.

Franco
quelle
15
+1, du solltest die akzeptierte Antwort sein. Unterschiede sind hier: developer.android.com/guide/topics/manifest/…
user1032613
1
Verwenden Sie zur Verdeutlichung singleTask, wenn Sie mehrere Aktivitäten in der App haben, und dies ist die übergeordnete, singleInstance, wenn Sie nur eine Aktivität haben.
frostymarvelous
4
Wenn jemand wie ich viele Lösungskombinationen ausprobiert hat, bevor er auf dieser Website gelandet ist: Entfernen Sie andere Änderungen, die Sie versucht haben, und stellen Sie sicher, dass Sie diese Änderung an der richtigen Aktivität vornehmen. Ich habe viel zu lange onNewIntent
gebraucht
Ich habe eine Karte von Messenger, Aktivitätspaar. Ich möchte die Aktivitätsinstanz anzeigen, wenn ich eine Nachricht von ihr erhalte. Gibt es eine Möglichkeit, dies zu tun? Beispiel: HashMap.get (Messenger) .bringActivityToFront (); Ich meine, die Aktivität läuft noch. Wenn ich die letzte Aufgabe öffne und darauf klicke, wird onResume () angezeigt. Kann ich nicht onResume () programmatisch.
@JaveneCPPMcGowan das scheint eine ganz andere Frage zu sein, ich schlage vor, Sie posten, dass ich als eigene Frage die Antwort leider nicht wirklich kenne.
Franco
46

Ich denke, der beste Weg, dies auf einfache Weise zu tun, besteht darin, die Aktivität normal zu starten, diese Aktivität jedoch im Manifest mit der singleInstanceEigenschaft festzulegen. Damit nähern Sie sich praktisch beiden Problemen, die Sie gerade haben, indem Sie die Aktivität ständig in den Vordergrund stellen und das Betriebssystem automatisch eine neue erstellen lassen, wenn keine Aktivität vorhanden ist, oder die aktuell vorhandene Aktivität in den Vordergrund stellen (dank der singleInstanceEigentum).

Auf diese Weise wird eine Aktivität als einzelne Instanz deklariert:

<activity 
   android:name=".YourActivity"
   android:launchMode="singleInstance"/>

Um eine abgehackte Animation beim Starten über singleInstance zu vermeiden, können Sie stattdessen "singleTask" verwenden. Beide sind sehr ähnlich, aber der Unterschied wird hier gemäß der Google-Dokumentation erläutert:

<activity 
   android:name=".YourActivity"
   android:launchMode="singleTask"/>

singleInstance ist dasselbe wie "singleTask", außer dass das System keine anderen Aktivitäten in die Task startet, die die Instanz enthält. Die Aktivität ist immer das einzige und einzige Mitglied ihrer Aufgabe.

Hoffe das hilft.

Grüße!

Martin Cazares
quelle
4
es scheint zu funktionieren, aber jetzt spielt jede andere neue Aktivität, die ich von der singleIntent MainActivity aus starte, diese seltsame Lichtbogenanimation anstelle der regulären Fade & Scale
urSus
Was ist, wenn ich jedes Mal eine neue Aktivität starte, aber alle anderen laufenden Instanzen davon lösche? Wäre das möglich?
urSus
Nun, ich glaube nicht, dass die Animation, die Sie erwähnen, etwas mit der Eigenschaft "singleInstance" zu tun hat. Alles, was sie tut, ist die Wiederverwendung vorhandener Instanzen. Vielleicht ist die Animation, über die Sie sprechen, ein völlig anderes Problem ...
Martin Cazares
1
Nun, ich teste es gerade und es tut es. Wenn ich alle Intent-Flags entferne und einfach den launchMode = "singleInstance" im Manifest setze, ist die seltsame Animation da, wenn ich sie entferne, ist sie wieder normal
urSus
Ja, laut Android-Dokumentation scheint die "init" -Animation nicht mehr wie gewohnt vorhanden zu sein, da die Aktivität nicht initialisiert wird, sondern nur wiederverwendet wird ...
Martin Cazares
26

Ich denke, was Sie brauchen, ist singleTop Activityeher als ein singleTaskoder singleInstance.

<activity android:name=".MyActivity"
          android:launchMode="singleTop"
          ...the rest... >

Was in der Dokumentation steht, passt perfekt zu Ihren Anforderungen:

[...] Es kann auch eine neue Instanz einer " singleTop" Aktivität erstellt werden, um eine neue Absicht zu behandeln. Wenn die Zielaufgabe jedoch bereits eine vorhandene Instanz der Aktivität oben auf ihrem Stapel hat, erhält diese Instanz die neue Absicht (in einem onNewIntent()Aufruf). Eine neue Instanz wird nicht erstellt. Unter anderen Umständen - zum Beispiel, wenn sich eine vorhandene Instanz der singleTopAktivität " " in der Zielaufgabe befindet, jedoch nicht am oberen Rand des Stapels oder wenn sie sich am oberen Rand eines Stapels befindet, jedoch nicht in der Zielaufgabe - eine neue Instanz würde erstellt und auf den Stapel geschoben.

Darüber hinaus (kein Wortspiel beabsichtigt) hatte ich genau das gleiche Bedürfnis wie Sie. Ich habe alle getestetlaunchMode Flags , um herauszufinden, wie sie sich in der Praxis tatsächlich verhalten. Daher singleTopist dies das Beste: Keine seltsame Animation, App wird einmal in der Liste der letzten Anwendungen angezeigt (im Gegensatz dazu singleInstancewird sie zweimal angezeigt , da dies nicht der Fall ist.) t zulassen, dass ein anderer ActivityTeil seiner Aufgabe ist) und sich richtig verhält, unabhängig davon, ob das Ziel Activitybereits existiert oder nicht.

Shlublu
quelle
2
Am Freitagabend bis 22 Uhr arbeiten und das ist es, was ich will ... Trauriges Entwicklerleben.
felixwcf
Hat viel Zeit gespart! Danke dir!
Hetsgandhi
13

Dies ist ein alter Thread, aber für alle, die noch nach einer Antwort suchen, ist hier meine Lösung. Es ist rein im Code, ohne Manifest-Einstellungen:

private static PendingIntent prepareIntent(Context context) {
  Intent intent = new Intent(context, MainActivity.class);
  intent.setFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP | Intent.FLAG_ACTIVITY_CLEAR_TOP);      
  return PendingIntent.getActivity(context, NON_ZERO_REQUEST_CODE, intent, 
    PendingIntent.FLAG_UPDATE_CURRENT);
}

Hier öffnet FLAG_ACTIVITY_SINGLE_TOP vorhandene Aktivitäten, wenn sie sich oben im Taskstapel befinden. Wenn es sich nicht oben, sondern im Stapel befindet, entfernt FLAG_ACTIVITY_CLEAR_TOP alle Aktivitäten über der Zielaktivität und zeigt sie an. Wenn sich die Aktivität nicht im Aufgabenstapel befindet, wird eine neue erstellt. Ein entscheidender Punkt, den es zu erwähnen gilt - der zweite Parameter von PendingIntent.getActivity (), dh requestCode sollte einen Wert ungleich Null haben (ich habe ihn in meinem Snippet sogar NON_ZERO_REQUEST_CODE genannt), sonst funktionieren diese Intent-Flags nicht. Ich habe keine Ahnung, warum es so ist wie es ist. Das Flag FLAG_ACTIVITY_SINGLE_TOP ist austauschbar mit Android: launchMode = "singleTop" im Aktivitäts-Tag im Manifest.

Andrey Koretskyy
quelle
Ich habe seit Stunden mit diesen Flaggen gekämpft und mich gefragt, warum das Ändern meiner Absichtsflaggen nichts geändert hat. Anforderungscode ungleich Null ... ein entscheidender Punkt, den man erwähnen sollte !!! Funktioniert jetzt! Danke dir!
Max Power
9

Ich weiß, dass es alt ist, aber nichts von dem oben genannten passte zu meiner Bewerbung.

Ohne Änderungen an Manifesten und anderen Konfigurationen finden Sie hier den Code, mit dem Sie Ihre App wieder nach vorne bringen oder öffnen können, wenn sie geschlossen wird

Intent notificationIntent = context.getPackageManager().getLaunchIntentForPackage(context.getPackageName());
notificationIntent.setPackage(null); // The golden row !!!
notificationIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED);
Raziza O.
quelle
Das ist die wahre Antwort!
Azizbekian
2
Nein, es funktioniert nicht - es wird eine neue Aktivität zusätzlich zur aktuellen hinzugefügt.
Tobliug
3

Ich habe es versucht und es hat funktioniert, obwohl sich die IDE über den Code beschwert hat

Intent notificationIntent = new Intent(THIS_CONTEXT, MainActivity.class);
    notificationIntent.setFlags(Intent.FLAG_ACTIVITY_REORDER_TO_FRONT);
    PendingIntent intent = PendingIntent.getActivity(THIS_CONTEXT, 0, notificationIntent, Intent.FLAG_ACTIVITY_REORDER_TO_FRONT);

    NotificationCompat.Builder mBuilder = new NotificationCompat.Builder(THIS_CONTEXT)
            .setSmallIcon(R.drawable.cast_ic_notification_0)
            .setContentTitle("Title")
            .setContentText("Content")
            .setContentIntent(intent)
            .setPriority(PRIORITY_HIGH) //private static final PRIORITY_HIGH = 5;
            .setAutoCancel(true)
            /*.setDefaults(Notification.DEFAULT_SOUND | Notification.DEFAULT_VIBRATE | Notification.DEFAULT_LIGHTS)*/;
    NotificationManager mNotificationManager = (NotificationManager) THIS_CONTEXT.getSystemService(Context.NOTIFICATION_SERVICE);
    mNotificationManager.notify(0, mBuilder.build());
Nada
quelle
2
<Aktivität android: name = ". MainActivity" android: launchMode = "singleTask">
nada
Intent.FLAG_ACTIVITY_REORDER_TO_FRONTkeine gültige Flag für sichPendingINtent.getActivity
rds
@rds Kannst du die Quelle verlinken?
Louis CAD
@ LouisCAD Es tut mir leid, ich habe keinen Zugriff mehr auf den Quellcode
nada
@rds Ich frage nicht nach dem Quellcode, sondern nach dem Link, wo Sie lesen, dass dies Intent.FLAG_ACTIVITY_REORDER_TO_FRONTkein gültiges Flag ist, wenn es als verwendet wird PendingIntent. Oder haben Sie vielleicht gemeint, dass es nicht gültig ist, an die getActivityMethode zu übergeben, sondern als IntentFlag verwendet wird, das dann als verwendet wird PendingIntent?
Louis CAD
2

Da Sie sagen, dass Sie Ihre Aktivität starten möchten, wenn sie noch nicht gestartet wurde, würde es Ihnen vielleicht nichts ausmachen, sie neu zu starten. Ich habe auch eine Menge Vorschläge und Flaggenkombinationen für die Absicht getestet. Dadurch wird immer die Aktivität, die Sie benötigen, in den Vordergrund gerückt, obwohl kein zuvor damit verbundener Status beibehalten wird.

intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK|Intent.FLAG_ACTIVITY_NEW_TASK);

Nur API11 +.

Fetter Shogun
quelle
0

Ich hatte ein ähnliches Problem, nachdem ich Benachrichtigungen hinzugefügt hatte, die auf der Android-Trainingsseite zu finden waren . Keine der anderen Antworten hier hat für mich funktioniert, aber diese Antwort hat für mich funktioniert. Zusammenfassung:

final Intent notificationIntent = new Intent(context, YourActivity.class);
notificationIntent.setAction(Intent.ACTION_MAIN);
notificationIntent.addCategory(Intent.CATEGORY_LAUNCHER);
notificationIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
gattsbr
quelle