Benachrichtigungsklick: Aktivität bereits geöffnet


164

Ich habe eine Anwendung mit Benachrichtigungen, die eine bestimmte Aktivität öffnen, wenn ich darauf klicke. Ich möchte, dass, wenn ich auf die Benachrichtigung klicke und die Aktivität bereits geöffnet ist, sie nicht erneut gestartet, sondern nur nach vorne gebracht wird.

Ich dachte, ich könnte es mit der Flagge machen FLAG_ACTIVITY_BROUGHT_TO_FRONToder FLAG_ACTIVITY_REORDER_TO_FRONT, aber es öffnet sie immer wieder, so dass ich die Aktivität zweimal habe.

Das ist mein Code:

event_notification = new Notification(R.drawable.icon,
            mContext.getString(R.string.event_notif_message), System.currentTimeMillis()); 
Intent notificationIntent = new Intent(mContext, EventListActivity.class);
notificationIntent.setFlags(Intent.FLAG_ACTIVITY_BROUGHT_TO_FRONT);
sendNotification(event_notification, notificationIntent, mContext.getString(R.string.event_notif_title),
                body, Utils.PA_NOTIFICATIONS_ID);

Kann ich es mit Flags verwalten oder sollte ich eine Variable in SharedPreferences speichern, um zu überprüfen, ob sie geöffnet ist oder nicht?

Vielen Dank!


1
Ich verwende intent.setFlags (Intent.FLAG_ACTIVITY_SINGLE_TOP | Intent.FLAG_ACTIVITY_NO_HISTORY);
Ashraful

Antworten:


298

Sie müssen das launchModeAttribut festlegen , mit dem ActivitySie beginnen singleTop. Dies führt dazu, dass eingehende Absichten an die vorhandene Instanz übermittelt werden, anstatt eine neue Instanz zu starten, wenn sich diese Activitybereits oben im Stapel der Aufgabe befindet.

Dies erfolgt im Manifest durch Hinzufügen android:launchMode="singleTop"zum <activity>Element. Um auf die neueste Absicht zuzugreifen (wenn Sie an Daten interessiert sind, die möglicherweise übergeben wurden), überschreiben Sie onNewIntent()Ihre Activity.


6
Ich stieß auf viele Antworten, die besagten, dass die Flagge der Absicht auf verschiedene Dinge gesetzt wurde. Das hat nicht funktioniert. Liegt das daran, dass die Absicht, unabhängig von ihrer Flagge, zu einer neu erstellten Aktivität geht? Ich frage, weil Devunwired sagte, dass sich das launchMode-Attribut ändert, wo die Absichten geliefert werden.
Lululoo

5
Die Dokumentationsseite ist unter developer.android.com/guide/topics/manifest/…
Mifeng

1
Ich sehe, dass, wenn Sie diesen Ansatz für die Aktivität verwenden, die vom Startbildschirm aus gestartet wird, jedes Mal, wenn Sie die Anwendung starten, mit der Stammaktivität begonnen wird, wodurch alle Aktivitäten zerstört werden, die zuvor oben angezeigt wurden. Dies ist sicherlich kein erwartetes Verhalten für einen Benutzer, der die App während einer anderen Aktivität in den Hintergrund stellt und sie erneut öffnet.
Deutsch

38

Setzen Sie Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_SINGLE_TOPstattdessen die Flags auf .

Aus der Dokumentation zu FLAG_ACTIVITY_CLEAR_TOP (Schwerpunkt Mine):

Wenn diese Option festgelegt ist und die zu startende Aktivität bereits in der aktuellen Aufgabe ausgeführt wird, werden anstelle einer neuen Instanz dieser Aktivität alle anderen darüber liegenden Aktivitäten geschlossen und diese Absicht an die (jetzt) ​​übergeben top) alte Aktivität als neue Absicht.

