5

Di seguito è riportata la funzione sendNotification che verrà chiamata da un servizio, sta funzionando correttamente creando una notifica e mostrandola sulla barra di stato. Ma quando l'app è già in esecuzione (sono a MainActivity), facendo clic sulla notifica per aprire ConversActivity, la MainActivity principale viene distrutta, e quando im premendo back button da ConversActivity, viene ricreata MainActivity. Per favore aiutatemi a evitare questo comportamento quando l'app è in esecuzione (in primo piano/sfondo)Android: Perché fare clic su notifica di intenti con backstack distrugge MainActivity principale?

Btw, questo è il comportamento corretto quando l'app viene uccisa o non in esecuzione, coz MainActivity viene creato dal backstack, che è corretto . Ma quando l'app è in esecuzione, perché MainActivity viene distrutto e ricreato? Ciò non è efficiente e causa lentezza nell'app a causa dell'avvio dell'app da parte di onCreate di MainActivity.

Grazie in anticipo & I migliori saluti.

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 (tasto indietro):

@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()); 
} 
+0

Avete controllato quando spostate ConversActivity in mainactivity, la vostra attività principale dovrebbe essere entrata in scena non in oncreate ?? – Mahi

+0

sì, ho inserito un log.d e eseguito il debug in onCreate e onDestroy di MainActivity, nel momento in cui clicco sulla notifica, vedo onDestroy viene attivato, quindi quando faccio clic su back-button da ConversActivity, onCreate viene attivato nuovamente . Potrebbe esserci qualcosa di sbagliato nel mio backstack e in attesaIntent? – hemlk

risposta

11

Guardando alla fonte codice, sembra che TaskStackBuilder aggiunge i seguenti flag alla radice attività Intent:

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

Se leggi il documentation su come impostare il comportamento di navigazione previsto dall'utente per le notifiche, sembra che ciò che vogliono che tu faccia è che la notifica crei una "nuova attività" che conterrà l'attività che stai lanciando e una parte appropriata -stack in modo che l'utente sia in grado di eseguire il backup tramite una copia "fresca" dell'applicazione nella schermata HOME. Temo che il comportamento standard di taskAffinity possa rendere impossibile conservare l'attività dell'app originale e avviarne un'altra dalla notifica. Questo potrebbe non essere quello che vuoi comunque.

Quello che sta succedendo qui è che, se la tua app è in esecuzione e fai clic sulla notifica, l'attività esistente viene portata in primo piano, cancellata (tutte le attività sono finite/distrutte) e quindi l'attività più in alto viene avviata questa attività (nel tuo caso ConversActivity). Il back stack viene quindi impostato in modo tale che se l'utente fa clic su BACK, ricrea le attività precedenti nel back stack, uno alla volta, finché l'utente non finisce nella schermata HOME.

Quanto sopra dovrebbe spiegare cosa sta succedendo e perché.

per risolvere il problema, io suggerirei di fare quanto segue:

Non impostare il backstack per la notifica. Basta che il lancio della notifica sia ConversActivity.

Nel ConversActivity.onCreate() effettuare le seguenti operazioni:

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

Questo dovrebbe Basta lanciare ConversActivity in cima alla vostra applicazione esistente (se è aperto), e dovrebbero lanciarlo con lo stack posteriore corretto se la vostra applicazione non è in esecuzione .

+1

omg im mi fa piacere che questo funzioni completamente per me, grazie grazie mille =)) – hemlk

0

Se il mainactivity non in esecuzione di quanto il tuo dati di notifica verranno in mainactivity di quanto si possa passare i dati da mainactivity a conversactivity.If mainactivity esecuzione tha i dati passare direttamente in conversactivity

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

fare qualche cambiamento nella vostra 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

ma quando sto facendo così, sto perdendo il mio backstack, questo è ok quando l'app è in esecuzione. Ma quando l'app viene uccisa (o quando premo il pulsante Indietro da MainActivity), quindi premendo Back Button da ConversActivity tornerò direttamente alla schermata principale. (Invia notifica viene chiamato da un servizio) – hemlk

+0

grazie Montu, ho avuto l'idea, proverò per vedere come ... – hemlk

+0

ciao Montu, in qualche modo isMainActivityRunning restituisce sempre false per me, notare che sto eseguendo sendNotification da un servizio, e il contesto passato a sendNotification proviene da [getApplicationContext()]. I addwatch isMainActivityRunning da MainActivity restituisce true, ma Log.d per sendNotification mostra sempre "false" per isMainActivityRunning. C'è qualcosa di sbagliato nell'ottenere il valore di isMainActivityRunning da un servizio. – hemlk