Problem on launching Activity from other application - android

I have met a problem, hope you can provide some suggestion on it.
Here is the problem:
There is an A Activity in my application which is the application's MAIN Activity, and can be started from other application(like SMS). Consider now there are A-B-C-D activities in my application's task, as I said before, user can start A Activity from SMS, when A is launched from SMS, I want B C D all to be finished, and the instance of A Activity in the task will be brought to front.
I tried to set A activity's launchMode to singleTask, this will do the trick, but there is another problem: for example, I got A-B-C-D Activities in my application's task, user press HOME key to the home screen, and re-launch the application from the launcher, then A Activity is shown instead of D Activity. It's like the application have been started from the beginning, that is not what I want.
Is there any way that I can do this? Any suggestion will be highly appreciated. Thanks in advance!

Haven't tried it, but you can try this:
Set the activity attribute alwaysRetainTaskState to true.
This should take care to retain all the activities in the stack.
When you want the root activity to be shown (In your case : when launched from SMS - I assume you are invoking the activity from your SMS receiver using start activity), in the intent you pass to startActivity set the FLAG_ACTIVITY_CLEAR_TOP flag.
This should clear off since you explicitly mention it in the Intent.

Related

How to launch activity from notification such that it can't be navigated back to?

I need to launch an activity when a notification is clicked.
The Activity launched is a standalone activity and can not be opened from any other flow from the app itself. I need to ensure that no one can navigate back to this activity once it is destroyed.
Currently i am using the following configuration:
<activity android:name=".Activities.SingleRestaurantOfferActivity"
android:taskAffinity=".Activities.SingleRestaurantOfferActivity"
android:excludeFromRecents="true"
android:screenOrientation="portrait"
android:resizeableActivity="false"/>
And I am launching this activity with the intents
FLAG_ACTIVITY_CLEAR_TASK | FLAG_ACTIVITY_NEW_TASK
Now when the acitivity is created (first notification click), it creates a new task and as per my understanding, if another notification is clicked, since the task will be existing, it will clear the task and re launch the new activity with the new intent. Is my understanding correct?
If the app is open. Then the user clicks on the notification and launches the activity. Now the home button is pressed. What will happen to the notification activity? The recents screen will only show the actual app task and not the notification activity task, will the notification activity be destroyed eventually or will it leak memory?
Please guide me as to how i should approach this. The official android guide also uses launchMode:singleTask, do i need to use that as well?
I am answering my own question here so that anyone who faces a similar issue gets an idea as to what they can do.
Steps to follow are:
1) In the manifest of the required activity, add the following:
android:taskAffinity = "com.yourpackage.youractivity"
This ensures that this activity has a seperate task affinity as compared to the default affinity. This will come into picture when excludeFromRecents is added.
android:excludeFromRecents = "true"
This flag tells android that the task associated with the given activity should not be shown in recents screen. If we had not added the taskAffinity explicitly, this would have meant that the whole application would not show in the recents screen which would be irritating. adding the task affinity will only hide the task of the required activity from recents
android:noHistory = "true"
I am not sure if this is necessarily needed. I added it to ensure that as soon as the user navigates away from the activity in any way ... eg home button, it will kill the activity using onDestroy. Also exclude from recents will prevent it from showing in the recents screen.
2) Now comes the part of intent flags to launch the activity:
I have used the flags:
FLAG_ACTIVITY_NEW_TASK :
This flag along with the taskAffinity will create a new task for the activity if the task is not already created with the same affinity. Then it will place the activity at the root of this new task. If the task already exists, it will be brought to front and the new intent will be delivered to the activity in onNewIntent() method. I wanted the activity to get fully recreated so i added the other flag below.
FLAG_ACTIVITY_CLEAR_TASK:
This flag clears the task and kills all the activities in it. Then it adds the new intended activity at the root of the task. This will ensure in my case that the activity gets fully destroyed and recreated from scratch. You might not need this in your case. CLEAR_TOP with standard launch mode will also almost do the same thing but that's a whole different scenario.
Hope this helps people creating standalone activities which don't merge directly into app flows.

Switching between activities without destroying the activity

I am new to android so don't know what can be the solution to this problem.
I have created an app with two activities in it named these as first and second activity.
First activity launch mode is singleTask and second activity launch mode is standard.
Now when i switch from second activity to first activity i don't want to destroy the second activity.
But in this case it is getting destroyed.
So can anyone help me in suggesting how can i achieve this scenerio of switching from second activity to first without
destroying second activity.
This is because activity one is single task activity.
Read here. According to this
"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.
To avoid this scenario, change launch mode of activity one to standard.
No need to destroy any activity for this, i think so. Just implement this:
Intent intent=new Intent(ActivityOne.this,ActivityTwo.class);
startActvity(intent);
in your oncreate() method of actvity
You can open new activity that you want to open, without finish() your current / previous activity by using finish().
Once you open multiple activity without finish() previous ones, the OS will automatically maintain the activity stack.

How to launch activity the same way launchers do?