Stellen Sie sich zum Beispiel eine Aufgabe vor, die aus den folgenden Aktivitäten besteht: A, B, C, D. Wenn D startActivity () mit einer Absicht aufruft, die in die Komponente der Aktivität B aufgelöst wird, werden C und D beendet und B erhält die angegebene Absicht , was dazu führt, dass der Stapel jetzt ist: A, B.

Die aktuell ausgeführte Instanz von Aktivität B im obigen Beispiel erhält entweder die neue Absicht, die Sie hier in ihrer onNewIntent () -Methode starten, oder wird selbst beendet und mit der neuen Absicht neu gestartet. Wenn der Startmodus als "mehrfach" (Standardeinstellung) deklariert wurde und Sie FLAG_ACTIVITY_SINGLE_TOP nicht in derselben Absicht festgelegt haben, wird er beendet und neu erstellt. Für alle anderen Startmodi oder wenn FLAG_ACTIVITY_SINGLE_TOP festgelegt ist, wird diese Absicht an onNewIntent () der aktuellen Instanz übergeben.


1
Das brauchte ich. Fügen Sie einfach eine Beschreibung hinzu, die wir benötigen, um diese Flags zur Absicht hinzuzufügen : new Intent(this, getClass()).addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_SINGLE_TOP).
Morteza Rastgoo

6

Verwenden Sie diese onNewIntent()Option, um neue Daten aus dem Benachrichtigungsklick zu verarbeiten, und aktualisieren Sie die Aktivität.

Holen Sie onNewIntentsich die neuen Daten aus der neuen Absicht (die von der neuen Benachrichtigung bereitgestellt wurde) und fangen Sie sie ab, zum Beispiel:

title = intent.getStringExtra("title")

in onCreatevorher :)

Die aktuelle Aktivität wird mit neuen Benachrichtigungsdaten aktualisiert.

Sie können diesem Tutorial auch folgen .


3
Notification.Builder mBuilder =
            new Notification.Builder(this)
            .setSmallIcon(R.drawable.cmplayer)
            .setContentTitle("CoderoMusicPlayer")
            .setContentText("PLayer0!");

    Intent resultIntent = new Intent(this, 

    AndroidBuildingMusicPlayerActivity.class);
        resultIntent.setAction(Intent.ACTION_MAIN);
        resultIntent.addCategory(Intent.CATEGORY_LAUNCHER);

        PendingIntent pendingIntent = PendingIntent.getActivity(this, 0,
                resultIntent, 0);

        mBuilder.setContentIntent(pendingIntent);
        NotificationManager mNotificationManager =
            (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
        mNotificationManager.notify(1, mBuilder.build());

Kopieren Sie einfach den Code und fügen Sie ihn in Ihre Hauptstartaktivität ein.

Hier ist die ursprüngliche Antwort


0

Ich denke, Sie sollten eine Logik hinzufügen, damit es funktioniert. Vielleicht kann dies helfen:

Zum Beispiel habe ich einen Begrüßungsbildschirm (Launcher und MAIN) von APP:

public class SplashScreen extends AppCompatActivity {
    private final int TIME_OUT = 2000;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_splash_screen);

        // Suscribirse al tema Notificaciones
        FirebaseMessaging.getInstance().subscribeToTopic("NOTA");
        if (getIntent().getExtras() != null) {
            if (getIntent().getExtras().size()>1){
                Intent home_activity = new Intent(getApplicationContext(), Home.class);
                home_activity.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
                if (getIntent().getExtras() != null) {
                    for (String key : getIntent().getExtras().keySet()) {
                        String value = "" + getIntent().getExtras().getString(key);
                        Log.d("TAG", key + "=" + value);
                        switch (key) {
                            case "url":
                                home_activity.putExtra("url", value);
                                break;
                        }
                    }
                }
                startActivity(home_activity);
                finish();

            }else{
                new Handler().postDelayed(new Runnable() {
                    @Override
                    public void run() {
                        try {
                            Intent home_activity = new Intent(getApplicationContext(), Home.class);
                            home_activity.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
                            startActivity(home_activity);
                            finish();
                        } catch (Exception ex) {
                            ex.printStackTrace();
                        }
                    }
                }, TIME_OUT);
            }


        } else {
            new Handler().postDelayed(new Runnable() {
                @Override
                public void run() {
                    try {
                        Intent home_activity = new Intent(getApplicationContext(), Home.class);
                        home_activity.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
                        startActivity(home_activity);
                        finish();
                    } catch (Exception ex) {
                        ex.printStackTrace();
                    }
                }
            }, TIME_OUT);
        }

    }

}

