Is it possible to launch an Activity on startup in Android 11?

Viewed 631

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.

2 Answers

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:

  1. Run the app (or run the debugger) to install.
  2. 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.
  3. 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.

Related