Related to: Android Messaging, Email app behavior when starting app from a link
To be able to start my app from an SMS, and then upon hitting the Messaging icon, have Messaging go back to where it was before (at the message showing the link), I added this to the manifest:
<activity android:name=".SMSActivity" android:launchMode="singleTask" >
But now when I do this, my app starts up great the first time I click the link in the SMS. If I then go back to Messaging and click the same link, my app is started, but with a completely black screen.
It seems I can't have it both ways. Changing the launchMode to singleTop fixes this problem, but if I do that, then if I launch the app from the SMS, my app takes over the Messaging app. The Recent list shows only the Messaging app running my app. I can't go back to Messaging.
There must be a way to get this to work. I have tried many combinations of launch modes in the manifest, and intent flags when starting up SMSActivity. Currently I am just using default flags when starting SMSActivity. I am not adding any flags to the Intent.
Thanks
Related
Tested on Pixel 3a (both emulator and physical device (my used device)) API 30 (11.0).
Repo:
https://github.com/amdreallyfast/AndroidStartOnBootExample
Goal:
I'm trying to launch an android app on startup, but failing.
Note: I am well aware that this should not be done for apps designed for the general public. This is not that. At the moment, this is just concept exploration for a personal project. The larger goal is to tinker with a used Pixel 3a and turn it into a home utility device. I don't want to start the app manually every time I need to turn it on and would rather have it starting automatically, so I'm trying to find a way to launch the app at startup.
Also Note: Because this is a project to start on boot, I can't use the debugger for most of this and have to rely on notifications instead to detect progress.
Progress:
I've got a BroadcastReceiver that responds to the BOOT_COMPLETED intent by launching a Service. The service's onCreate(...) function creates a simple intent to start another app (at the moment, just Google Maps, which is readily available without additional software installation).
I've also got MainActivity, a simple program that has a button that uses an intent to launch the same Service. I use this to compare behavior between starting the service at startup and starting the service from an already-running activity.
Already tried setting the intent flag Intent.FLAG_ACTIVITY_NEW_TASK.
Problem:
Google Maps does not launch from the service when called during startup. I know that the service's code is correctly set up to launch the map intent because launching the MainActivity and pressing the button will launch the service and then start Google Maps just fine. I also know that the code running on startup got through to the point where it launched the map intent because notifications indicate as such.
The only difference that I'm noticing between not working and working seems to be the manner in which the service is started.
Documentation:
I found this android docs page: https://developer.android.com/guide/components/activities/background-starts. It says (in part):
Apps running on Android 10 or higher can start activities only when one or more of the following conditions are met:
The app has a visible window, such as an activity in the foreground.
<other possible conditions>
Why doesn't this start? Am I misunderstanding this? Google Maps most certainly has a visible window, so I am expecting to be able to start it.
Note: Again, I'm not planning on releasing my app to the general public. This is just for me.
The larger goal is to tinker with a used Pixel 3a and turn it into a home utility device
Write a launcher app (i.e., have your activity respond to ACTION_VIEW/CATEGORY_HOME) and set it as your default launcher. It will automatically start when the phone starts, just as your current default launcher does. And, you can put a button or something in your own launcher that launches the real launcher via an explicit Intent.
This would allow you to skip the on-boot receiver and the service.
Why doesn't this start?
You do not qualify for a background activity start.
Google Maps most certainly has a visible window, so I am expecting to be able to start it.
First, presumably it does not have a visible window right after boot.
Second, you are not writing the Google Maps app, and Google Maps is not trying to start an activity from the background. You are writing your own app, and your own app is trying to start an activity from the background. And, since your own app does not have a visible window right after boot, it does not qualify for a background activity start under the "app has a visible window" rule.
Following up on the answer by #CommonsWare, here is my activity's configuration in my app's manifest file (just for the sake of completeness):
<activity
android:name="com.example.androidstartonboot.MainActivity"
android:launchMode="singleTask"
android:stateNotNeeded="true"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.HOME" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
Note: Strictly speaking, launchMode and stateNotNeeded are not necessary for MainActivity to successfully launch on startup, but my understanding is that it is good practice to add them to a launcher. Documentation: https://developer.android.com/guide/topics/manifest/activity-element
To enable:
Run the app (or run the debugger) to install.
Press the "Home" button (solid dot on Android 11). Android should present an option for which app to use to respond to the LAUNCHER intent. There should be two options: "Pixel Launcher" (the Android default) and the app who's MainActivity is configured as above.
Select your app and choose "Always use this app".
Now, every time you press the "Home" button, your app should run.
Note: To restore the "Pixel Launcher" as the default launcher:
Swipe down from top
-> Settings
-> Apps & Notifications
-> All Apps
-> Pixel Launcher
-> Advanced
-> Home (should say "No" at this point)
-> <choose "Pixel Launcher">
This was tested on Android Studio Bumblebee | 2021.1.1 Patch 2, in a Kotlin project.
Note: This does not work if there is also a BroadcastReceiver that the manifest is configuring to respond to the intent filter <action android:name="android.intent.action.BOOT_COMPLETED". I tried it. Disabling the BroadcastReceiver allowed this to work. Re-enabling it prevented MainActivity from launching on startup. So that needs to be commented out/removed before this launcher will work.
I have an application which I simply want to run but it should not have launcher Icon.
I have deleted this tag
category android:name="android.intent.category.LAUNCHER" />
But then Android studio starts to give error that
Could not identify launch activity: Default Activity not found
Error while Launching activity
then I switched the run configuration as the following :
What I want :
I just want that My application start running once I run it from the android studio , but it must not have launcher icon . SO that user should not be able to launch it by himself.
Note:
I do know that it is not legal we should have activity so that user can se it , use it and change something if he wants. But that is not the case in my app as the user want himself to hide its launcher so that no body knows about app. So do not worry about such case. :)
I have an application which I simply want to run but it should not have launcher Icon.
Then your app will never run.
running service or broadcast receiver
Your app, once installed, is in a stopped state. None of your code will run until something uses an explicit Intent to start one of your components. Normally, that is the launcher icon. Other possibilities include if the user sets up an app widget, or if your app is a plugin for some other app (and that other app uses an explicit Intent to start one of your components). Outside of those scenarios, your app will never run. This is to help prevent malware.
the user want himself to hide its launcher so that no body knows about app
You will still need a launcher icon. However, when the user runs your app, you can use PackageManager and setComponentEnabledSetting() to disable that activity, so it will no longer show up in the launcher.
My Android application is being restarted when using the launcher to launch it after I have used the app store to launch it (and visa versa). Is there any way to prevent this?
By restarted I mean that the activity stack is lost. This is important as our users are setting up and returning to an activity in the app intermittently over the course of an hour or so. After first install, they will likely have installed and opened the app from the app store, set themselves up and then backgrounded the app. Later they are likely to open the app from the launcher and lose all their state!
The problem is further compounded as we start a foreground service along with the set-up activity. Clicking the services notification should bring the user back to the set-up activity but, as with the launcher, if the user originally opened the app from the Play store, they again lose all their state!
Reproducing the problem
I've made a sample application here:
https://github.com/samskiter/LaunchTest
Note: it uses the BBC weather application package Id in order to allow you to quickly open from the app store (the "Open" button will be shown on the BBC weather application if this app is installed).
Steps are as follows:
Uninstall the BBC weather app if you have it
Install the LaunchTest app
Close the LaunchTest app from recents
Open the LaunchTest app from the BBC weather app page on the Play Store
Click the button to navigate to the Second activity
Background the application (press home)
Open the LaunchTest application from the app launcher
The state is lost! you are back at the First (root) activity
What I've tried
Using singleTask launch mode hasn't helped - it causes the app to be relaunched even if you use the launcher every time.
I've tried alwaysRetainTaskState - I don't really expect this to work as this only really affects things over about a 30 minute wait.
What I think is going on
There is no mechanism in the activity manager / intent system to open a running app in it's current state. Instead, I think the UID of the launching application is taken into account. If it is different then the Intent.FLAG_ACTIVITY_NEW_TASK flag is forced and so created a new task and dropping all my users' lovely state.
Inspecting Google Maps
Google maps has a very similar interaction model to our application: a setup UI, followed by an ongoing process the user is going through for a long period of time (navigation) with a paired, foreground service (the navigation service you can see in your notification bar). BUT GMaps doesn't suffer from this problem. I think this is because it uses only a single activity for all of it's interface and uses singleTask. So now, when you tap on the launcher after originally launching from the play store, the task can be reused.
In my opinion this exposes a hole in the android intent/activity management system. The whole point of the savedInstanceState/activity lifecycle is to prevent dropping state, but here we have a way to dump everything. My current best solution is to detect app restarts by the fact the service is running and try to get the user back to where they were, which is more than a little tricky.
If someone knows a way I can prevent my state being dropped on the floor when reopening from the app launcher after opening from the store, I would really appreciate it.
This is more like a workaround to your problem, but it seems that there may be no real solution.
My first thought was - since the whole setup will take a while anyway - why don't you just save some kind of bookmark ('firstLaunch') to Preferences, post a (delayed?) notification and finish the app, so that the user has to open it again by tapping on the launcher icon. Only then you start the real setup, so you will not lose information due to the installer vs launcher problem.
But the problem seems to have been around for some time and the following SO-posts may help:
Re-launch of Activity on Home button, but…only the first time
After tap on app icon,launcher create a new instance of root activity again & again
Hope this helps!
I have got an app that is using "plugin apps" (apps without launcher icon that get started via intent by the main application) and i want to have the Play Store "Open"-Button for this application to just open the main application.
Is there a way of not having the launcher icon but defining an entry point in order to launch the main application after play store install (by intent or launching a dummy activity which will launch the other applications activity immediatly).
I thought about removing the launcher category "android.intent.category.LAUNCHER" and still setting the main action "android.intent.action.MAIN". But this seems not to work at least via apk install the "Open" button is not active.
Thanks
You could try android.intent.category.INFO.
According to the documentation, this is for the case where you want to provide an entry activity for your app, but don't want your app to be shown in the app list.
I'm developing an android service application, which reacts on some intents. As you know, intents won't trigger until the app is launched for first time. Because my app is not interactive, I'd like it not to be shown in the launcher (app list). I can do this by removing
<category android:name="android.intent.category.LAUNCHER"/>
from the manifest file, but after that, how do I execute the app, as it is not shown anywhere? :|
Thanks.
What about disable the launcher icon after the application was launched the first time?
http://www.helloandroid.com/tutorials/removing-app-icon-launcher
Although this
the icon will only disapper when the launcher is restarted, so likely on next phone reboot, forcing the launcher to restart is not recommended"
doesn't sound good...
how do I execute the app, as it is not shown anywhere?
So you have to use BroadcastReceiver So similar topic where your can find similar solution. Check this
If your application is serviced based, responding to intents, why do you need to execute it? Won't the intents start your application?
Make sure you include the right intent filters in your manifest. Without them intents won't trigger your services.
http://developer.android.com/guide/topics/manifest/intent-filter-element.html