Single android application with two tasks and its navigation - android

I am developing a calling application. My HomeActivity is a singleTask activity. My call activity is also a singleTask activity.
From HomeActivity a call is initiated. At this moment, there are two tasks for my application as they both are singleTask. In call screen I have a button to reach my HomeActivity.
When I press the home button in my call screen and navigate back, my call activity is destroyed. But it should not get destroyed. It should remain.
When I press home button in call screen I do the below.
Intent intent = new Intent();
intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK);
intent.setClass(this.getActivity(), MyHomeActivity.class);
startActivity(intent);
My manifest declaration:
<activity
android:name=".XXX.MyHomeActivity"
android:label="#string/app_name"
android:alwaysRetainTaskState="true"
android:launchMode="singleTask"
android:screenOrientation="portrait"
android:windowSoftInputMode="adjustNothing"
android:theme="#style/MyTheme"
>
</activity>
<activity
android:name=".XXX.MyCallActivity"
android:label="#string/app_name"
android:launchMode="singleTask"
android:screenOrientation="portrait"
android:theme="#style/MyTheme"
android:windowSoftInputMode="adjustResize">
Inflating HomeActivity from CallActivity:
Intent intent = new Intent();
intent.setClass(this.getActivity(), HomeActivity.class);
startActivity(intent);
Inflating CallActivity:
Intent intent = new Intent();
intent.setClass(this, CallActivity.class);
startActivity(intent);
Can anyone help me with the navigation parameters to use to achieve this?

In order to have 2 tasks, you need to make sure that the root Activity of the tasks have different taskAffinity, otherwise Android will put both in the same task. The default taskAffinity is the name of your package.
Add android:taskAffinity="" to one of the <activity> declarations.

According to the documentation using FLAG_ACTIVITY_CLEAR_TASK will do the following:
this flag will cause any existing task that would be associated with
the activity to be cleared before the activity is started. That is,
the activity becomes the new root of an otherwise empty task, and any
old activities are finished.
So if want your CallActivity to stay in the back stack you can simply do this:
Intent intent = new Intent();
intent.setClass(this.getActivity(), MyHomeActivity.class);
startActivity(intent);

Related

Preventing multiple async startActivity calls in Android

I have a listView with items that, when clicked, create an intent and start an activity with that intent using the startActivity method.
The issue is that items can be pressed multiple times while the asynchronous call to startActivity is made, which will open multiple activities one on top of each other.
Using the FLAG_ACTIVITY_SINGLE_TOP doesn't solve it either, perhaps because the activity being opened from intent 1 hasn't been placed at the top of the stack when intent 2 fires?
How can I handle this?
Manifest:
<activity
android:name=".Activity2"
android:parentActivityName=".Activity1"
android:launchMode="singleTask"/>
Intent code:
Intent intent = new Intent(Activity1.this, Activity2.class);
intent.setFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP);
intent.putExtra("a", "b");
startActivityForResult(intent, REQUEST_CODE);
In Your Manifest file inside activity tag add android:launchMode="singleTask"
<activity
android:name="YourActivity"
android:launchMode="singleTask"/>
Solved with the FLAG_ACTIVITY_REORDER_TO_FRONT intent flag instead of FLAG_ACTIVITY_SINGLE_TOP

How to launch once instance of an Activity?

I am having a scenario. I am trying to lock my application using an PinActivity which I created. I am running a service which has a counter timer for 5mins. If there is no activity by the user in app for 5 mins. I will show him the PINActivity which he has to unlock and enter the app. I am launching the PINActivity like this:
Intent loginIntent = new Intent(this, PINActivity.class);
loginIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(loginIntent);
So when the user comes back to the app and see the PINActivity he will unlock it and enter the app. But what if the user doesn't enter the PIN and leave the app again ideal for more then 5 mins(Note: my service starts the counter timer the moment user brings the app to foreground). I don't want to add multiple instance of the same PINActivity at top. How can I make sure I have only one PINActivity at the top?
You should use FLAG_ACTIVITY_SINGLE_TOP. This will prevent Android from launching PINActivity if there is already an instance of PINActivity on top of the stack.
Intent loginIntent = new Intent(this, PINActivity.class);
loginIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_SINGLE_TOP);
startActivity(loginIntent);
Please don't try to use special launch modes like singleTask or singleInstance as others have suggested. This won't help and will complicate the problem for you.
You can specify android:launchMode="singleTop" in the manifest entry for PINActivity as well. This has the same effect as FLAG_ACTIVITY_SINGLE_TOP.
Add launchMode="singleInstance" in your activity in manifest like this:
<activity
android:launchMode="singleInstance"
android:name=".MainActivity"
..... />
add android:launchMode="singleInstance" in manifest
<activity
android:name=".MainActivity"
android:launchMode="singleInstance"/>
When you launch activity you can use this :
Intent intent = new Intent(this, MyActivity.class);
intent.addFlags(Intent.FLAG_ACTIVITY_REORDER_TO_FRONT);
startActivity(intent);
If activity is already there then it will use the same instance else create new one and no duplication will be there.
In manifest add attribute of singleInstance in activity tag.
<activity
android:launchMode= "singleInstance" />
Click Here