Und in meinem FirebaseService habe ich Folgendes getan:

public class FCMessagingService extends FirebaseMessagingService {

    private final String TAG = "PUSH";
    private String body = "";
    private static String _url = "";
    private static int numMessage = 0;

    @Override
    public void onMessageReceived(RemoteMessage remoteMessage) {
        super.onMessageReceived(remoteMessage);

        String from = remoteMessage.getFrom();
        Log.d(TAG, "Mensaje recibido de: " + from);

        if (remoteMessage.getNotification() != null) {
            Log.d(TAG, "Notificación: " + remoteMessage.getNotification().getBody());

            if (remoteMessage.getData().size() > 0) {
                Log.d(TAG, "Data: " + remoteMessage.getData());
                try {
                    JSONObject data = new JSONObject(remoteMessage.getData());
                    String url = data.getString("url");
                    Log.d(TAG, "onMessageReceived: \n" + "Extra Information: " + url);
                    this._url = url;
                    Log.d("_URL",_url);
                    mostrarNotificacion(remoteMessage.getNotification().getTitle(), remoteMessage.getNotification().getBody());
                    mensaje(url, remoteMessage.getNotification().getTitle(), remoteMessage.getNotification().getBody());
                } catch (JSONException e) {
                    e.printStackTrace();
                }
            }
        }



    }


    private void mensaje(String url, String title, String body){
        boolean acti =  Util.comprobarActivityALaVista(getApplicationContext(), "com.dev.android.subagan.MainActivity");
        if(acti){

            Intent imain = new Intent(MainActivity.URL);

            imain.putExtra("key_url",url);
            imain.putExtra("key_title",title);
            imain.putExtra("key_body",body);

            LocalBroadcastManager.getInstance(getApplicationContext()).sendBroadcast(imain);

        }else{

            Intent ihome = new Intent(Home.URL);

            ihome.putExtra("key_url",url);
            ihome.putExtra("key_title",title);
            ihome.putExtra("key_body",body);
            LocalBroadcastManager.getInstance(getApplicationContext()).sendBroadcast(ihome);

        }

    }




    private void mostrarNotificacion(String title, String body) {

        final int NOTIFICATION_ID = 3000;

        Intent intent = new Intent(this, MainActivity.class);
        intent.putExtra("url",_url);
        intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);


        PendingIntent pendingIntent = PendingIntent.getActivity(this, 0, intent,PendingIntent.FLAG_UPDATE_CURRENT | PendingIntent.FLAG_ONE_SHOT  );



        Uri soundUri = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION);

        NotificationCompat.Builder notificationBuilder = new NotificationCompat.Builder(this)
                .setSmallIcon(R.mipmap.ic_launcher)
                .setContentTitle(title)
                .setContentText(body)
                .setAutoCancel(true)
                .setSound(soundUri)
                .setTicker(body)
                .setContentIntent(pendingIntent);

        NotificationManager notificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
        notificationManager.notify(0, notificationBuilder.build());

    }

}

0
Intent intent = new Intent(this, MainActivity.class);
intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
PendingIntent contentIntent = PendingIntent.getActivity(this, new Random().nextInt(), intent, 0);

4
Bitte erläutern Sie, wie Ihr Code zur Lösung des in der Frage genannten Problems beiträgt. Dies ist für andere Leser, die mit denselben / ähnlichen Problemen konfrontiert sind, möglicherweise nicht offensichtlich.
NOhs
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.