Resume specific activity instead of launching new instance - android

I am working on a task switcher, and already figured out the way to show list of apps and switch to the app when user presses my notification. My problem is, instead of resuming the app, like launcher does, my app just starts new instance (resets) the activity it's switching to.
Here's the code I'm using to set the Intent:
ComponentName componentName = taskInfo.topActivity;
String packageName = componentName.getPackageName();
/*Setting intent*/
Intent startApp = packageManager.getLaunchIntentForPackage(packageName);
PendingIntent pendingIntent = PendingIntent.getActivity(context, 0, startApp, PendingIntent.FLAG_UPDATE_CURRENT);
childView.setOnClickPendingIntent(R.id.imageButton2, pendingIntent);
To be clear, I want the user to be able to got back to whatever he was doing in that app instead of starting it anew.

Related

Resume background App

Scenario:
App is in the background, main Activity is in onStop state. I receive a specific message, display a notification to the user, he clicks on it and I want to bring the app to the forwground and just resume the main Activity, without starting a new one.
I want the samw effect as you get when you click on a paused app in the recent tasks(it just resumes).
I assume that this has to do with setting the right flags on an Intent, but I couldn't find it.
Is it possible? Thanks.
The Notification just needs to contain a launch Intent to bring your app to the foreground in whatever state it was in:
PackageManager pm = context.getPackageManager();
Intent launchIntent = pm.getLaunchIntentForPackage(context.getPackageName());
PendingIntent pi = PendingIntent.getActivity(context, requestCode, launchIntent, 0);
Set pi as contentIntent on the Notification.

updating android activity when a user taps a notification

I use this code, inside a notification, so when the user taps the notification the MainActivity starts:
PendingIntent contentIntent = PendingIntent.getActivity(this, 0, new Intent(this, MainActivity.class), 0);
If the user exits the app with the back button and taps a notification then main activity starts but if the user exit the app with the home button a new MainActivity starts over the first one. How can I detect if the MainActivity is loaded?
Thkx
You should add flags to your Intent to specify this behavior. Something like FLAG_ACTIVITY_CLEAR_TOP may be what you're looking for. This will finish any Activities on top of MainActivity (if any) and bring any existing instance to the foreground. If no instance is available, one will be created. Depending on your launchMode, you'll either get a callback to onNewIntent() (receiving the new Intent you provided) or the activity will be recreated with the new Intent.
Intent mainIntent = new Intent(this, MainActivity.class);
mainIntent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
PendingIntent.getActivity(this, 0, mainIntent, 0);

How to start an app the same way Android Launcher does (resume)

There are a lot of questions/answers about how to start an application from within your application in Android. But those solutions do not produce the same flow as if an icon was tapped in Android launcher.
For example, I do this (this is used with notifications):
intent = context.getPackageManager().getLaunchIntentForPackage("com.test.startup");
intent.setAction(Intent.ACTION_MAIN);
intent.addCategory(Intent.CATEGORY_LAUNCHER);
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
pendingIntent = PendingIntent.getActivity(context, 0,
intent, PendingIntent.FLAG_UPDATE_CURRENT);
Then when I tap on notification the app is started, however, it is started somewhat differently than when I tap the icon in the App drawer. Specifically: with this approach my main Activity is always created (i.e. onCreate() then onResume() is called). However, if application was already started and then put in background, then starting it from Launcher will only cause onResume() of currently shown activity to be called (not onCreate() on the main one). Is there a way to trigger the same resume flow programmatically from within my app?
To summarize the task: when user taps on notification I need my app to be either started (if it's not already), or brought to the foreground in its current state (if it's in background) and have some data passed to it. The app will then take care of handling/rendering that data.
Your app is behaving the way it supposed to. Even if you try the launch the app from App drawer it will call the same callback. You have to understand the lifecycle. As your activity is in the background onCreate will not get called. But for the handling the data from the notification intent you should utilize callback method OnNewIntent() in activity. You should override this method and extract the data the from the new intent and should update UI. After onNewIntent onresume will be called.
I hope this solves your problem.
Here is my onPause code which works the way you expected i.e when user clicks on the notification it doesnt call onCreate again:
notificationManager = (NotificationManager)getSystemService(NOTIFICATION_SERVICE);
intent = new Intent(getApplicationContext(), PlayerActivity.class);
intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP| Intent.FLAG_ACTIVITY_SINGLE_TOP);
PendingIntent pIntent = PendingIntent.getActivity(getBaseContext(), 0, intent,0);
NotificationCompat.Builder noti =
new NotificationCompat.Builder(this)
.setSmallIcon(android.R.drawable.ic_media_play)
.setContentTitle("Nepali Music And more")
.setContentText("Playing");
noti.setContentIntent(pIntent);
noti.setAutoCancel(true);
noti.setOngoing(true);
Notification notification = noti.getNotification();
notificationManager.notify(1, notification);
Focus mainly on the intent flags
You want to use the intent flags Intent.FLAG_ACTIVITY_CLEAR_TOP to find your activity and clear the stack above it. You also need the Intent.FLAG_ACTIVITY_SINGLE_TOP flag to prevent your activity from being recreated (to resume).
The Intent.FLAG_ACTIVITY_SINGLE_TOP is necessary since by default, the launch mode is "standard" which lets you create multiple instances of your activity. If you were to set your launch mode to SingleTop, then this flag own't be necessary

