Android can i avoid onCreate() being called? - android

I have two applications App-1 & App-2. App-2 has a button which will start App-1.
The need is to behave like the following:-
User launches App-1 (using launcher) & activities A, B & C are started & activity C is at the top of the activity stack.
Please note that entry point of App-1 is activity A.
User presses home key.
User then launches the application App-2. User chooses the button in App-2 to start App-1.
onClick() of the button in App-2 has the following code:-
Intent i = new Intent();
i.setAction("com.x.y.z"); //resolves to activity A of App-1
i.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_NEW_TASK);
i.putExtra("x", "y");
startActivity(i);
After step-4, onCreate() of activity A is called which is quite normal. But I want Android to bring the entire Activity Stack to be brought to the foreground, since App-1 is running & Android hasn't killed it.(Which is the same behavior if I had launched App-1 after step-2).
I want activity C to be shown to the user.
Kindly help me if it is possible to do this.
I have tried making activity A as singleTask & singleInstance. if i do that, only activity A is brought to the foreground which is not what i want.
the snippet of App-1's manifest looks like below:-
<activity android:name=".aa.a"
android:configChanges="orientation|keyboardHidden|locale"
android:label="#string/app_name"
android:theme="#android:style/Theme.NoDisplay"
>
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
<intent-filter>
<action android:name="com.x.y.z" />
<category android:name="android.intent.category.LAUNCHER" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</activity>

FLAG_ACTIVITY_NEW_TASK informs Android to start a new task; the new task doesn't contain B & C, so don't expect any of them to be shown.
Also, FLAG_ACTIVITY_CLEAR_TOP removes B & C, which is exactly opposite to what you want.
Try removing both flags.

Related

App started from deep link, then activated again from launcher restarts the activity

The following situation:
app is started from a deep link (sms) and launches the MainActivity
user presses the start button in the app which opens SecondActivity
app goes into background
user presses on app icon again in launcher => HERE I EXPECT the SecondActivity be still active. But instead, MainActivity is relaunched.
Tried with "singleTop" activity mode - no difference.
SecondActivity is launched from MainActivity without any special intent flags, plain startActivity()
<activity
android:name=".MainActivity"
android:label="#string/app_name"
android:screenOrientation="portrait"
android:alwaysRetainTaskState="true"
android:launchMode="singleTop"
android:windowSoftInputMode="adjustResize">
<intent-filter>
<action android:name="android.intent.action.MAIN"/>
<category android:name="android.intent.category.LAUNCHER"/>
</intent-filter>
<intent-filter>
<action android:name="android.intent.action.VIEW"/>
<category android:name="android.intent.category.DEFAULT"/>
<category android:name="android.intent.category.BROWSABLE”/>
It turned out there are two reasons:
Starting app from deep link created separate instance of the app => solved by specifying "singleTask"
The SecondActivity was destroyed at some point, which explains why starting the app again from icon will bring MainActivity screen
Thanks all commenters for helpful hints!
When starting the secondActivity you can just call finish() in the firstActivity (for example in onPause() or buttonClick() firstActivity). In this way, your app is still running (i.e secondActivity). When you launch the app the secondActivity should run directly (if the app is not totally destroyed yet).

launchMode="singleTask" does not create a new task

I have 2 activities: Activity A and Activity B. Activity A's launch mode is standard, and Activity B's launch mode is singleTask.
<activity
android:name=".AActivity"
android:label="#string/app_name"
android:launchMode="standard">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
<intent-filter>
<action android:name="android.intent.action.VIEW" />
<data android:scheme="dd"></data>
<data android:host="a"></data>
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
</intent-filter>
</activity>
<activity
android:name=".BActivity"
android:label="#string/app_name"
android:launchMode="singleTask">
<intent-filter>
<action android:name="android.intent.action.VIEW" />
<data android:scheme="dd"></data>
<data android:host="b"></data>
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
</intent-filter>
</activity>
I launch the app, and the launcher Activity A starts. Then i press Home Button and return to home screen of the phone. Then i launch browser app and type the following:
dd://b
to open Activity B. The system navigates to my App and starts activity B on top of activity A. At this point if i press back button, activity B is popped and i see activity A.
This is not what i expected because the android documentation states:
For singleTask activities, the system creates a new task and instantiates the activity at the root of the new task. However, if an instance of the activity already exists in a separate task, the system routes the intent to the existing instance through a call to its onNewIntent() method, rather than creating a new instance. Only one instance of the activity can exist at a time.
What i understand from these sentences is, in my case since an instance of Activity B does not exist, a new task should have been launched and it should have had only Activity B at its stack(Another instance of my app should still exist in a separate task and it should have Activity A in its stack). Then if i press back while i was at Activity B, since it is the only activity in the backstack, it is popped out and the system returns to the browser.
Why this is not the case? How does android system know that my app is open and navigates to it and starts activity B on top of existing app stack instead of launching another instance of my app and letting two instances of my app have their own stacks? What does it mean to instantiate activity in a new task? Can anyone explain?
Thanks.
In addition to the accepted answer, I found an explanation to this problem. As android documentation states:
The affinity indicates which task an activity prefers to belong to. By default, all the activities from the same application have an affinity for each other. So, by default, all activities in the same application prefer to be in the same task which belongs to that app(The app that has the Activity B). However, you can modify the default affinity for an activity.
So, if your app is running, and you start an activity, which has launchMode:singleTask attribute, unless you explicitly state taskAffinity attribute, it starts the activity in the same task. But if you explicitly state an affinity in your manifest:
<activity
android:name=".BActivity"
android:label="#string/app_name"
android:taskAffinity=""
android:launchMode="singleTask">
</activity>
then it starts the activity in a new task.
You can see which activity belongs to which task by the following adb command:
adb shell dumpsys activity
and also, to better understand launchMode concept, you can see the following app in the Google Play: https://play.google.com/store/apps/details?id=com.novoda.demos.activitylaunchmode
You said that your app navigate to B in passing by A.
So, i think you have two stack. In the first, you have only A, in the second you have only B. If you press back, then B is popped and disapeared but A exists and is showing because A in behind B even if A and B are in separate stack.
If you want that B pop and then you return to home, try to call "finish()" after call B from A

