is there a way to awake already running app from the notification bar after c2dm message?
i have this app that is registered with c2dm servers that receives push notifications from my server to do some processing. so after i receive c2dm message from my server, it displays the status bar notification to the user, user expands the notifications and clicks on my app, brings it up.
all is good but if this app was already running before (stared from the icon) this would load another instance of my app into memory. also some of the things are crashing in it. i already changed the android:launchMode="singleTop" on all my activities, i tried using intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP) in my notification and no luck. i always end up with 2 apps running.
any help is appreciated
here my static function that i use to create a notification after i receive the c2dm message:
public static void notifyStart(Context context, String notificationText) {
//notification
String ns = Context.NOTIFICATION_SERVICE;
NotificationManager mNotificationManager = (NotificationManager) context.getSystemService(ns);
int icon = R.drawable.icon_notify;
CharSequence tickerText = notificationText;
long when = System.currentTimeMillis();
Notification notification = new Notification(icon, tickerText, when);
notification.ledARGB = 0xff00ff00;
notification.ledOnMS = 400;
notification.ledOffMS = 400;
notification.flags |= Notification.FLAG_SHOW_LIGHTS;
notification.defaults |= Notification.DEFAULT_SOUND;
CharSequence contentTitle = "App Name";
CharSequence contentText = notificationText;
Intent notificationIntent = new Intent(context, home.class);
notificationIntent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
PendingIntent contentIntent = PendingIntent.getActivity(context, 0, notificationIntent, 0);
notification.setLatestEventInfo(context, contentTitle, contentText, contentIntent);
mNotificationManager.notify(1350, notification);
}
and here is my home activity:
<activity android:name=".home"
android:label="#string/app_name"
android:theme="#android:style/Theme.NoTitleBar"
android:launchMode="singleTop" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
guys, i am very sorry but it was my fault :| couple of days ago i decided to change the name of the package of my app and forgot to remove the old app from the phone. i didn't realize that it would cause two separate installations on my phone, the task manager displays only app name so it did look like there were two instances of the same app, in fact there was one instance of each ;) sorry about trouble and appreciate your willingness to help :)
Android documentation says:
As shown in the table below, the modes fall into two main groups, with "standard" and "singleTop" activities on one side, and "singleTask" and "singleInstance" activities on the other. An activity with the "standard" or "singleTop" launch mode can be instantiated multiple times. The instances can belong to any task and can be located anywhere in the activity stack. Typically, they're launched into the task that called startActivity() (unless the Intent object contains a FLAG_ACTIVITY_NEW_TASK instruction, in which case a different task is chosen — see the taskAffinity attribute).
In contrast, "singleTask" and "singleInstance" activities can only begin a task. They are always at the root of the activity stack. Moreover, the device can hold only one instance of the activity at a time — only one such task.
so it seems (though I haven't checked) that singleInstance is what you're looking for.
see: http://bit.ly/gH8SBb
Related
So here is what I am trying to achieve here... We have two android APKs installed on the device... Each APK can force itself to be on the foreground (This is not an app the general public will use so it's okay...)
So we launch task a with activity a.
We then launch task b with activity b.
Then activity a & task a wants to go to foreground (This can happen at any time)
At some point later, activity a and task a wants to go to foreground
So we had this code working using the following code:
Intent i = new Intent(Variables.context, HomeActivity.class);
i.setFlags(Intent.FLAG_ACTIVITY_REORDER_TO_FRONT);
startActivity(i);
Great!
However, on a phone running 4.2.2 (and maybe others too) we noticed that the behavior was not as expected. The following two things can happen.
Let's assume activity a & task a is in the foreground, but want to make activity b and task b come to the foreground it does not work.
However if no task was in the foreground and the home launcher is focused, then activity b and task b gets popped to the foreground as expected.
Here is an example of one of my manifest from one of the applications:
<activity
android:name="some.app.id.goes.here"
android:label="#string/app_name"
android:screenOrientation="portrait"
android:windowSoftInputMode="adjustPan">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
I have tried adding this line of code:
android:launchMode="singleTop"
and it still does not work.
Is there anything I am missing?
A few notes:
Activity A can be ANY application, not just our developed application which rules out activity A from stopping this from happening. We had the same results using Google chrome / Google maps / Google play store.
We do not override onNewIntent
Well, what a pain this was...
Here is the workaround I had to make...
private void generateNotificationToPopActivityToTop(final int id, Context context, String message) {
Intent notificationIntent = new Intent(context, HomeActivity.class);
notificationIntent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_SINGLE_TOP);
PendingIntent intent = PendingIntent.getActivity(context, 0, notificationIntent, 0);
NotificationCompat.Builder mBuilder = new NotificationCompat.Builder(context)
.setSmallIcon(R.drawable.ic_launcher)
.setContentTitle(context.getString(R.string.app_name))
.setFullScreenIntent(intent, true)
.setPriority(NotificationCompat.PRIORITY_MAX)
.setContentText(message)
.setAutoCancel(true)
.setDefaults(Notification.DEFAULT_SOUND | Notification.DEFAULT_VIBRATE | Notification.DEFAULT_LIGHTS);
final NotificationManager mNotificationManager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
mNotificationManager.notify(id, mBuilder.build());
new Handler().postDelayed(new Runnable() {
#Override
public void run() {
mNotificationManager.cancel(id);
}
}, 1000);
}
I want to create a constant notification on status bar (like current battery percents - it's always there), but the icon will be changed every day on 00:00.
In addition, I want this notification will alert automatically after rebooting the device and not only after the user opens the application.
I created the notification in MainActivity, but I don't know how to make it alert after rebooting and also I don't know how to change it every day at mid-night.
I tried to create AlarmService and broadcast reciever but it run every 5 seconds and it's far too much so I deleted it.
My current code is:
NotificationCompat.Builder mBuilder = new NotificationCompat.Builder(this)
.setContentTitle(getString(R.string.notificationTitle))
.setContentText(....)
.setLargeIcon(largeIconBitmap)
.setSmallIcon(getResources().getIdentifier("icon_status_" + myHelper.getCurrentImageNumber(),"drawable", getPackageName())); // change the icon at mid-night. 'getCurrentImageNumber' should get me the right icon number
Intent resultIntent = new Intent(this, MainActivity.class);
PendingIntent resultPendingIntent = PendingIntent.getActivity(this,0,resultIntent,PendingIntent.FLAG_UPDATE_CURRENT);
mBuilder.setContentIntent(resultPendingIntent);
Notification notification = mBuilder.build();
notification.flags |= Notification.FLAG_NO_CLEAR | Notification.FLAG_ONGOING_EVENT;
mNotifyMgr = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
mNotifyMgr.notify(mylHelper.myRequestCode, notification);
Right now I see a notification, but the icon doesn't change and it does not alarm after reboot. I saw some answers in stackoverflow but nothing helped me.
I wont give you all the code, you will need to learn by doing.
Here is what you should do:
1 Use a Service to launch your notification and maintain the logic to updating it. If the notification already exists you can update the existing one or programmatically dismiss it and replace with a new one.
2 Register a broadcast receiver in AndroidManifest.xml with multiple intent filters to launch your service.
<receiver android:name=".myReceiver">
<intent-filter>
<action android:name="android.intent.action.TIME_TICK" />
</intent-filter>
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED" />
</intent-filter>
</receiver>
3 Create class which extends the broadcast receiver class and use and launch the above service.
I have an activity which starts a service through a button press. During service initialization, if an error occurs, this error is displayed by a notification, as follows:
String tickerText = getString(R.string.init_error);
Notification notification = new Notification(
R.drawable.ic_stat_notify_msg,
tickerText, System.currentTimeMillis());
PendingIntent notificationIntent = PendingIntent.getActivity(
this, 0, new Intent(this, MyServiceActivity.class), 0);
notification.setLatestEventInfo(this,
getText(R.string.init_error_tts_title),
getText(R.string.init_error_tts_text),
notificationIntent);
NotificationManager nm = (NotificationManager)getSystemService(NOTIFICATION_SERVICE);
nm.notify(R.string.init_error, notification);
stopSelf();
When the notification appears in the status bar, I open the notifications window. Then, when I click on the notification, a new instance of MyServiceActivity is launched... Why?
Try to add this attribute on your activity tag on the manifest :
android:launchMode=["multiple" | "singleTop" |
"singleTask" | "singleInstance"]
with value singleTop or singleInstance
Activity Element Documentation
I have a music player that has the initial launcher activity, then a selection activity and then the player. The notification needs to return the user to the player. I used Christophe's idea and found that putting
android:alwaysRetainTaskState="true"
android:launchMode="singleTop"
in the manfest's activity tag of the PLAYER ACTIVITY gave me the correct behavior. Then make sure your notification invokes the PLAYER ACTIVITY class. I didn't do this at first. It invoked the app launcher class and, while this was okay for newer Androids, it left me with the extra activity problem in Android 2.3.6. Now all is good.
If my activity fix doesn't work for you, you'll have to brute-force your way through the choices found at
http://developer.android.com/guide/topics/manifest/activity-element.html#lmode
I should add that my player is stateless, just four buttons connected to a service. But if your activity needs its state set up when the notification's intent comes in, you need to override onNewIntent:
#Override
protected void onNewIntent(Intent intent) {
super.onNewIntent(intent);
}
Kudos to Christophe. This is a hard question to get the right answer for.
set a proper launch mode, or add the required intent flags.
I am really moving forward with my android application. I was able to implement onDestroy() and onPause() routines.
I have also managed to get Android's notification service to place my icon with title and body in the notification bar/task menu.
The only problem with this notification service is that if my android app is already running, and has initiated the onPause() function that super.onPause(); moveTaskToBack(true);, if a users taps the notification, it will bring up a NEW instance of my app.
Once the user interacts with the new instance, the program will crash because the background version is already running, causing conflicts.
Here's my notification code, I need help in making this code look for an already running version of my app:
String ns = Context.NOTIFICATION_SERVICE;
NotificationManager mNotificatonManager = (NotificationManager) getSystemService(ns);
int icon = R.drawable.ic_launcher;
CharSequence tickerText = "app name";
long when = System.currentTimeMillis();
CharSequence contentTitle = "app title";
CharSequence contentText = "text";
Intent notificationIntent = new Intent(this, SuperMicProActivity.class);
PendingIntent contentIntent = PendingIntent.getActivity(this, 0, notificationIntent, 0);
notification.setLatestEventInfo(context, contentTitle, contentText, contentIntent);
final int signed = 1;
mNotificatonManager.notify(signed, notification);
I was looking at onResume() with may be some sort of bringTaskToFront(this) option. Does this exist?
Thanks,
You have a few issues, IMHO.
and has initiated the onPause() function that super.onPause(); moveTaskToBack(true);
That is rather strange behavior. Why are you doing this?
Once the user interacts with the new instance, the program will crash because the background version is already running, causing conflicts.
Then whatever was being done in the original activity should not be in an activity at all, but in a service. Once you no longer have a foreground activity, the odds of Android terminating your process to free up memory is fairly high and may occur rather quickly, depending on what else is going on. You seem to be depending upon that older activity somehow still doing something. A "background version" of an activity should not be doing anything that would impact any other activity in your process, and an activity not in the foreground should not be responsible for doing anything that the user might miss if the activity goes "poof".
That being said, there are other reasons to avoid having a second copy of your activity, notably navigation -- as it stands, when the user presses BACK from the second copy of the activity, they will see the first copy, and get confused.
I need help in making this code look for an already running version of my app
No, you "need help in making this code look for an already running version of" your activity. An app is not an activity. An activity is not an app.
Adding FLAG_ACTIVITY_CLEAR_TOP and FLAG_ACTIVITY_SINGLE_TOP to your Intent will solve this:
Intent i=new Intent(this, SuperMicProActivity.class);
i.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP|Intent.FLAG_ACTIVITY_SINGLE_TOP);
PendingIntent pi=PendingIntent.getActivity(this, 0, i, 0);
This will bring your existing activity to the foreground and, if needed, get rid of other activities in your task.
Yes something like that is possible. You need to use flags.
http://developer.android.com/reference/android/content/Intent.html#setFlags(int)
You should look into these 2 in particular.
FLAG_ACTIVITY_SINGLE_TOP
FLAG_ACTIVITY_CLEAR_TOP
I am experiencing a strange behavior with my android application when dealing with a notification that is created from a BroadcastReceiver when a C2DM message arrives on the mobile device. The flow I am executing to experience this behavior is the following one:
Start my application, DashboardActivity is displayed;
Close application either by pressing home button or back button;
Receive the push message and create the notification;
Click the notification item and the activity BookingOfferActivity is launched;
Close the BookingOfferActivity either by pressing home or back button or calling finish()
Long press home button and select my application from recent applications
BookingOffcerActivity is displayed instead of DashboardActivity
The BookingOfferActivity is being launched from the notification using the following code:
Intent notificationIntent = new Intent(context, BookingOfferActivity.class);
notificationIntent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
Bundle b = new Bundle();
b.putSerializable("booking", booking);
notificationIntent.putExtras(b);
PendingIntent contentIntent = PendingIntent.getActivity(context, 0, notificationIntent, 0);
Notification notification = new Notification(icon, tickerText, when);
notification.setLatestEventInfo(context, contentTitle, contentText, contentIntent);
long[] vibrate = {0,100,200,300};
notification.vibrate = vibrate;
notification.flags = Notification.FLAG_AUTO_CANCEL;
NotificationManager mNotificationManager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
mNotificationManager.notify(AppUtil.getNextPushIndexBooking(), notification);
BookingOfferActivity is defined in the AndroidManifest this way:
<activity android:name=".activity.BookingOfferActivity"
android:label="#string/app_name"
android:screenOrientation="portrait" />
and my DashboardActivity is defined like this:
<activity android:name=".activity.DashboardActivity"
android:label="#string/app_name"
android:configChanges="orientation|keyboardHidden"
android:windowSoftInputMode="stateHidden|adjustPan">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
The reason I am calling it a strange behavior is that I would like to start DashboardActivity whenever my application is started or restarted by the user, not by the notification item. So after closing, finishing or destroying BookingOfferActivity and reopening by application by accessing recent opened application (long press on home button) or accessing the launcher icon on the application list, I would like to see the Dashboard.
I create a question similar to this one but I didnt provide too much details, so I closed the other one and opened this one with more data.
Many thanks for any guidance on how to solve this problem
T
I'm not sure, but I suppose that in your scenario second activity just go to the top of activity stack and will be shown until application wont be killed. We have approximately same problem and solv it in easy way: Notification start main(first) activity with extra "go to second immediately". in onCreate of first activity check this extra and start second activity if needed. With this solution you should be careful with pressing back button - if you dont want to show first activity in case of "notification start" you should care about it in onResume of first activity