Open an existing activity - mono for android - android

I am building a mono android app that receives notifications from GCM and opens an activity when then user clicks on the notification.
An issue is occurring when an instance of the activity the notification creates already exists and is the current active activity in the application. Upon clicking the notification a duplicate activity is created in the application. The issue is subtle as the new duplicate activity opens in the foreground and looks identical to previous activity, however when the user clicks the back button the duplicate activity is killed but the previous activity remains meaning the user has to click back button twice.
The following is current code used to generate notification and create an activity on click. I would hope the process would be something like, if activity exists then open existing activity else start new activity. Appreciate any help thank you.
void createNotification(string title, string desc)
{
//Create notification
var notificationManager = GetSystemService(Context.NotificationService) as NotificationManager;
//Create an intent to show ui
var uiIntent = new Intent(this, typeof(Messaging));
//Create the notification
var notification = new Notification(Android.Resource.Drawable.SymActionEmail, title);
notification.Defaults = NotificationDefaults.Sound;
//Auto cancel will remove the notification once the user touches it
notification.Flags = NotificationFlags.AutoCancel;
//Set the notification info
//we use the pending intent, passing our ui intent over which will get called
//when the notification is tapped.
notification.SetLatestEventInfo(this, title, desc, PendingIntent.GetActivity(this, 0, uiIntent, 0));
//Show the notification
notificationManager.Notify(1, notification);
}

Try this
Intent intent = new Intent(context, MyActivity.class);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_MULTIPLE_TASK);
startActivity(intent);

Related

On Notification Click put my app to background