Android: make sure that specific activity retains in backstack

I want to make so the every activity launches with only one main activity in the backstack, so I always can return to the main activity with back button as for example (for starting activities I use startActivity()):
Main Activity - Activity1 (back pressed) returns to Main
Activity
Main Activity - Activity1 - Activity2 (back pressed) also
returns to Main Activity
It looks like I need to use FLAG_ACTIVITY_CLEAR_TASK flag on launching every new activity, but it clears Main Activity either. I've tried FLAG_ACTIVITY_CLEAR_TOP works fine in the 1st case, but not in the 2nd.
If someone has the same problem, please help. Any thoughts appreciated! Thanks!
My main activity:
<activity
android:name=".activity.main.MainActivity"
android:label="#string/app_name"
android:screenOrientation="portrait"
android:configChanges="orientation|keyboardHidden"
android:launchMode="singleTop">
<meta-data
android:name="android.app.default_searchable"
android:value=".activity.search.SearchActivity" />
</activity>
Set FLAG_ACTIVITY_LAUNCHED_FROM_HISTORY flag while firing the intent of Main Activity in onBackPressed().
Just make sure that you call finish() when Activity1 starts Activity2. This will ensure that your task stack looks like this: MainActivity->Activity2.
As #EmmanuelMtali mentioned, I used parent activity for this reason.
For activity different from Main, I set meta-data (and android:parentActivityName, API > 16) as follows:
<activity
android:name=".activity.user.LoginActivity"
android:screenOrientation="portrait"
android:configChanges="orientation|keyboardHidden"
android:launchMode="singleTop"
android:parentActivityName=".activity.main.MainActivity">
<meta-data
android:name="android.support.PARENT_ACTIVITY"
android:value=".activity.main.MainActivity" />
</activity>
When I need to start new activity I use array of intents and startActivities() method:
public static Intent[] createIntentsWithMainActivityInStack(Context context, Intent topMostIntent) {
TaskStackBuilder taskStackBuilder = TaskStackBuilder.create(context);
topMostIntent.addFlags(Intent.FLAG_ACTIVITY_NO_ANIMATION);
Intent[] intents =
taskStackBuilder
.addNextIntentWithParentStack(topMostIntent)
.getIntents();
return intents; }
and
Intent[] intents = createIntentsWithMainActivityInStack(context, new Intent(context, LoginActivity.class));
startActivities(intents);
Try this in every activity so that when you back press main activity opens:
#Override
public void onBackPressed()
{
super.onBackPressed();
Intent intent = new Intent(ACTIVITYTHREE.this,MAINACTIVITY.class);
startActivity(intent);
}

Could an activity with single task flag be cleared via clear top?

Assume that I have a launcher activity A which has singleTask launch mode. Now imagine that A starts Activity B like;
Intent intent = new Intent(this, B.class);
intent.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP
| Intent.FLAG_ACTIVITY_CLEAR_TOP);
startActivityForResult(intent, REQ_ACCOUNT_ACTIVITY);
In this case it seems like A's not destroyed. I wonder if it's correct or did I something wrong?
You can achieve this by using below attribute in AndroidMenifest file
android:finishOnTaskLaunch="true"
<application
...
>
<activity
android:finishOnTaskLaunch="true"
android:launchMode="singleTask"
...>
</activity>
</application>
If you not want to kept new activity in the history stack. Use below one_
FLAG_ACTIVITY_NO_HISTORY
//Actvity B is not in BackStack if we set FLAG_ACTIVITY_NO_HISTORY flag
Intent intent = new Intent(this, B.class);
intent.addFlags(Intent.FLAG_ACTIVITY_NO_HISTORY);
startActivityForResult(intent, REQ_ACCOUNT_ACTIVITY);
As soon as the user navigates away from Activity B, the activity is finished. This may also be set with the noHistory attribute.
For more -> Tasks and Back Stack
It's been a while but I came across my own question when I was wandering over here.
The activity A was not getting deleted because the flags are set for the activity B. And when I call this code, there's no such activity called B in the task stack already. So effectively, nothing to clear on top of B.
Hope this helps.

Activity is getting created again instead of resuming and using instance from stack?

I have an android application with several activities .Each and every activity has Application Icon in action bar which helps user to return back to main activity directly instead of pressing back button.My problem is that when I use the icon to start my home activity it does not uses the previous instance from the stack and start creating it again.
My Action bar app icon code is :
startActivity(new Intent(this, DashBoard.class)
.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP));
this above code starts Dashboard activity and calls its both onCreate() and onResume().But If I uses back button to return to this activity from any activity it just calls onResume().
Activity definition from manifest file:
<activity
android:name=".DashBoard"
android:configChanges="keyboardHidden"
android:label="#string/app_name"
android:screenOrientation="portrait" >
</activity>
Why is this happening?Am I missing something to prevent it from not creating it again?Please help
Thanks
Use setFlags(), instead of addFlags(). You are on right track. Use the following code.
Intent intent = new Intent(this, DashBoard.class);
intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP|Intent.FLAG_ACTIVITY_SINGLE_TOP);
startActivity(intent);
Remove the FLAG_ACTIVITY_CLEAR_TOP.

Categories

Resources