Frage Android: Warum wird durch Klicken auf die Absichtsmitteilung mit Backstack die MainActivity überschrieben?


Im Folgenden finden Sie meine sendNotification-Funktion, die von einem Service aufgerufen wird. Es funktioniert einwandfrei, indem eine Benachrichtigung erstellt und in der Statusleiste angezeigt wird. Aber wenn die App bereits läuft (ich bin bei MainActivity), klicke ich auf die Benachrichtigung, um ConversActivity zu öffnen, die übergeordnete MainActivity wird zerstört, und wenn ich die Zurück-Taste von ConversActivity drücke, wird MainActivity neu erstellt. Bitte helfen Sie mir, dieses Verhalten zu vermeiden, wenn die App läuft (entweder im Vordergrund / im Hintergrund)

Übrigens, das ist das richtige Verhalten, wenn die App beendet wird oder nicht läuft, coz MainActivity wird aus dem Backstack erstellt, was korrekt ist. Warum wird MainActivity bei der Ausführung der App zerstört und neu erstellt? Dies ist nicht effizient und verursacht aufgrund der App-Initiierung von MainActivity onCreate Langsamkeit in der App.

Danke im voraus Viele Grüße.

AndroidManifest.xml:

<activity
        android:name=".View.MainActivity"
        android:hardwareAccelerated="true"
        android:windowSoftInputMode="stateHidden"
        android:launchMode="singleTop"
        android:label="@string/app_name"
        android:screenOrientation="portrait"
        android:theme="@android:style/Theme.Black.NoTitleBar" >
        <intent-filter>
            <action android:name="android.intent.action.MAIN" />
            <category android:name="android.intent.category.LAUNCHER" />
        </intent-filter>
</activity>


<activity
        android:name=".View.ConversActivity"
        android:label="@string/title_activity_convers"
        android:parentActivityName=".View.MainActivity"
        android:screenOrientation="portrait"
        android:windowSoftInputMode="stateHidden|adjustResize" >
        <meta-data
            android:name="android.support.PARENT_ACTIVITY"
            android:value=".View.MainActivity"/>
</activity>

-

ConversActivity.java (Zurück-Schaltfläche):

@Override
public boolean onOptionsItemSelected(MenuItem item) {
    // Handle action bar item clicks here. The action bar will
    // automatically handle clicks on the Home/Up button, so long
    // as you specify a parent activity in AndroidManifest.xml.
    switch (item.getItemId()) {
        case android.R.id.home:
            //onBackPressed();
            //finish();
            NavUtils.navigateUpFromSameTask(this);
            return true;
        case R.id.action_settings:
            return true;
    }
    return super.onOptionsItemSelected(item);
}

-

public static void sendNotification(Context context, String dname) {
    NotificationManager mNotificationManager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
    Intent intent = new Intent(context, ConversActivity.class);
    intent.putExtra("dname", dname);

    PendingIntent pendingIntent = TaskStackBuilder.create(context)
                    // add all of DetailsActivity's parents to the stack,
                    // followed by DetailsActivity itself
                    .addNextIntentWithParentStack(intent)
                    .getPendingIntent(0, PendingIntent.FLAG_UPDATE_CURRENT);

    NotificationCompat.Builder mBuilder =
            new NotificationCompat.Builder(context)
                    .setSmallIcon(R.drawable.ic_launcher)
                    .setContentTitle("You've got a message!")
                    .setStyle(new NotificationCompat.BigTextStyle().bigText("@" + dname + ": " + msg))
                    .setContentText("@" + dname + ": " + msg)
                    .setAutoCancel(true)
                    .setVibrate(new long[]{100, 100}) //off-on-off-on-off
                    .setLights(Color.GREEN, 3000, 3000)
                    .setSound(Settings.System.DEFAULT_NOTIFICATION_URI);
    ;
    mBuilder.setContentIntent(pendingIntent);
    mNotificationManager.notify(dname, 0, mBuilder.build());
}

5
2017-12-12 10:16


Ursprung


Antworten:


