Help with first Android Activity - android

When my app first opens my first activity that is presented to the user can vary based on configuration options. I only know how to hard code the first activity that runs when the app is running by adding something like this in the Manifest
<activity android:label="#string/app_name" android:name=".MyFirstActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
Where MyFirstActivity is the class name of the first activity class to be run. How can I dynamically select which activity to run first when the app is first launched rather than hard code it in the manifest?
Thanks!

Option #1: In onCreate() of MyFirstActivity, call startActivity() for the right activity, then finish().
Option #2: Define several activities with the LAUNCHER <intent-filter>, all but one disabled. On first run (or as needed), enable the right activity and disable the others. Downside: may require a phone reboot to update the launcher, since not all home screen launchers will detect your change.
Option #3: Redesign your GUI such that this is not an issue.

Related

SingleTask activity is created multiple times within the same process

I have a launcher app which has a singleTask activity as the main entry point. When the user navigates away to another activity or to a 3rd party app and then hits the home button, then this activity should be brought to the front. However what I experience is that for the first home button press only, another instance is created instead (a new task is created, onCreate() is called). In the meantime the old task is still alive, containing the original instance of this activity, but it is impossible to navigate back to that task/activity or to bring it to the foreground.
After the first home button press, the next home button press brings the 2nd instance of this activity to the foreground. Not sure why not the very first instance's onNewIntent() method is called for the first time... So this only happens once, after that always the 2nd instance's onNewIntent() method is called. This means that the original activity will be not accessible..
I tried to bring the task to the foreground, nothing was happening... Like if it never existed (but the task is there with the activity, it is not killed at any point). I can find the task from code and also using a shell script. It contains the original activity
This is happening on Android TV (Os: Pie). Any idea what can be the reason for this? I do not really understand how this is happening... BTW the result is the same if I set the activity to singleInstance.
The activity looks like this:
<activity
android:name=".activities.MainActivity"
android:excludeFromRecents="true"
android:launchMode="singleTask"
android:theme="#style/AppTheme">
<intent-filter android:priority="2">
<action android:name="android.intent.action.MAIN"/>
<category android:name="android.intent.category.HOME"/>
<category android:name="android.intent.category.DEFAULT"/>
<category android:name="android.intent.category.LEANBACK_LAUNCHER"/>
<category android:name="android.intent.category.LAUNCHER"/>
</intent-filter>
<intent-filter>
<action android:name="android.intent.action.ALL_APPS"/>
<category android:name="android.intent.category.DEFAULT"/>
</intent-filter>
</activity>
I tried alternating the above attributes (priority, excludeFromRecents, taskAffinity), also removed them completely, they had no effect...
The home button press sends the following intent:
action: "android.intent.action.MAIN"
category:
"android.intent.category.HOME"
component: the above activity
it has also some extras but I do not think it is relevant
You are experiencing this nasty long-standing Android bug:
Re-launch of Activity on Home button, but...only the first time
You say in a comment that it doesn't happen with real users. That is not actually true. If a real user would install your app from the Play store and then launch it immediately (click the OPEN APP button after installation) then the problem would be reproduced exactly as you describe it.
I was struggling with the exactly same issue for the last couple of hours and I've read many similar Q&A about this topic/bug on StackOverflow. No solution really worked for me until, out of mere curiosity, I did the following.
If you're building a launcher and using onNewIntent() in your MainActivity (although OP doesn't mention that he's using this method), then simply comment out this line:
super.onNewIntent(intent);
Uninstall your app and install it again.
I don't know how this works, but EVEN when you then uncomment the very same line, it still behaves in a proper manner, that is: the app has really only single instance of its main activity all the time. And how I know that? My MainActivity is doing some database operations, and previously I saw in my Logcat that these operations were done twice every time, but now they are done only once.
And BTW my MainActivity tag in AndroidManifest.xml is nothing special:
<activity
android:name=".activities.MainActivity"
android:exported="true"
android:excludeFromRecents="true"
android:launchMode="singleTask">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
<category android:name="android.intent.category.HOME" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</activity>

Avoid Activity resuming when app goes in background

In my application I have three activities:
<activity
android:name="com.example.myapp.SplashScreenActivity"
android:exported="true"
android:launchMode="singleInstance"
android:noHistory="true"
android:screenOrientation="sensorLandscape" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity
android:name="com.example.myapp.MainActivity"
android:exported="false"
android:launchMode="singleInstance"
android:screenOrientation="sensorLandscape" >
</activity>
<activity
android:name="com.example.myapp.ListActivity"
android:exported="false"
android:launchMode="singleTop"
android:screenOrientation="sensorLandscape" >
<meta-data
android:name="android.support.PARENT_ACTIVITY"
android:value="com.example.myapp.MainActivity" />
</activity>
The first one is the LAUNCHER, SplashScreenActivity, which is a splash screen that disappears quite soon and it's not shown in recent activities, it starts MainActivity. In MainActivity users can select a category and ListActivity shows the items belonging to the given category. This is done with the following code:
Intent i = new Intent(getActivity(),ListActivity.class);
i.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK|Intent.FLAG_ACTIVITY_REORDER_TO_FRONT);
i.putExtra("category",mCategory);
startActivity(i);
In ListActivity the onResume method checks for the "category" extra and shows data accordingly. Since Activity launchMode is singleTop, I've also overridden the onNewIntent method to set the new Intent of the Activity.
This works properly if the app doesn't go in background: in this case, when I restart MainActivity and select a category, ListActivity resumes the old Activity showing data belonging to the previously chosen category.
How should I fix flags/launchMode in such way that my app doesn't resume ListActivity with the old data loaded?
You should not use the special launch modes. These are rarely required and only in very specific circumstances. Remove all the launchMode specifiers from your manifest. You also don't need to use these flags when launching ListActivity from MainActivity:
i.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK|Intent.FLAG_ACTIVITY_REORDER_TO_FRONT);
Your use of singleInstance launch mode is causing you all these problems.
Assuming you would ditch all the launchModes and Flags, then activity lifecycle gives you all the information needed to implement application as you have described - maybe there is somethings you have not added?
Once application goes to background, then ListActivity will be allowed to save its state, even if system will kill your process (lack of memory etc.), then still - launching back your app will first bring back ListActivity with previously saved instance state. So you will not have behaviour as you describe : when I restart MainActivity and select a category, ListActivity resumes the old Activity showing data belonging to the previously chosen category.
Still, if you need to keep to your current design, then you should somehow inform ListActivity of new data changes, question is if ListActivity.onNewIntent is being called at all in the case your describe? Have you tried adding Intent.FLAG_ACTIVITY_SINGLE_TOP : as per this blog entry: http://www.acnenomor.com/1094151p2/bug-onnewintent-not-called-for-singletop-activity-with-intentflagactivitynewtask ?

