Android SDK. Get NOTIFICATION_SERVICE to resume, not start new instance - android

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

Related

Notification click behaviors depending on the state of the app

After a long search, I was not able to find exactly what I need.
I simply want : When a notification is displayed to the user, if the app is simply in background I want to reopen MainActivity. But if the app/activity has been killed, I want to restart the app completely.
My actual code :
NotificationCompat.Builder mBuilder =
new NotificationCompat.Builder(context)
.setSmallIcon(R.drawable.notification_icon)
.setContentTitle(notification.getSubject())
.setContentText(notification.getMessage())
.setSound(Settings.System.DEFAULT_NOTIFICATION_URI);
mBuilder.setContentIntent(
PendingIntent.getActivity(context, 0, new Intent(context, MainActivity.class)
.setFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP), PendingIntent.FLAG_UPDATE_CURRENT));
NotificationManager mNotificationManager =
(NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
Notification notif = mBuilder.build();
notif.flags = Notification.DEFAULT_VIBRATE | Notification.FLAG_AUTO_CANCEL;
Case which is not working actually is to restart the app if app or activity has been killed.
EDIT : By killed I mean the app has been closed in the app manager. Or we lost the focus and the activity is destroyed. In those cases I would like to fully restart the app.
I think you don't entirely understand how android functions. Whenever your program is needed, the program is started by android (See the Application class for an onCreate that you can override).
Whenever an activity is necessary it is (re)created or brought to the foreground.
That means that an activity restart does not necessarily imply a restart of the application. In practice, if the program was still in memory, then an application restart won't happen.
If you want to investigate this further
create an Application.onCreate method so you see whether your app is restarted or not.
trigger the notification
go to the android settings, application tab, and there select 'show cached processes'. Clear your process from the list.
tap the notification.
This should trigger a restart of the application. If this is indeed the problem then you cannot 'solve' it. Android decides when it will kill your application and when it removes it from memory.
The best solution then is to redesign your activity that whatever the application restart would trigger is also performed in the activity itself. Or so, without more detail what functionality you would like to see performed on an 'activity/application-restart' it is difficult to advice further on this matter.
I think you need to change your setFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP) value to setFlags(Intent.FLAG_ACTIVITY_REORDER_TO_FRONT).
The reason is due to the way that FLAG_ACTIVITY_REORDER_TO_FRONT
works. When you use this flag, Android looks for an instance of the
desired activity in your activity stack, starting from the front of
the stack and scanning until it gets to the root/back of the stack. As
soon as it finds an instance of the specified activity, it brings that
one to the front (ie: if there are multiple instances of the specified
activity it will bring to the front the most recent instance).
Original I found here.
See android developer doc here.
I hope its help you.

Android service is frequently stopped and restarted

I'm trying to develop an Android application which draws a floating overlay on the screen, as it is done by Facebook messenger with chat heads.
I've created an Android service from which I handle the UI. Everything works well, but on some devices the service is stopped very frequently and sometimes it is started again after more than 60 seconds.
I know this is a behavior defined by the Android System, but I was wondering if there is a way to give my service the maximum priority. Is this possible? Could this behavior be worsened by something in my implementation which is wrong?
One option is to make your Service a "Foreground Service" as briefly explained in Android documentation. This means that it shows an icon and possibly some status data in the status bar. Quoting:
A foreground service is a service that's considered to be something
the user is actively aware of and thus not a candidate for the system
to kill when low on memory. A foreground service must provide a
notification for the status bar, which is placed under the "Ongoing"
heading, which means that the notification cannot be dismissed unless
the service is either stopped or removed from the foreground.
In practice you just need to modify the Service's onStartCommand() method to set up the notification and to call startForeGround(). This example is from the Android documentation:
// Set the icon and the initial text to be shown.
Notification notification = new Notification(R.drawable.icon, getText(R.string.ticker_text), System.currentTimeMillis());
// The pending intent is triggered when the notification is tapped.
Intent notificationIntent = new Intent(this, ExampleActivity.class);
PendingIntent pendingIntent = PendingIntent.getActivity(this, 0, notificationIntent, 0);
// 2nd parameter is the title, 3rd one is a status message.
notification.setLatestEventInfo(this, getText(R.string.notification_title), getText(R.string.notification_message), pendingIntent);
// You can put anything non-zero in place of ONGOING_NOTIFICATION_ID.
startForeground(ONGOING_NOTIFICATION_ID, notification);
That's actually a deprecated way of setting up a notification but the idea is the same anyway even if you use Notification.Builder.

Relaunching activities in Android

