Kliknięcie powiadomienia: czynność już otwarta

164

Mam aplikację z powiadomieniami, które otwierają określoną aktywność, jeśli je kliknę. Chcę, aby jeśli kliknę powiadomienie, a działanie jest już otwarte, nie zostanie uruchomione ponownie, ale po prostu przeniesione na wierzch.

Myślałem, że mogę to zrobić z flagą FLAG_ACTIVITY_BROUGHT_TO_FRONTlub FLAG_ACTIVITY_REORDER_TO_FRONT, ale wciąż ją otwiera, więc mam aktywność dwukrotnie.

To jest mój kod:

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

Czy mogę zarządzać tym za pomocą flag, czy powinienem przechowywać zmienną w SharedPreferences, aby sprawdzić, czy jest otwarta, czy nie?

Dzięki!

PX Developer
źródło
1
Używam intent.setFlags (Intent.FLAG_ACTIVITY_SINGLE_TOP | Intent.FLAG_ACTIVITY_NO_HISTORY);
ashraful

Odpowiedzi:

298

Musisz ustawić launchModeatrybut tego, od Activityktórego zaczynasz singleTop. Spowoduje to, że przychodzące intencje zostaną dostarczone do istniejącej instancji, zamiast uruchamiać nową instancję, która Activityznajduje się już na szczycie stosu zadania.

Odbywa się to w manifeście przez dodanie android:launchMode="singleTop"do <activity>elementu. Aby uzyskać dostęp do najnowszej intencji (jeśli interesują Cię jakiekolwiek dane, które mogły z nią przejść), nadpisz onNewIntent()w pliku Activity.

Devunwired
źródło
6
Napotkałem wiele odpowiedzi, które mówiły, że ustawiają flagę intencji w różnych sprawach. To nie zadziałało. Czy to dlatego, że intencja, niezależnie od jej flagi, zmierza do nowo utworzonego działania? Pytam, ponieważ Devunwired powiedział, że atrybut launchMode zmienia się tam, gdzie są dostarczane intencje.
lululoo
5
Strona dokumentacji znajduje się pod adresem developer.android.com/guide/topics/manifest/ ...
Mifeng,
1
Widzę, że jeśli zastosujesz to podejście do działania uruchamianego z ekranu głównego, to za każdym razem, gdy uruchomisz aplikację, rozpocznie się aktywność root, niszcząc wszystkie działania, które wcześniej były wyświetlane na górze. Z pewnością nie jest to oczekiwane zachowanie użytkownika, który umieszcza aplikację w tle podczas wykonywania innego działania i ponownie ją otwiera.
niemiecki
38

Spróbuj Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_SINGLE_TOPzamiast tego ustawić flagi na .

Z dokumentacji dla FLAG_ACTIVITY_CLEAR_TOP (moje wyróżnienie ):

Jeśli jest ustawiona, a uruchamiane działanie jest już uruchomione w bieżącym zadaniu, to zamiast uruchamiać nowe wystąpienie tego działania, wszystkie inne działania na nim zostaną zamknięte, a ta intencja zostanie dostarczona do (teraz do góry) stara aktywność jako nowa intencja.

Na przykład rozważmy zadanie składające się z działań: A, B, C, D.Jeśli D wywołuje startActivity () z intencją, która odpowiada komponentowi działania B, wtedy C i D zostaną zakończone, a B otrzyma podaną intencję , w wyniku czego stos jest teraz: A, B.

Aktualnie działające wystąpienie działania B w powyższym przykładzie otrzyma nową intencję, którą tu rozpoczynasz, w metodzie onNewIntent () lub zostanie zakończone i uruchomione ponownie z nową intencją. Jeśli zadeklarował tryb uruchamiania jako „wiele” (domyślny) i nie ustawiłeś FLAG_ACTIVITY_SINGLE_TOP w tym samym celu, zostanie zakończony i ponownie utworzony; dla wszystkich innych trybów uruchamiania lub jeśli ustawiono FLAG_ACTIVITY_SINGLE_TOP, to intencja zostanie dostarczona do onNewIntent () bieżącej instancji.

cicha mięta
źródło
1
To jest to, czego potrzebowałem. Wystarczy dodać opis, który musimy dodać do tej flagi intencją: new Intent(this, getClass()).addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_SINGLE_TOP).
Morteza Rastgoo
6

Posługiwać się onNewIntent() do obsługi nowych danych z powiadomienia, kliknij i odśwież aktywność.

W onNewIntentuzyskaniu nowych danych z nowej intencji (której służyło nowe powiadomienie) i złapaniu ich np .:

title = intent.getStringExtra("title")

w onCreate poprzednio :)

Odświeży obecną aktywność nowymi danymi powiadomień.

Możesz również skorzystać z tego samouczka.

Afjalur Rahman Rana
źródło
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());

Po prostu skopiuj kod i wklej go w swojej głównej aktywności programu uruchamiającego.

Oto oryginalna odpowiedź

Społeczność
źródło
0

Myślę, że powinieneś dodać trochę logiki, aby to działało, może to pomoże:

Na przykład mam ekran powitalny (Launcher i MAIN) aplikacji:

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

    }

}

W mojej usłudze FirebaseService wykonałem następujące czynności:

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

    }

}
Carlos Alberto Gonzalez
źródło
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);
Manjunath
źródło
4
Wyjaśnij, w jaki sposób Twój kod pomaga rozwiązać problem, o którym mowa w pytaniu. Może to nie być oczywiste dla innych czytelników, którzy mają takie same / podobne problemy.
NIE,