I am working on an functionality where I get notification for POI (Point of Interest )while the user is navigating through Google Navigation app (used background service to get location update ).
scenario
1) User clicks navigate button from my app
2) He is taken to Google Navigation with data to navigate
3) Now user receives Notification for POI , then he clicks on it and he is taken to my app (my app brought to foreground , still Google Navigation i in background)
4) Now user is seeing my app , now he clicks the same notification , In this case I must put my app to background , so that use now sees Google Navigation
what i tried
Bringing my app to foreground is achieved , but putting my app to background on Notification click is not achieved .
moveTaskToBack(true) this is what I came across, but how can I implement this in Notification click
code
Intent intent = new Intent();
intent.setComponent(new ComponentName(getPackageName(), B_Activity.class.getName()));
intent.addFlags(Intent.FLAG_ACTIVITY_REORDER_TO_FRONT);
intent.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP);
intent.putExtra("toFront", toFront);
PendingIntent pendingIntent = PendingIntent.getActivity(this, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT);
moveTaskToBack(boolean bool) is a method Of Activity class . So you can only call it with activity reference. I don't thing that there is way to do it with intent . What you can do send a broadcast in notification intent, and then validate the intent in activity if its in foreground -> call movetaskBack().
If your B_Activity has no Ui . Then just set null component in Pending Intent.
Use Local Broadcast to notify your currently running activity to call moveTaskToBack().
Intent intent = new Intent();
intent.setAction("com.settaskback");//Your custom action goes here
LocalBroadcastManager.getInstance(this).sendBroadcast(intent);
Then send broadcast on notification click. The activity which will receive this broadcast will put task to background (only if its in forground)
final Intent broadcastIntent = new Intent("com.settaskback");
PendingIntent intent = PendingIntent.getBroadcast(getApplicationContext(), 0, broadcastIntent, PendingIntent.FLAG_UPDATE_CURRENT);
notificationBuilder.setContentIntent(intent);
notification = notificationBuilder.build();
notification.flags |= Notification.FLAG_AUTO_CANCEL;
NotificationManager mNotificationManager =
(NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
mNotificationManager.notify(1, notification);
You need to register a Local broadcast receiver for this action in Activity.
#Override
public void onReceive(Context context, Intent intent) {
if(somecondition){
moveTaskToBack(true);
}
}

Bringing activity back from foreground

I stuck in a problem.
Suppose there is an activity A
now, user press Home key, and put A into background.
now, after remaining in background for a while, it will generate a notification.
On clicking on that notification, it will bring back the exact same activity which was in the background.
Like, after pressing home key, if user start the application again by clicking on the icon or from the recent launched history, then android re-opens exactly last activity in it's previous state.
Here, I dont want to detect which was the last activity. My activity is fixed, I just want to bring it back at its previous state on clicking on the notification ?
Is that possible ? how to do that ?
here is my code for notification,
private void generateNotification(Context context, String message, String data) {
NotificationManager notificationManager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
Notification notification = new Notification(R.drawable.notification, message, System.currentTimeMillis());
Intent notificationIntent = new Intent(context, MenuActivity.class);
//notificationIntent.setFlags(Notification.FLAG_ONGOING_EVENT | Notification.FLAG_NO_CLEAR);
notificationIntent.setFlags(Intent.FLAG_ACTIVITY_LAUNCHED_FROM_HISTORY);
Bundle bundle = new Bundle();
bundle.putString("data",data);
notificationIntent.putExtras(bundle);
//Constants.NOTIFICATION_ID++;
notification.setLatestEventInfo(context, context.getString(R.string.app_name), message, PendingIntent.getActivity(context, 0, notificationIntent, Notification.FLAG_ONGOING_EVENT | Notification.FLAG_NO_CLEAR));
notification.flags |= Notification.FLAG_AUTO_CANCEL;
notificationManager.notify(Constants.NOTIFICATION_ID, notification);
}
Use Intent.FLAG_ACTIVITY_CLEAR_TOP instead of FLAG_ACTIVITY_LAUNCHED_FROM_HISTORY.

Single Notification but should deliver multiple pending intents when app is launched - Android

I am receiving multiple messages from GCM. When the app is running foreground or background i have no issues because i use broadcast receiver. But when the app is not running I would want to Queue the messages in the pendingIntent and keep it as part of the notification managers notification. So that when user clicks on the notification the mainActivity is launched and it is passed all the messages. I have posted the code below.
With current Code I am able to receive, only 1 message and that is the latest message, in the onCreate method of the activity.
To summarize the requirement
Application is not running. App Exited.
Call notify with pendingIntents on every new message received with Extra Field set to the message
Just one notification message in notification bar ( let us assume "number of messages received 3" is seen in notification bar)
Now User clicks the notification
Application should be able to read all the 3 messages by accessing the pendingIntent
Hope i can find help!
// build intent
final Intent notificationIntent = new Intent(context,
MainActivity.class);
notificationIntent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP
| Intent.FLAG_ACTIVITY_SINGLE_TOP);
notificationIntent.putExtra(CommonUtilities.EXTRA_MESSAGE, message);
notificationIntent.setAction("DUMMY");
// pending intent creation
int requestID = (int) System.currentTimeMillis();
// set intent so it does not start a new activity
final PendingIntent intent = PendingIntent.getActivity(context, requestID ,
notificationIntent, 0);
// create notification using intent
final String title = context.getString(R.string.app_name);
Notification notification = new NotificationCompat.Builder(context)
.setContentTitle(title)
.setContentText(formattedMessage)
.setSmallIcon(icon)
.setDefaults(Notification.FLAG_AUTO_CANCEL|Notification.DEFAULT_SOUND | Notification.DEFAULT_VIBRATE)
.setContentIntent(intent).build();
final NotificationManager notificationManager = (NotificationManager) context
.getSystemService(Context.NOTIFICATION_SERVICE);
notificationManager.notify(1, notification);
//Now in mainActivity:OnCreate
//Receive
Bundle extras = getIntent().getExtras();
if (extras != null) {
String inp = extras.getString(CommonUtilities.EXTRA_MESSAGE);
if (inp != null ) {
doSomething(inp);
}
}
Since you are the one receiving the GCM incoming messages, and you are the one raising the Notification, it is up to you to arrange to store the details of the GCM messages in a file or database, and it is up to you to arrange to show all those details when the user taps on the Notification.
Guys finally i used the following logic to solve my problem
Have a local array when receiving Intents.
If pending Intent Already Exists ( FLAG_NO_CREATE )
then
append the array with the new message and update the pending Intent
This way the EXTRA will have old + new message in an array
else
Clear the old message array because the notification has already been cleared.
Now add the new EXTRA with ( FLAG_UPDATE CURRENT)
End
Then Notify
Now when user clicks on the single notification a new activity is launched.
In MainActivity Oncreate I read the intent data and go in a loop and all the messages that I would have missed when the app was not running!
Ofcourse not aware of how heavy it would be on the notification bar if the user does not click on the notification for a long time!