Change Android App starting activity

I'm trying to change the start up activity.
I created an activity when the app loads but I want to add a screen before that, I'm not sure where to change the Android manifest to load a certain layout/activity when the app starts.
The startup activity [Launcher Activity] is declared in the projects' AndroidManifest.xml file
Look for that activity tag in the manifest which looks like this
<activity android:name=".Main"
android:label="#string/app_name">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
Look at the attribute android:name. Main is the class which is launched when the app starts. Currently your calendar activity name should be there. Change that to the .classpath of your activity that you want to launch.
That should do it. You may also want to do the hello world application in the tutorials and go through the docs a little to see how Android Applications work.
From here
Just create another activity and set it as Launcher Activity and after a timer (if that's your achieve) just call the other activity!

How could I set an activity to be the one to be resumed (by multitask)

I am experiencing a little pain on Android. I have two activities, one is a Splash Screen, launched when you click on the app icon, and an other one which can wake up when a specific event occurred (a NFC event, but it is not the problem).
There is the declaration in the manifest :
<activity android:label="#string/general.appName" android:name=".activity.SplashActivity" android:screenOrientation="portrait">
<intent-filter>
<action android:name="android.intent.action.MAIN"/>
<category android:name="android.intent.category.LAUNCHER"/>
</intent-filter>
</activity>
<activity android:excludeFromRecents="true" android:label="#string/general.appName" android:name=".EventReceiver" android:noHistory="true" android:screenOrientation="portrait">
<intent-filter>
<action android:name="android.nfc.action.TRANSACTION_DETECTED">
</action>
<category android:name="android.intent.category.DEFAULT">
</category>
<data android:host="secure" android:path="/aXXXXX" android:port="0" android:scheme="nfc"/>
</intent-filter>
</activity>
All works fine, it means that the EventReceiver is launched when it received a specific event, the Splash Screen is functional etc...
But, when the application is launched by an event, so it is the EventReceiver which is launched first. If I pause the app by clicking on the home button of the phone, and by long clicking on it again, it makes appear the multitask table, with all the recent opened apps. There, is I click on my application, it resumed the application on the EventReceiver, just like if an event had occurred. So do you know a way to resume an application on one selected activity only (in my case the SplashScreen).
Or do you know a way to recognize that the application was resumed by a multitask function ? (I could open the good activity at the onCreate of my EventReceiver too if I get this information).
For the moment, the only solution I found is to put a android:excludeFromRecents="true" flag on my EventReceiver activity. This will result that the application will not appear in the multitask table if the application was launched by an event. But this is a little bit tricky and I do not like that very much.
Do you have any ideas ?
Thank you very much beforehand for your answers ! (and sorry for my scholar English ^^)
If you really have to detect when the application is lauched from the "recents" you can use intent flags.
if (getIntent().getFlags() & Intent.FLAG_ACTIVITY_LAUNCHED_FROM_HISTORY) {
// Lauched from recent apps.
}
Do NOT use a splash screen. It only slows down your app experience and has no value what so ever.
In addition... Android apps are a lose set of activities... There is no concrete entry point that would need a splash screen.
That said... the app switcher returns you to the previously active activity. In your case the .EventReceiver. You could change your structure by using a second activity that shows your ui so that the EventReceiver lets you forward to that.
Correct me if i am mistaken... But can't you intercept the nfc event with an receiver? From there you should open your ui activity.

Android Program Flow Help

Consider the following:
I have three packages:
package.a
package.b
package.c
Each package contains a class and an activity
package.a>>activity.a>>class.a
package.b>>activity.b>>class.b
package.c>>activity.c>>class.c
I am assembling all of these together into one application and I want activity.c to be the first activity in the stack. In other words, I want it to run first. Do I simply modify the order in the manifest? What initializes the first application and what sets their corresponding order? After the first activity is started can I just go back and forth with intents?
Thanks for your help!
You want to use the CATEGORY_LAUNCHER intent filter on the activity you want to be launched when the application starts.
From the documentation:
CATEGORY_LAUNCHER The activity can be the initial activity of a task and is listed in the top-level application launcher.
Once the application is started, you can move back and forth using intents.
You need to set your activity C with this intent filter:
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
This way that will be the only activity launched from the home screen.

Categories

Resources