Proper flags to start an activity from a launcher - android

I have an application that starts the app selected by a user when it is clicked (like a launcher would). Note however that the actual starting of the app is performed by a service because of abstraction.
One note by a user:
Launching greader from your app opens greader as if it had never been used, prompting for account details etc regardless of whether they have been entered previously. Launching greader from any other method (nova laucher app drawer) gets me to my usual newsfeed.
Other users are reporting issues with root explorer crashing when started.
My best bet is that is has something to do with the launch flags. After investigating the default android launcher, my conclusion is that I am using the same flags.
These flags are: Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED
What flags should I be using instead? I would not prefer to add exceptions for certain apps, so the flags should work for all apps to be started.
Thanks for any help

The problem was not with the flags themselves, they were just fine. This issue was with the action not being set properly. The problem was solved by initializing the intent like this:
Intent i = new Intent(Intent.ACTION_MAIN);
i.addCategory(Intent.CATEGORY_DEFAULT);
i.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED);

Related

Why do we get these "invalid" intents?

We have an app with an Activity that can be started in two ways:
From another Activity - always with some extra data filled in
From deep linking
As far as I can see this is always working just fine. We either get the Intent.ACTION_VIEW with a data URI, or we get some string extras.
However, we have a very few instances where action is Intent.ACTION_MAIN and there are no extra data.
The toString() of the Intent is as follows (class name changed):
Intent { act=android.intent.action.MAIN cat=[android.intent.category.LAUNCHER] flg=0x10400000 cmp=com.example.OurActivity }
Intent.getExtras() returns null, Intent.getDataString() returns null.
In which cases can this happen? Why is the category for the Activity Intent.CATEGORY_LAUNCHER? How can we get the data needed to show the user the right contents?
launchMode is not specified for the Activity. The only IntentFilter in AndroidManifest.xml is for the deep linking (and not the launcher category).
The issue happens on Android 4-6 on a wide range of devices.
Edit: Forgot to mention the flags:
As the print out suggests the flags for the Intent are FLAG_ACTIVITY_NEW_TASK and FLAG_ACTIVITY_BROUGHT_TO_FRONT. I suppose that could be relevant here.
I believe, I nailed it:
There're launchers, like Nova Launcher which allows users to start with any of app's Activities, instead of the normal flow:
For example, you can add a shortcut on your desktop to start Gmail client with Account setup Activity.
And in this case, Activity is being started with empty Extras and technically it becomes a launcher's Activity.
Now that AndroidManifest.xml is manipulated by the build system, it often happens that libraries that you include also add things to the manifest, which I suspect may be happening here.
Although you state that there is only one IntentFilter in the manifest, have you actually checked the installed app to see what its manifest says (rather than relying on what you think you put in your source code)?
Various apps are available in the Play Store to show you the manifest of an installed app - including App Detective (which I wrote).

Bring the app to foreground and if it is already running rather than creating new instance of it in android

In my app I want to launch apps(messaging,contacts,etc)if my launched app(messaging,contacts,etc) is already running in background I want it to bring front.I tried using moveTaskToFront() but it doesn't implement from above API 23(Lollipop).So,I ended up with this code:
Intent intent=getPackageManager().getLaunchIntentForPackage("com.android.mms");
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(intent);
By using this code if I launch a messaging from inside my app it launches,and if I again launches the same app from inside my app it perfectly resumes it and continue from where we left it.
But when I Launches the same messaging app from my default android launcher it just create new instance of messaging app on above of my already running messaging app which was already launched by my app.
I don't know what the solution for this.Please help me ...
Use the below approach to invoke intents within your app like this.
Intent intent = new Intent(CONTEXT, TARGET_ACTIVITY.CLASS);
intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_SINGLE_TOP | Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(intent);

Already launched Activity is not displayed in front when launching Intent

that's the second question concerning my custom Android launcher project.
This time, I encountered a problem opening Apps. It only occurs, when an App is already opened and therefore in the history.
E.g. if I open the Settings App and after that the Facebook App, both of them appear in the history. When I try launching the Settings App again, it just shows me the Facebook App.
Here is the source code of the Launching Intent. ActionName ist the PackageName of the ApplicationInfo.
Intent launchIntent = activity.getPackageManager().getLaunchIntentForPackage(actionName);
launchIntent.addCategory(Intent.CATEGORY_LAUNCHER);
//launchIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK |
// Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED);
launchIntent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_NEW_TASK);
activity.startActivity(launchIntent);
I tried all imaginable Flag-Configurations. Not just the ones you see in the code sample. (REORDER_TO_FRONT,...) Maybe I missed one.
Thanks in advance!

How to completely exit the app