Android: What Intent Flag to use so undestroyed Activity will not automatically show upon Notification

I have 3 Activities
A. MainActivity - just an Activity with a text and button on it
B. SettingsActivity - this will be displayed if the button on (A) is clicked, this initializes time picker that will send a notification when it alarms
C. DisplayNotification - activity for displaying notification in the status bar, when clicked, it should show A
This is what I want to happen:
I launch my application, A will be shown
I click the button, B will be shown
I set a time for the alarm
When the alarm triggers, a notification is shown in the status bar
If I click the notification, A will be shown
This is what happens (I have 2 scenarios with different results):
First scenario:
After step 3, I tap the back button, A will now be shown
Then, I tap again the back button, the onDestroy of A will be called and screen will show the 'home page' or 'desktop' of the phone
I wait till the alarm triggers
When the alarm triggers, notification is shown on the status bar
I click the notification, it launches my app displaying A
End of story. This is what is expected to happen
Second scenario: (the buggy one)
After step 3, I tap the HOME button, A's onDestroy is not yet called and the latest screen was B
The screen shows the 'home page' or 'desktop' of the phone
I wait till the alarm triggers
When the alarm triggers, notification is shown on the status bar AND B was shown automatically without me clicking the notification on the status bar
What I want to happen here is that it should not automatically display B activity.
Am I missing any flags for notification or intent?
Here is the code snippet for Activity B which triggers the alarm
AlarmManager alarmManager = (AlarmManager) getSystemService(ALARM_SERVICE);
Intent i = new Intent(this, DisplayNotification.class);
i.putExtra("NotifID", 1);
PendingIntent displayIntent = PendingIntent.getActivity(getBaseContext(), 0, i, 0);
alarmManager.setRepeating(AlarmManager.RTC_WAKEUP, calendar.getTimeInMillis(), AlarmManager.INTERVAL_DAY, displayIntent);
Here is the code for Activity C
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
int notifID = getIntent().getExtras().getInt("NotifID");
Intent i = new Intent(this, MainActivity.class);
i.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP);
i.putExtra("NotifID", notifID);
PendingIntent detailsIntent = PendingIntent.getActivity(this, 0, i, 0);
NotificationManager nm = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
Notification notif = new Notification(R.drawable.ic_launcher, "See activity!", System.currentTimeMillis());
notif.flags |= Notification.FLAG_AUTO_CANCEL;
notif.defaults |= Notification.DEFAULT_SOUND;
CharSequence from = "Notification from me";
CharSequence message = "See activity!";
notif.setLatestEventInfo(this, from, message, detailsIntent);
nm.notify(notifID, notif);
finish();
}
I hope someone would help me :)
Thanks!
Edit:
Thanks Chirag_CID! I should have used Broadcast Receiver instead of another Activity. So, instead of extending Activity, the DisplayNotification now extends Broadcast Receiver. This is the onReceive method of DisplayNotification:
public void onReceive(Context context, Intent intent) {
Log.d(TAG, "DisplayNotification onReceive");
int notifID = intent.getExtras().getInt("NotifID");
Intent i = new Intent(context, MainActivity.class);
i.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP);
i.putExtra("NotifID", notifID);
PendingIntent detailsIntent = PendingIntent.getActivity(context, 0, i, 0);
NotificationManager nm = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
Notification notif = new Notification(R.drawable.ic_launcher, "See the quote of the day!", System.currentTimeMillis());
notif.flags |= Notification.FLAG_AUTO_CANCEL;
notif.defaults |= Notification.DEFAULT_SOUND;
CharSequence from = "Notification";
CharSequence message = "See the activity!";
notif.setLatestEventInfo(context, from, message, detailsIntent);
nm.notify(notifID, notif);
}
I read the whole Question 2-3 times..
Now I want to point to few things up there,
You have made Activity C in which you are creating notification which will call MainActivity on it's Click.
But, When you set alarm from B you are passing intent of Activity C, Though your code of C doesn't have setContentView method, and Also you have written finish() in the end of onCreate() so when Activity C is called through the Alarm set from B, It just call Activity C and set Notification ..but As you written finish() it ends Activity C and shows Activity B latest from the Stack.
If You want to cross check..
Write logs in onCreate(),onPause() and onDestroy() of Activity C..and you will see the Activity C is created and Destroyed when Alarm triggered.
Solution:
If you don't want to show any activity when you are on Home Screen and Alarm trigger then,
In Activity B where you written pending intent for Activity C..You will need it to change to call the Broadcast Receiver and use PendingIntent.getBroadcast where its PendingIntent.getActivity and the code you have written in C for notification you will have to write that in Receiver...hence none of your activity will be called when the Alarm Trigger.
Happy Coding :)