I'm a newbie in Android developing and after reading the documentation about tasks and activities I can't get my application working correctly.
(First of all, sorry for my English)
My application consist of two activities: LOGIN and NEWS. Both activities launching method is singleTask.
The NEWS activity creates a notification with onCreate with the standard notification code of the Android notification tutorial!.
int icon = R.drawable.notification_icon; // icon from resources
CharSequence tickerText = "Hello"; // ticker-text
long when = System.currentTimeMillis(); // notification time
Context context = getApplicationContext(); // application Context
CharSequence contentTitle = "My notification"; // expanded message title
CharSequence contentText = "Hello World!"; // expanded message text
Intent notificationIntent = new Intent(this, MyClass.class);
PendingIntent contentIntent = PendingIntent.getActivity(this, 0, notificationIntent, 0);
Notification notification = new Notification(icon, tickerText, when);
notification.setLatestEventInfo(context, contentTitle, contentText, contentIntent);
When I first open the application:
LOGIN --> onResume() --> NEWS --> onCreate() --> Notification
With the code
Intent newLogAct = new Intent(Login.this, News.class);
TomTuckerActivity.this.startActivity(newLogAct);
If I hit Back *NEWS* is destroyed and again:
LOGIN --> onResume() --> NEWS --> onCreate() --> Notification
(I don't like that loop, the reason of using it is explained at the end)
If I hit Home I go back to the main menu and here begin what I don't understand:
If I use the notification to relaunch the application there is no problem and NEWS window is opened again without calling onCreate and without sending the notification.
If I use the application icon when calling NEWS the singleTask option seems to be useless because onCreate() is called again and the notification is sent again.
What I want is to recover the application where I left it either I use the notification or the icon.
May a flag in the newLogAct will solve the problem?
Is OK tho have singleTask launching option in both activities?
About the Back button loop problem:
To avoid the loop I thought about using onCreate() instead of onResume(). However, when I relaunches the application with the application icon LOGIN is loaded but onCreate is not called so NEWS is not loaded.
Is there any other way to solve that?
Maybe with onNewIntent() method?
Your problem (or at least a part of it) seems to be: How to make a notification come back where you left the application.
Notification are not supposed to be used this way, clicking on a notification should start a new activity whose aim is to deal with the notification.
If you do want to come back to the application where you left it (I’m doing it), you can use the following trick (I don’t know if this is good practice, but it works and does not seems that hackish) : create an Activity called Autodestruct which call finish() in its onCreate() method, and make the notification run this Activity. This will restore the back stack with a dummy Activity on top of it and remove the dummy Activity immediately.

Correct way of using android notifications to pass data to my application

Hallo!
I have a question concerning notifications.
I want to create an application, that parses received SMS for a certain content. If the sms contains a certain content it is parsed and the data is extracted. A notification should be created and it should show up. When the user selects the notification, the application should be invoked with the extracted data. If the application is not running, it should be started. If it is already running, the instance should be displayed and processing the information.
To solve this I did the following:
A Broadcast receiver listens for SMS and parses them. To invoke the application I use the following code:
NotificationManager mNotificationManager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
Notification notification = new Notification(icon, tickerText, when); Bundle bundleNotification = creatingNotificationBundle(...);
Intent notificationIntent = new Intent(Intent.ACTION_MAIN); notificationIntent.setClassName(...); notificationIntent.putExtras(bundleNotification);
PendingIntent contentIntent = PendingIntent.getActivity(context, 0, notificationIntent, 0); notification.setLatestEventInfo(context, contentTitle, contentText, contentIntent); mNotificationManager.notify((int) System.currentTimeMillis(), notification);
The Activity that I invoke processes the Intent in the onCreate(...) method. This works fine when the application is not running. When I already have an instance running, it is invoked and no data is passed (or I'm not overwriting the correct methods). I have seen the an onResume() is invoked. But this method doesn't have an intent as a parameter. What is the best idea to solve this problem?
I did an (in my opinion) very dirty workaround to get this work:
I created a temporary activity
I do the same code as above except that I invoke this new activity and set the flags notificationIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK) and notificationIntent.addFlags(Intent.FLAG_ACTIVITY_MULTIPLE_TASK)
this activity sends first a Broadcast and than an Intent both forwarding the data previously parsed.
Using this way the main application alwas gets the data. If it is already running it receives the broadcast and comes to front with the intent, if it is not running, it receives the data from the intent in the onCreate(...) method.
But I don't think that this is the correct solution for this problem, since it seams quite dirty to create a dummy activity just for redirecting data and doing nothing else.
Any ideas and suggestions would be highly appreciated.
Thanks
You probably want to override Activity#onNewIntent(android.content.Intent):
…when the activity is re-launched while at the top of the activity stack instead of a new instance of the activity being started, onNewIntent() will be called on the existing instance with the Intent that was used to re-launch it.

Custom Notification

I would like to know if there is a way of using the notication bar in order to do some operations (onClick), without having an activity being launched/resumed.
for example.. let's say i raise a notifcation, and when the user press on it, then instead of take me to some activity, it invoke some regular method in my current activity/service
Is there any way to implement such a thing?
for example the current notifcation code do a standart behave onClick. running up an activity.. how will channge the code in order to invoke some method instead of an activity?
messagesManager = (NotificationManager)
context.getSystemService(Context.NOTIFICATION_SERVICE);
Notification notification = new Notification(R.drawable.icon, message,
System.currentTimeMillis());
PendingIntent contentIntent = PendingIntent.getActivity(context, 0,
new Intent(context, someActivity.class), 0);
notification.setLatestEventInfo(context, "notification", message,
contentIntent);
messagesManager.notify(R.string.noto, notification);
Is there any way to implement such a
thing?
Use an appropriate PendingIntent. Instead of calling getActivity(), call getService() or getBroadcast().
I don't believe this is possible or, at the very least, best practice. It's possible that Android could kill your activity while the Notification is still waiting in the top bar. For example maybe you get a phone call but Android is low on RAM - it kills your activity, thus there's really not a 'current' activity anymore.

Categories

Resources