Android Widget PendingIntent Fails

There have been some similar issues discussed here, but my situation does work some of the time. I am developing a widget that when clicked should launch an activity that's part of the same package. This same activity can also be launched by a notification that may be posted. The widget updates and notification posting are done by a Service in the package. Here is the method that's called to issue the PendingIntent:
// Get pending intent for widget or notification
private PendingIntent getPendingIntent(int widgetId, int extraData) {
Intent clickIntent = new Intent(mCtx, OtdShowEvents.class);
clickIntent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, widgetId);
clickIntent.putExtra("OTDExtra", extraData);
clickIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
PendingIntent pendIntent = PendingIntent.getActivity(mCtx, 0, clickIntent,
0);
return pendIntent;
}
If I create an instance of the widget on a clean (rebooted) device, both the widget and notification launch the target activity as expected. However, if I remove the widget and create another instance, the Intent is no longer launched. Likewise, if I uninstall the widget altogether, then re-install it and create an instance, no Intent is fired off. However, if I power off and back on (leaving the widget in place), it works again when booted up.
One error that I saw along the way was from the PackageManager saying "Name not found", but indicating the package name "com.ghcssoftware.OTD.full", which is the correct name of my package!
Any ideas? And by the way, I have tried some of the PendingIntent flags such as FLAG_CANCEL_CURRENT and FLAG_UPDATE_CURRENT without affecting this behavior.
FWIW, I found that the code snippet provided in this article was exactly what I needed to figure out how to get this all working correctly, especially for multiple instances of my widget, etc.: PendingIntent in Widget + TaskKiller

How do I cancel Pending Intents in a Android Widget?

I've got some weird behavior and I can only assume is because of the Pending intents I am using.
Scenario
I have a widget (4x1) which has 4 buttons. Within onUpdate of the widget, I add an pending intent for each button. My intents fires a Service with a bundeled parameter and depending on this parameter starts something. I attach intents as this:
RemoteViews views = new RemoteViews(context.getPackageName(), R.layout.widget_layout);
Bundle b = new Bundle();
b.putString("myVariable", someVariable);
Intent intent = new Intent(context, AppStarterService.class);
intent.putExtras(b);
PendingIntent pendingIntent = PendingIntent.getService(context, buttopnPosition, intent, 0);
views.setOnClickPendingIntent(R.id.btnOne, pendingIntent);
The problem
The code works just fine, until the user decides to update the content of the button. Then, a new Pending Intent is done. So, when I press again the button, sometimes it still executes the old intent and not the new one. I don't know how to explain this better. Let's say for my first intent the parameter is "TestOne", after my update, the new intent has parameter "TestX". When the user clicks on the button, on my service I get in intent extras still "TestOne" instead "TestX". So, my guess is that somehow, I need to cancel the previous intent, when the widget button content changes.
Is this the issue ? Am I doing something wrong ? How do I cancel the old intent, I need to recreate it and then cancel it ?
Thank you for your time.
I you keep having this problem even with FLAG_UPDATE_CURRENT, try defining a different requestCode each time, with something like this:
private static int request = 0;
...
PendingIntent pendingIntent = PendingIntent.getService(context, request++, intent, 0);
So each time a new PendingIntent is created, a new requestCode is used, at least during class life.
I hope it helps.
I think you want to set the flag http://developer.android.com/reference/android/app/PendingIntent.html#FLAG_UPDATE_CURRENT as the last parameter to PendingIntent.getService

Categories

Resources