Android: Why does clicking on a notification of intent with a backstack destroy the parent MainActivity?

Below is my sendNotification function, which will be called from the Service, it works fine by creating a notification and displaying it in the status bar. But when the application is already running (I'm in MainActivity), by clicking on the notification to open ConversActivity, the parent MainActivity will be destroyed, and when im clicks the return button from ConversActivity, MainActivity is recreated. Please help me avoid this behavior when the application is running (either in focus / background)

Btw, this is the correct behavior when the application is killed or does not work, due to which MainActivity is created from the backstack, which is correct. But when the application is running, why is MainActivity destroyed and recreated? This is inefficient and causes the application to become slow due to launching the application from MainActivity onCreate.

Thanks in advance and best regards.

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 (return button):

 @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 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
source share
2 answers

After looking at the source code, it looks like TaskStackBuilder adds the following flags to Intent root activity:

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

If you read the documentation on how to configure the user-expected navigation behavior for notifications, it seems that they want you to have the “Notification” create a “new task” that will contain the activity you started and the corresponding back stack so that the user can execute backup through the “new” copy of your application on the “HOME” screen. I am afraid that the standard behavior of taskAffinity may lead to the inability to save the original task of the application, as well as launch another notification. Perhaps this is not the way you want.

What happens here is that if your application is running and you click on the alert, the existing task is currently in the foreground, cleared (all kinds of activities are completed / destroyed), and then the top activity is launched into it (in your case ConversActivity ). Then the back stack is installed, so if the user presses the BACK button, he will recreate the previous actions in the background stack one at a time until the user finishes working on the HOME screen.

The above should explain what is happening and why.

To solve your problem, I suggest you do the following:

Do not set the stack for notification. Just run the ConversActivity alert.

In ConversActivity.onCreate() do the following:

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

This should simply launch ConversActivity on top of an existing application (if it is open) and run it with the correct stack if your application is not running.

+11
source

If mainactivity is not working, than your notification data will come to mainactivity, than you can transfer data from mainactivity to conversactivity. If mainactivity works, that data goes directly to 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; } } 

make some changes to your 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
source

Source: https://habr.com/ru/post/1208875/


All Articles