I have an Activity A which is declared as singleTop and android.intent.action.MAIN in Android Manifest. I start it from launcher, then launch another activity B through Intent and then press Home button. Now I have a task with activity stack "A, B" waiting in background. If I then again start activity A from launcher I get back already running instance with a stack restored (activity B running in foreground).
This is nice. And I want to achieve the same effect when launching activity A from my own Notification. I've tried different combinations of Intent flags but I've got either a new instance of activity A or the same instance but with cleared stack (no activity B in foreground).
First of all, let's make sure that the system won't kill your Activity B when you are not using that task for a long time.
If the user leaves a task for a long time, the system clears the task of all activities except the root activity. When the user returns to the task again, only the root activity is restored. The system behaves this way, because, after an extended amount of time, users likely have abandoned what they were doing before and are returning to the task to begin something new.
There are some activity attributes that you can use to modify this behavior:
alwaysRetainTaskState: If this attribute is set to "true" in the root activity of a task, the default behavior just described does not happen. The task retains all activities in its stack even after a long period. So what you need to do is to set this to true under your <activity> tag in your manifest file for A.
Second, you won't need singleTop. Check this figure from Android docs. I guess this is what you want. If you start an activity that specifies the singleTask launch mode, then if an instance of that activity exists in a background task, that whole task is brought to the foreground. At this point, the back stack now includes all activities from the task brought forward, at the top of the stack.
So you also need to add singleTask under the tag of A and B, instead of singleTop. Then, you need to launch activity A from Notification without any flags but FLAG_ACTIVITY_NEW_TASK and FLAG_ACTIVITY_REORDER_TO_FRONT(optional).
I haven't tried this myself but I have a strong belief that it will work. Try it and let me know if it doesn't.

launch external activity w/o it appearing in the back stack

I need to launch an external activity (which isn't mine) for a split second, and then I have a service that launches my previous activity for the user to see.
This works great, but the problem is when the user then presses the back key, he gets to that external activity.
I have two different activity launches here, one for the external activity, and one for my activity to return to (in which I need to use FLAG_ACTIVITY_NEW_TASK because I'm launching it from a service).
For these two launches I've tried any combination of:
FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET, FLAG_ACTIVITY_NO_HISTORY, FLAG_ACTIVITY_NEW_TASK, FLAG_ACTIVITY_CLEAR_TOP, FLAG_ACTIVITY_CLEAR_TASK, FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS.
Nothing helps, I keep seeing the external activity after pressing back.
I've seen some similar questions here, but they all have the middle activity in their own app, so they can call finish on it, or set noHistory="true" in the manifest.
Any ideas?
UPDATE:
Seems like the issue is that I re-launch my previous activity from a service, which means I need to give it FLAG_ACTIVITY_NEW_TASK, from the documentation of Tasks and Back Stack:
FLAG_ACTIVITY_NEW_TASK Start the activity in a new task. If a task is
already running for the activity you are now starting, that task is
brought to the foreground with its last state restored and the
activity receives the new intent in onNewIntent(). This produces the
same behavior as the "singleTask" launchMode value, discussed in the
previous section.
And from the singleTask paragraph:
"singleTask" The system creates a new task and instantiates the activity at the root of the new task
...
Note: Although the activity starts in a
new task, the Back button still returns the user to the previous
activity.
So I need a flag that overrides this behavior somehow...

How to start an activity from a singleInstance activity?

I have a widget which can pop up small dialogs when clicked. These dialogs are displayed by an activity called RemoteActivity in singleInstance launchMode. In one of these dialogs, there is a button to launch the main app MainActivity, which has the standard launchMode.
However, when this button is clicked, and startActivity() called, MainActivity isn't launched, although I can see the corresponding "Starting activity: Intent { ... }" in logcat.
If I set the launchMode of RemoteActivity to standard then MainActivity gets launched, but this isn't what I want, RemoteActivity is merely an extension of the widget, I don't want it to stack with any other activity.
I also tried with FLAG_ACTIVITY_NEW_TASK but it didn't help, and it shouldn't be necessary anyway according to the docs:
A "singleInstance" activity, on the
other hand, permits no other
activities to be part of its task.
It's the only activity in the task. If
it starts another activity, that
activity is assigned to a different
task — as if FLAG_ACTIVITY_NEW_TASK
was in the intent.
How can I launch my main activity?
UPDATE / ERRATA:
The MainActivity is actually launched but only if it isn't already part of a task. If I launch MainActivity normally through the launcher, and press Back to exit, then RemoteActivity does launch MainActivity.
But if, instead of pressing Back, I press Home to leave MainActivity, then RemoteActivity can't launch MainActivity, although the intent appears in logcat.
I'm testing this on Froyo.
Any idea of what's happening?
Maybe the noHistory flag will work for what you are looking for?
I found the problem: this behavior only occurs when calling finish() before startActivity() in RemoteActivity. If I call startActivity() before finish() then it works fine whether MainActivity is already part of an existing task or not.
Go figure...

Categories

Resources