I'm working on a widget for an Android app and I encounter a problem. When the user click on the widget, I'd like the application to open his first activity (the one with intent-filter: 'action.MAIN' / 'category.LAUNCHER') (I'll call it Activity A).
To do that, I use this snippet (in my WidgetProvider class):
Intent intent = context.getPackageManager().getLaunchIntentForPackage(context.getPackageName());
PendingIntent pendingIntent = PendingIntent.getActivity(context, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT);
views.setOnClickPendingIntent(R.id.view , pendingIntent);
This works very good if my application is killed or if all the activities have been closed (using the back button until the application close)
The problem happen when several activities are open. Imagine the activity stack is like : Activity A -> Activity B -> Activity C.
If I click on the widget, SOMETIMES the application is just brought to front and Activity C is visible instead of Activity A.
It's very strange because this doesn't happen every time. (It seems that it happen after I navigate a lot in activities)
I really need the activity A to open and not another activity whatever how the activity stack was because this activity is like a hub with several links to differents fonctionnalities.
Can somebody help me?
Thank you very much.
PS: Sorry if my English is pretty poor, I'm from Belgium
From a widget you should do more or less the same as the system launcher does with intents.
Try using FLAG_ACTIVITY_CLEAR_TOP in your intent. You will also want to look at FLAG_ACTIVITY_NEW_TASK.
It's better to follow the platform guidelines by the way, which say that you can also inject deep into your app, provided you give the user the right path to navigate up again.
If you want a specific Activity to launch, why don't you just call that activity specifically, instead of dynamically.
You are experiencing issues due to the Activities in your back-stack. Android manages the life-cycle of your Activities in a very special way that you should probably research - http://developer.android.com/reference/android/app/Activity.html#ProcessLifecycle
calling finish() - will always return to the activity that launched the current activity. The only time your app will close, is if there was not an original activity. You could always test for this condition, and if the calling activity is NULL, you could explicitly call you Activity A.
Related
I've written an android application.
So, this is what happens:
I've got a listview and if the user taps on a specific row the following code in invoked to create an activity:
Intent intent = new Intent();
intent.setClassName( getPackageName(), getPackageName() + ".matchView.MatchViewActivity" );
intent.putExtra("leagueId", leagueId );
startActivity( intent );
Then the activity is started and let's suppose the user return back to the list view by tapping the back button
Now he is again in the Listview and can tap the same cell again such that the same activity is started again.
However, the problem is that when I start the activity and I return back with the back button the (now old) activity is not deallocated. It still runs in the background and if the user again taps on the same cell the same acitvity is started again resulting in the same activity running two, three, four and so on times (depending on how often the user taps).
So if the user taps the back button how do I make sure that the activity I started is properly deleted or ended?
Activity will be deleted automatically (when you return back) by system if you are not holding any reference to it.
Better read about activities and back stack
Answering to your question, if you don't intend anymore to use an Activity, the correct way of ending it is by calling finish().
This tells the Android SO you don't want to use it again, but don't expect it to be finished immediately. Android keeps the references to both instances and Activities (this ones are instances too) in memory a certain time after finished so if the user reopens that Activity within a short amount of time, it's recovered much faster.
If you are worried about the state in which the Activity is reopened, you can force it to be restarted every time it's reopened. You might find more references in the Intent reference page, especially the FLAG_ACTIVITY_CLEAR_TOP flag.
You can define in the manifest how an activity is launched based on the "launchMode", and you can choose from one of four launch modes:
"standard"
"singleTop"
"singleTask"
"singleInstance"
It sounds like you want to use, "singleTask" or "singleInstance", which you can read more about under the "android:launchMode" section here:
http://developer.android.com/guide/topics/manifest/activity-element.html
Add finish(); after starting the new activity to delete the current one.
I have two Android applications - A and B.
Application B has two Activities, its Launcher Activity which we'll call Activity 1, and another we'll call Activity 2.
Application A needs to call both Application B's activities multiple times each in arbitrary sequence.
What I've found though is that if I call Activity 2 (from Application A) then later call Activity 1 - this works.
What doesn't work is when I need to call Activity 2 anytime AFTER I've called Activity 1.
When I do this I always get Activity 1 regardless.
Looking at the logs I can see that the ActivityManager is receiving an intent with the correct ComponentName for Activity 2 that I've set in my code in Application A - yet still it still resolves to Activity 1.
The only thing that has worked is when I call finish() in the onPause() method for Activity 1. If I do this - Application A can call both Application B's activities without issue.
This is not a good solution generally but it is definitely not a solution for me as I'm trying to define an integration pattern with Application A that pre-existing apps (App B in this case) can follow.
Is there any way I can alter this result by the way I call Application B's activities from Application A (as opposed to modifying the activity configuration in Application B).
At the moment I call both Activity 1 and Activity 2 by their ComponentName like so:
Intent i = new Intent(Intent.ACTION_MAIN);
i.addCategory(Intent.CATEGORY_LAUNCHER);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK |Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED);
intent.setComponent(name);
context.startActivity(intent);
The only difference is that for the non-launcher activity (Activity 2) I am using action VIEW and category DEFAULT (vs MAIN and LAUNCHER as per above).
Obviously Activity 2 also needs an intent filter matching that combination - but assuming it does..
Any suggestions?
Did you already have a look at the different Activity attibutes? android:finishOnTaskLaunch seems to me as if it could be of help.
See a full list at the Developers Guide.
I have an app that contains several activities...so lets say user is navigating activity stack A->B->C. Then presses the HOME button. Now when the user clicks on the Widget, I just want bring my app's existing/current instance to the foreground. I do NOT want a new instance of the app. I want activity C to get back to foreground.
I tried launchMode to "singleTask" | "singleInstance" but that does NOT solve my desired requirement since it clears the current instance and creates a new one with activity A.
Any ideas how to solve this?
Thanks much!
Using a "singleInstance" is not such a good idea (for many reasons).
Here is a better way - from your widget intent handler:
Intent yourActivity = new Intent(context, YourActivity.class);
yourActivity.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TOP);
context.startActivity(yourActivity);
You don't need to add CLEAR_TOP to recall activity C, but you need it if you want to bring A or B.
I am only posting because between some 10+ similar posts nobody actually pointed the correct way of doing it.
http://developer.android.com/reference/android/content/Intent.html#FLAG_ACTIVITY_CLEAR_TOP - last paragraph.
I managed to figure out a solution. I set the specialized launch mode....
android:launchMode="singleInstance"
Every time the user clicks on the widget or the app icon again, the default activity A is started. To open the app up where it last was, inside the onCreate() method in your MainActivity class just check isTaskRoot(). If false, call finish() and the activity A (MainActivity) will not appear and the app will open up to where it was in activity B.
Try adding this to your intent
intent.setFlags( Intent.FLAG_ACTIVITY_BROUGHT_TO_FRONT);
I am trying to close a whole stack of activities using the way described here:
How to kill an application with all its activities?
Namely, each activity starts the other one with startActivityForResult, and in onActivityResult calls finish() to close itself together with the activity it opened.
The problem is that the activities in the task still seem to repaint themselves at least once before they close, and this doesn't look good. After closing the topmost activity one sees all previously opened activities like in a very fast slideshow.
How can one avoid this graphical issue?
EDIT: I need that if the user presses HOME button and then presses the app's icon in launcher, he returns to the current state of the stack, not to the very first activity again. So, from what I understand, with such a requirement I can't finish() activities before starting next ones.
That's native behaviour, intended to aid in user Experience. When an Activity is started with startActivityForResult and then finishes, it will (on devices that allow fancy animations) automatically slide away. That helps people not get surprised by the screen suddenly changing.
You could try starting the Activities without startActivityForResult and handling the passing of data to and from Activities manually, then handle how/when Activities finish() and which Activity they pass back to. You might find you implement something where Activities actually pass forward to the appropriate Activity all the time, rather than back to an Activity on the stack.
Intent intent = new Intent();
intent.setClass(getApplicationContext(),
PhoneListCheckboxAES.class);
intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
startActivity(intent);
finish();
If u give like this when u are starting the next activity then the graphical problems won't occur
In an app I have very reused Activity, that shows a list of stuff happening on a specific day. The day is specified using Intent Extras.
My problem is, that if the user starts at day=1, then chooses day=2 and then day=1, from the menu, then I would like the back button to go to day=2 and then home. That is, I want to do REORDER_TO_FRONT, but not just based on the name of the activity, but also its extras.
There doesn't seam to be any intent flags suitable for this purpose. I've considered implementing my own 'sub activity stack' using onNewIntent, but it probably wouldn't work very well.
Have you tackled similar problems in your apps? Is there perhaps a way to programmatically access the activity stack, and choose which one is suitable to return to?
Manage your own Activity stack! If I'm not mistaken, you use the same Activity to display each day. Make it single top (FLAG_ACTIVITY_SINGLE_TOP). In the launching intent, pass on the current stack, in your example "121".
Respond to the back button event by launching your Activity with a smaller stack: "12" - or if stack is already "", then just let the Activity handle Back event. Then as you mentioned, use the onNewIntent function to update your Activity.