Android PendingIntent take you to an already existing activity?

Wasn't really sure how to search for this...
I have a the following which is called whenever a job is added or removed from my queue to put a notification in the status bar:
private void showNotification()
{
int jobsize = mJobQueue.size();
int icon = (jobsize == 0) ?
android.R.drawable.stat_sys_upload_done :
android.R.drawable.stat_sys_upload;
Notification notification =
new Notification(icon, "Test", System.currentTimeMillis());
Intent intent = new Intent(this, FileManagerActivity.class);
PendingIntent pendingIntent = PendingIntent.getActivity(this, 0, intent, 0);
notification.flags =
(Notification.FLAG_SHOW_LIGHTS | Notification.FLAG_AUTO_CANCEL);
notification.setLatestEventInfo(this,
"Uploading to our servers",
getString((jobsize > 0) ?
R.string.notification_active_transfers :
R.string.notification_no_transfers),
pendingIntent);
mNotifyManager.notify(NOTIFICATION, notification);
}
As it is now the behavior is this:
if the user logs out and hits the notification, it will still open a new FileManagerActivity (ops!) I could get around this by starting at my authentication activity and passing the intent up my stack in a natural order, its when the application is already running is where I have difficulties.
if the user already has the FileManagerActivity open clicking the notification will put a second instance over it. In this case, I want the currently running FileManagerActivity to recieve focus instead of launching a new instance.
How could I get the correct behavior?
I've done this before by setting my Activity to use the launch mode 'singleTop' in the Application Manifest. It will achieve the desired function, using the existing activity if one exists. In this case, onNewIntent will be called in your activity.
You'll need to check in your FileManagerActivity for authentication and start a new activity as appropriate if the user is not logged in.
I think Worked when added these:
intent.setAction(Long.toString(System.currentTimeMillis()));
PendingIntent.FLAG_UPDATE_CUR
Intent intent = new Intent(context, MyOwnActivity.class);
intent.putExtra("foo_bar_extra_key", "foo_bar_extra_value");
intent.setAction(Long.toString(System.currentTimeMillis()));
PendingIntent pendingIntent = PendingIntent.getActivity(context, 0,intent,PendingIntent.FLAG_UPDATE_CURRENT);

Categories

Resources