I have an Activity that is defined to be singleTop so that only the one instance will exist.
<activity
android:name=".MyMainActivity"
android:label="#string/app_name"
android:configChanges="keyboard|keyboardHidden|orientation|screenSize"
android:launchMode="singleTop" android:multiprocess="true">
I set up a Notification Intent with some data, and include it in a PendingIntent, and send it to the Notification Manager.
Intent notificationIntent = new Intent(context, MyMainActivity.class);
notificationIntent.setAction(MyMainActivity.CustomInternalMessageAction);
notificationIntent.putExtra(MyMainActivity.ReceiveTestMessage, rawMessageText);
...
PendingIntent contentIntent = PendingIntent.getActivity(context, 0, notificationIntent, 0);
mNotificationManager.notify(number, notification);
If the actiivty is not running, the intent starts the activity via onCreate() as expected.
If The activity is running, but in the stopped state / not in foreground (like when clicking the home button), and the notification is clicked, my activity's onNewIntent() is called as expected.
However, if the Activity is already called when it's in the foreground, then onNewIntent() doesn't get called.
How can I set up this notificaiton so that my singleTop Activity gets sent the intent, when it's in the pause/stop state (and also still functions in the other cases I mentioned). I'm thinking there's a flag to set on my notificationIntent object, but the functions of the flags aren't really clear for the case of singleTop activities.
If your application is composed by more than one activity, the remain activities need to be defined as singleTop as well if you want to receive a onNewIntent()call when that activity is active.
Let suppose that main activity is A and is defined as singleTop and from there you start activity B not defined as singleTop. If now you select a notification that calls your application, the application will start on activity B but onNewIntent() is not called.
You can also override this behaviour adding the flag Intent.FLAG_ACTIVITY_CLEAR_TOP which remove activity B from stack and Activity A will recive the call on onNewIntent().
Related
Neither
val intent = Intent(sourceActivity, SomeActivity::class.java).addFlags(Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TOP)
startActivity(intent)
nor
val intent = Intent(sourceActivity, SomeActivity::class.java).addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
startActivity(intent)
triggers onNewIntent as described by official docs:
FLAG_ACTIVITY_NEW_TASK Start the activity in a new task. If a task is
already running for the activity you are now starting, that task is
brought to the foreground with its last state restored and the
activity receives the new intent in onNewIntent(). This produces the
same behavior as the "singleTask" launchMode value, discussed in the previous section.
They always try to recreate SomeActivity, calling onCreate instead!
Expected behaviours:
SomeActivity, running but not on foreground, paused, is brought back to foreground
SomeActivity's back stack is preserved
SomeActivity receives some info - I want to inform SomeActivity of a success/ failure
SomeActivity instance is reused vs. a duplicated is created anew - so FLAG_ACTIVITY_SINGLE_TOP or android:launchMode="singleTop" is not derisable
Interestingly, the Manifest.xml approach works as expected!
<activity
android:name=".webview.SomeActivity"
android:launchMode="singleTask"
android:configChanges="screenSize|orientation" />
What am I missing?
This has worked for me :
intent = new Intent(this, HomeScreenActivity.class);
intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK);
If this still doesn't work and you want to clear all activities before starting a new one you can use finishAffinity() before starting a new activity.
This is the code I use to create the PendingIntent for my notification.
Intent notificationIntent = new Intent(context, Activity1.class);
PendingIntent myIntent = PendingIntent.getActivity(context, 0,notificationIntent, 0);
This PendingIntent launches Activity1 when the notification is click.
How can I simply reopen the app and go to the most recent Activity (as though clicking on the launcher icon) instead of launching a new Activity when the notification is clicked?
Activity1 is just an example. I have multiple Activity in the app. I just want to reopen the app and go to the most recent Activity
NOTE: this looks like wrong design for me, because notification should allow user to enter activity that is in context with the notification.
Technically, you can create redirecting activity and your notification intent should launch it when tapped. In its onCreate() you check what activity you want user to be redirected (you can keep this info in SharedPreferences, and each activity would write this info in onCreate() (or make that in your base class if you have it). Then in redirector you call regular startActivity() to go last activity and call finish() to conclude your redirector. Moreover, your redirector activity does not need any layout so add
android:theme="#android:style/Theme.NoDisplay"
to its Manifest entry (of course you also need no call to setContentView())
create Activity1 as a singletask activity , by changing the launchMode of the activity to singleTask...
set your activity to launchMode="singleTop" in your Manifest.xml then use this code instead of what you are using above to reopen the active one:
Title = "YourAppName";
Text = "open";
notificationIntent = new Intent(this, Activity1.class);
cIntent = PendingIntent.getActivity(this, 0, notificationIntent, 0);
notification.setLatestEventInfo(getApplicationContext(), Title, Text, cIntent);
You can change the android:launchMode in the manifest file for the activity targeted by the pending intent.
Typically, you can use singleTop, which will reuse the same instance when the targeted activity is already on top of the task stack (i.e.: Activity is shown before you left your app).
You can also consider SingleTask and SingleInstance, if you want to keep only a single instance of the activity.
I have a singleTop activity, this activity is launched via Intent:
Intent intent = new Intent(GCMIntentService.this,MainActivity.class);
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
onNewIntent is called.
My problem is that then I hit home button, and then launch application again (from background) onNewIntent is called again with the same intent, and I can not find a way to discard this Intent.
I tried to putExtra flag to this intent, but it is not persisted between application state changes.
Is it possible to stop calling onNewIntent() when application comes to foreground?
In your manifest add the line below to your MainActivity
android:finishOnTaskLaunch="true"
guess I'm having some misunderstandigs with the Intent Flags.. What I'm trying to do is, I'm having a radio streaming applications, which has two Activities (PlayerApplication and SettingsScreen). I have a Service.class for Streaming which runs in the background, which holds a Notification as well (you can stop/start playback in the notification-overlay menu and the PlayerApplication). If the User clicks on the Notification, the PlayerApplicationActivity should be com back to screen.
Everything works fine, expect the case: User opens SettingsScreenActivity -> opens NotificationOverlayMenu -> clicks at Notification -> PendingIntent resumes to PlayerApplicationActivity
Now, PlayerApplicationScreen is there, but I cannot click anything. I see, that the onCreate() of my PlayerApplication isn't triggered, if I resume from Notification. But the layout looks fine (also inflated in the onCreate())
I used following PendingIntent in the Service.class:
PendingIntent contentIntent = PendingIntent.getActivity(
this.getApplicationContext(), //Service.class
0,
new Intent(this,PlayerApplicationActivity.class)
.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP
| Intent.FLAG_ACTIVITY_SINGLE_TOP),
0);
So actually the PendingIntent should bring the Activity (if already running) back to the top. Am I using wrong Intents or am I missing a point?
EDIT:
and I declared launchMode in Manifest.xml
android:launchMode="singleTask"
According to android developer site, In FLAG_ACTIVITY_CLEAR_TOP,FLAG_ACTIVITY_SINGLE_TOP and in launch mode : SingleTask , If the instance of activity you are calling is already running then instead of creating new instance, it call onNewIntent() method. So I think you should check this condition that your activity is running when onCreate() is not calling.
I just figured out what I was doing wrong:
For my purpose I used the wrong launchMode. Right one is singleTop not singleTask
I declared the launchMode in the <application-node> instead of the <activity-node>
//Manifest.xml
<activity
android:name="..."
android:launchMode="singleTop" >
I have an activity called MainActivity. This activity launches a notification that has a PendingIntent that opens this MainActivity.
So, to close the application, I have to click the back button twice. I would like to set up activity as singleton. I tried to set singleInstance or singleTask to manifest but this doesn't work.
singleInstance and singleTask are not recommended for general use.
Try:
android:launchMode="singleTop"
For more information please refer to launchMode section of the Activity element documentation.
In addition to the previous reference you should also read tasks and back stack
If you need to return to your app without creating a new instance of your activity, you can use the same intent filters as android uses when launching the app:
final Intent notificationIntent = new Intent(context, MainActivity.class);
notificationIntent.setAction(Intent.ACTION_MAIN);
notificationIntent.addCategory(Intent.CATEGORY_LAUNCHER);
PendingIntent contentIntent = PendingIntent.getActivity(this, 0, notificationIntent, 0);
As the intent you created to open your activity from the notification bar is the same as android used for launching your app, the previously opened activity will be shown instead of creating a new one.