Start Activity with NFC in a specific task

My app contains a number of activities. One of these activities responds to an NFC intent filter, as well as standard intents, however, this activity is launching in it's own task, and not in the same task as the app. The app is not necessarily running when the NFC intent is initiated but if it is, I want the activity to launch in the same task to ensure a seamless user experience. At the moment, the app is behaving as though there are 2 of them running.
Here is the manifest for my NFC activity:
<activity
android:name="name.subname.app.activity.ItemSummaryActivity"
android:label="#string/title_activity_item_summary" >
<intent-filter>
<action android:name="android.nfc.action.NDEF_DISCOVERED" />
<data android:mimeType="application/vnd.name.nfcdemo" />
<category android:name="android.intent.category.DEFAULT" />
<data android:mimeType="text/plain" />
</intent-filter>
</activity>
Is it possible to launch the activity in the existing task, if it exists?
I see two options here:
1) Add android:launchMode="singleTask" to activity tag in the manifest:
<activity
android:name="name.subname.app.activity.ItemSummaryActivity"
android:label="#string/title_activity_item_summary"
android:launchMode="singleTask" >
"singleTask":
The system creates the activity at the root of a new task and routes the intent to it. However, if an instance of the activity already exists, the system routes the intent to existing instance through a call to its onNewIntent() method, rather than creating a new one.
2) Supply Intent.FLAG_ACTIVITY_BROUGHT_TO_FRONT flag to startActivity() intent. But, if the activity is triggered by NFC (and using this option is not feasible) consider what #NFC guy has to say here.

Android launchMode="singleTask" and Intent-filters

So I have an Activity A that is defined in the AndroidManifest.xml as defined below:
<activity
android:name=".activity.A"
android:screenOrientation="landscape"
android:windowSoftInputMode="stateAlwaysHidden"
android:launchMode="singleTask">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
This Activity launches a welcome Screen which we will call Activity B.
If you launch the application the Welcome screen is displayed and then once the user is done with it Activity A comes back.
The issue I am having is when I push the "Home" button from the welcome screen I go back to the Home Screen as expected. Now when I reclick on the Application Icon the application won't launch. Instead both my Activity A & B get destroyed. If I click on the icon again then the application relaunches as expected.
Now if I'm on the welcome screen and push the back arrow and reclick on the App icon it launches the application as expected. I don't have to push it twice.
Unfortunately I have to use the launchMode="singleTask" since it is a requirement for integration with another team. I have read the Android API's for Tasks and Back Stacks numerous times. Any pointers or suggestions would be greatly appreciated.
I came across a blog indicating there is an undocumented bug with using singleTask and intent-filters together but didn't find any official documentation on this.
Thanks
EDIT
Launching Activity B like this:
Intent intent = new Intent(context, B.class);
startActivityForResult(intent, CONST_VAR);
I tried making two activities which launches ActivityB from Activity A. I see no such problem as described in the question. PFB my manifest. Also, when you say home button, is it Phone home button or your app specific home button. PFB my manifest
<activity
android:name="com.android.testsingletask.MainActivity"
android:launchMode="singleTask"
android:screenOrientation="landscape"
android:windowSoftInputMode="stateAlwaysHidden"
android:label="#string/app_name" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity
android:name="com.android.testsingletask.WelcomeActivity"
android:screenOrientation="landscape"
android:windowSoftInputMode="stateAlwaysHidden"
android:label="#string/app_name" >
</activity>

How to make multiple intent filters start an activity in the same task

I have two intent filters for the root activity of my application
<activity
android:name=".MyActivity"
android:label="#string/app_name"
android:theme="#android:style/Theme.Dialog" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
<intent-filter>
<action android:name="android.nfc.action.NDEF_DISCOVERED" />
<data android:mimeType="application/com.example.package" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</activity>
One filter is for launching the application from the launcher icon, the other is to launch the activity when the user touches an NFC tag.
I want that when user presses the HOME button from any activity in the application, the next time he presses the launcher icon or touches NFC tag, the application must resume (as it is the case with every application).
But this is what is happening:
When user taps the NFC tag, the first activity is launched. Then he navigates onto further activities. Presses HOME. Taps the NFC tag again, the first activity (MyActivity) is launched, and the previous stack is cleared.
On the other hand,
When the user selects the launcher icon, navigates onto further activities, presses HOME, and then presses the the launcher icon again, MyActivity is started as a new activity on top of the stack. (now there are two MyActivities in the stack).
You need to define the way your activity launches.
If you want your activity to always launch on the same task use: android:alwaysRetainTaskState="true" and android:taskAffinity="your.task.name"
Also take a look on android:launchMode="singleTop" and android:launchMode="singleTask" for further control on how the activity is launched.

Categories

Resources