Mit Blick auf den Quellcode sieht es so aus TaskStackBuilder Fügt der Root-Aktivität die folgenden Flags hinzu Intent:

    intents[0].addFlags(Intent.FLAG_ACTIVITY_NEW_TASK |
            IntentCompat.FLAG_ACTIVITY_CLEAR_TASK |
            IntentCompat.FLAG_ACTIVITY_TASK_ON_HOME);

Wenn du das liest Dokumentation Wie Sie das erwartete Navigationsverhalten des Benutzers für Benachrichtigungen einrichten, scheint es so zu sein, dass Sie mit der Benachrichtigung eine "neue Aufgabe" erstellen müssen, die die Aktivität, die Sie starten, und einen entsprechenden Backstack für den Benutzer enthält können durch eine "frische" Kopie Ihrer Anwendung zurück auf den Startbildschirm gesichert werden. Ich habe Angst, dass das Standardverhalten von taskAffinity Es kann dazu führen, dass es unmöglich wird, die Aufgabe Ihrer ursprünglichen App beizubehalten und auch eine andere aus der Benachrichtigung zu starten. Das ist vielleicht nicht das, was du willst.

Was passiert hier, wenn Ihre App läuft und Sie auf die Benachrichtigung klicken, wird die bestehende Aufgabe in den Vordergrund gebracht, gelöscht (alle Aktivitäten werden beendet / zerstört) und dann wird die oberste Aktivität in diese Aufgabe gestartet (in dein Fall ConversActivity). Der Backstack wird dann so eingerichtet, dass der Benutzer, wenn er auf BACK klickt, die vorherigen Aktivitäten im Backstack einzeln nacheinander neu erstellt, bis der Benutzer auf dem HOME-Bildschirm landet.

Das obige sollte erklären, was passiert und warum.

Um Ihr Problem zu lösen, würde ich Folgendes vorschlagen:

Richten Sie den Backstack für die Benachrichtigung nicht ein. Lassen Sie einfach die Benachrichtigung starten ConversActivity.

Im ConversActivity.onCreate() Mach Folgendes:

super.onCreate(...);
if (isTaskRoot()) {
    // Started from a Notification and the app is not running, restart the app with back stack
    // Here create a launch Intent which includes the back stack
    Intent intent = new Intent(this, ConversActivity.class);
    // Copy extras from incoming Intent
    intent.putExtras(getIntent());
    // Now launch this activity again and immediately return
    TaskStackBuilder.create(this)
        .addNextIntentWithParentStack(intent)
        .startActivities();
    return;
}

Dies sollte nur starten ConversActivity oben auf Ihrer vorhandenen App (wenn es geöffnet ist), und sollte es mit dem richtigen Backstack starten, wenn Ihre App nicht ausgeführt wird.


11
2017-12-16 20:29



Wenn Ihre Hauptaktivität, die nicht als Ihre Benachrichtigungsdaten ausgeführt wird, in die Hauptaktivität gelangt, können Sie Daten von der Hauptaktivität zur Konversationsaktivität übertragen. Wenn die Hauptaktivität ausgeführt wird, leiten Ihre Daten direkt die Konversation ein

 public class MainActivity extends Activity

 {
  public static boolean isMainActivityRunning;

@Override
protected void onCreate(Bundle savedInstanceState) {
    // TODO Auto-generated method stub
    super.onCreate(savedInstanceState);
}

@Override
protected void onResume() {
    // TODO Auto-generated method stub
    super.onResume();

    isMainActivityRunning = true;
}

@Override
protected void onDestroy() {
    // TODO Auto-generated method stub
    super.onDestroy();

    isMainActivityRunning = false;
}
}

Ändere etwas in deinem PendingIntent

 NotificationManager mNotificationManager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
 Intent intent=null;
 if(!MainActivity.isMainActivityRunning){
 intent = new Intent(context, MainActivity.class);
 }
else{
 intent = new Intent(context, ConversActivity.class);
 }

intent.putExtra("dname", dname);
int requestID = (int) System.currentTimeMillis();
PendingIntent mContentIntent = PendingIntent.getActivity(mContext,
                    requestID , intent , Intent.FILL_IN_ACTION);

0
2017-12-12 11:35