I would like to exit the app completely. I tried finish() and android.os.Process.killProcess(Process.myPid()) but they still leave app running in background.
A lot of people said that this is impossible, but my bank app is able to do that. When you exit that bank app, you can't see it in Recent Apps menu.
Does anyone know how to do it?
When you exit that bank app, you can't see it in Recent Apps menu.
That has nothing to do with a process. Processes and tasks are not particularly related.
Try finishAndRemoveTask() (API Level 21+), or perhaps finishAffinity() (API Level 16+), both methods on Activity. Or, as Thom Wiggers suggests in the comments, perhaps the app is not showing up in the recent-tasks list at all, via android:excludeFromRecents.
To remove activity from recents use this in the activity tag in manifest:
android:excludeFromRecents="true"
To remove application from background use below code. Please note that this will not remove the application from recents. It justs starts the application from the starting activity.
int pid = android.os.Process.myPid();
android.os.Process.killProcess(pid);
or
Intent intent = new Intent(Intent.ACTION_MAIN);
intent.addCategory(Intent.CATEGORY_HOME);
startActivity(intent);

Android Activity Stack is not working as stated in the docs - last activity in task stack not shown

According to Android docs:
http://developer.android.com/guide/topics/fundamentals/tasks-and-back-stack.html
"When the user leaves a task by pressing the Home button, the current activity is stopped and its task goes into the background. The system retains the state of every activity in the task. If the user later resumes the task by selecting the launcher icon that began the task, the task comes to the foreground and resumes the activity at the top of the stack."
If I understand this correctly, this means:
Activity A as MAIN Activity.
Activity B that gets started in A, through "startActivity" - common, plain intent instance.
I open app for first time, A gets loaded.
I click on button in A and B is openend.
I press home button.
I open app again, for 2nd time, and B is expected to be shown
...right?
I suppose this is the correct behavior to expect...
However, I am not seeing this in my app.
If I hit "Home button" and then resume my app, by pressing the launcher icon, it will start with the main activity - not the one at the top or latest one.
I am coding on a Samsung Galaxy Tab Android 2.2.1 - I have the most common options in the Android manifest - thing is that I handle like 10 different activities with different intent extras - and a Dispatcher class approach - or save each activity state - sounds quite demanding.
I am using Eclipse IDE with ADT version 12; and I found something very interesting:
When I run the app from the Eclipse IDE, with my device connected, I don't see this behavior. The app behaves as stated in the docs.
In fact, I saw this only after I deployed my apk at the Google Play app repository; and downloaded it to test.
My question is, has anybody found the real reason why is this happening?
Is the documentation wrong? or missing something?
Is this a bug on Android?
Another research I have done is:
When I try my app, downloaded from the google play, as APK, if I enter my app for the 2nd time, I get the "main" activity instead of the last one openend. I press home.
After pressing home, I enter application management settings for android, locate my app and click on "force stop".
After doing this, the app behaves as stated in the docs.
Somebody help! :)
This is a bug in android's platform:
http://code.google.com/p/android/issues/detail?id=2373
The workaround is, to place this in the onCreate method of your main Activity:
if (!isTaskRoot())
{
final Intent intent = getIntent();
final String intentAction = intent.getAction();
if (intent.hasCategory(Intent.CATEGORY_LAUNCHER) && intentAction != null && intentAction.equals(Intent.ACTION_MAIN))
{
Log.w(LOG_TAG, "Main Activity is not the root. Finishing Main Activity instead of launching.");
finish();
return;
}
}
as extracted from:
How to prevent multiple instances of an activity when it is launched with different intents
...spent 3 days looking out for this.
I'm just going to explain why it fails, and how to reproduce this bug programmatically so you can incorporate this in your test suite:
When you launch an app through Eclipse or Market App, it launches with intent flags: FLAG_ACTIVITY_NEW_TASK.
When launching through the launcher (home), it uses flags: FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_BROUGHT_TO_FRONT | FLAG_ACTIVITY_RESET_TASK_IF_NEEDED, and uses action "MAIN" and category "LAUNCHER".
If you would like to reproduce this in a test case, use these steps:
adb shell am start -f 0x10000000 -n com.testfairy.tests.regression.taskroot/.MainActivity
Then do whatever is needed to get to the other activity. For my purposes, I just placed a button that starts another activity. Then, go back to the launcher (home) with:
adb shell am start -W -c android.intent.category.HOME -a android.intent.action.MAIN
And simulate launching it via the launcher with this:
adb shell am start -a "android.intent.action.MAIN" -c "android.intent.category.LAUNCHER" -f 0x10600000 -n com.testfairy.tests.regression.taskroot/.MainActivity
If you haven't incorporated the isTaskRoot() workaround, this will reproduce the problem. We use this in our automatic testing to make sure this bug never occurs again.
Hope this helps!
The docs are right, the only possible problem I can think of that is causing this is the device you are testing on, if it works as expected on the emulator (which is stock Android) it should work on at least 90% of Androids, its the manufactures fault for this I believe not Android.

Categories

Resources