Android BOOT_COMPLETED not received when application is closed
Asked Answered
B

9

36

I am aware that this question has been asked a lot on the site, however, I cant seem to find a solution. My BOOT_COMPLETED receiver is not called when the application is not running.

Manifest:

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.startuptest"
    android:versionCode="1"
    android:versionName="1.0"
    android:installLocation="internalOnly">
    <uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
    <uses-sdk android:minSdkVersion="8" android:targetSdkVersion="17" />

    <application
        android:allowBackup="true"
        android:icon="@drawable/ic_launcher"
        android:label="@string/app_name"
        android:theme="@style/AppTheme" >
        <activity
            android:name="com.example.startuptest.MainActivity"
            android:label="@string/app_name" >
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>

        <receiver android:name="com.example.startuptest.StartUpBootReceiver" >
            <intent-filter>
                <action android:name="android.intent.action.BOOT_COMPLETED" />
            </intent-filter>
        </receiver>
    </application>
</manifest>

StartUpBootReceiver:

public class StartUpBootReceiver  extends BroadcastReceiver {

    @Override
    public void onReceive(Context context, Intent intent) {

        Log.d("startuptest", "StartUpBootReceiver " + intent.getAction());

        if ("android.intent.action.BOOT_COMPLETED".equals(intent.getAction())) {
            Log.d("startuptest", "StartUpBootReceiver BOOT_COMPLETED");
        }
    }
}

If the application is running and I simulate a call with

adb shell
am broadcast -a android.intent.action.BOOT_COMPLETED

The event is received correctly, however, if the application is closed the event is not receieved, nor is it received at start up.

I have installed the application then launched it a couple of times to make sure it is registered. I'm pretty lost on this one so any advice would be highly appreciated.

Edit: I can see in the logs that all the other closed applications (Youtube, FileObserver, etc) receive the boot_completed event, just not mine.

Bayne answered 21/6, 2013 at 1:33 Comment(0)
K
41

I start my app when the BOOT_COMPLETED, so I know it's working. I add Log.d it won't show. I add Toast it show. Small differents in Manifest.xml

<receiver android:name="com.example.startuptest.StartUpBootReceiver">
    <intent-filter>
         <action android:name="android.intent.action.BOOT_COMPLETED" />
    </intent-filter>            
</receiver>
Koeppel answered 21/6, 2013 at 7:51 Comment(9)
I had left out the Default tagBayne
Thanks, this did the trick. android:enabled="true" android:exported="true" are also required so Android knows about this receiver.Pogonia
But aren't these the defaults. developer.android.com/guide/topics/manifest/…Tarantella
You'll receive the Log.d on another process console in the Android monitor because exported="true" makes the receiver as a new processGarrott
@Pogonia these two are true by default - if something started working likely you just turned on "run in background" on meizu flyme, or added application to protected on huawei or whatever may surprisingly happen on contemporary phones. Except maybe for priority=999.Nissie
<category android:name="android.intent.category.DEFAULT"/> and android:enabled="true" android:exported="true" aren't neededCounterproposal
In my experience android:exported is not required. But the enabled flag is required.Eggshaped
@Eggshaped enabled is true by defaultCounterproposal
export is providing components of your app to other appsCounterproposal
C
111

Starting with Android 3.1 all applications, upon installation, are placed in a "stopped" state.(This is the same state that the application ends up in after the user force-stops the app from the Settings application.)

Android stopped state

While in "stopped" state, the application will not run for any reason, except by a manual launch of an activity. (Meaning no BroadcastReceviers(ACTION_PACKAGE_INSTALLED, BOOT_COMPLETED etc.) will be invoked, regardless of the event for which they have registered, until the user runs the app manually.)

This is an anti-malware move by Google. Google has advocated that users should launch an activity from the launcher first, before that application can go do much. Preventing BOOT_COMPLETED from being delivered until the activity is launched is a logical consequence of the that argument.

More details about this:
http://developer.android.com/about/versions/android-3.1.html#launchcontrols
http://commonsware.com/blog/2011/07/05/boot-completed-regression.html
http://devmaze.wordpress.com/2011/12/05/activating-applications/

Confirmatory answered 8/11, 2013 at 10:8 Comment(6)
this answer is must read if you have app with only BroadcastReceiver and Service for itIveson
This link also covers the related topic.Sulphonate
But then what is the point of registering a boot complete broadcast in the first place? The way I see it, if I not able to take any action/do something in the time after the device is booted and before the app is launched by the user, then what purpose will registering a boot complete receiver solve?Chlorothiazide
@Chlorothiazide I was confused as you are, but after few hours reading around, I got these ideas. Applications are in a stopped state when they are first installed but are not yet launched and when they are manually stopped by the user (in Manage Applications). That means, user should launch app at least once after installation to activate the application, then the app can receive all implicit broadcast from OS as normal.Gilbertine
take a look at my answer to get more detail: #20441808Gilbertine
Might not affect many of you, but it could be of someone else's interest: in my case it was an option to compile my app as a system app into an Android ROM. Seems like system apps are NOT in the "stopped state" by default, so I was able to bake an app without an activity into an Android build and its service was started automatically because it could receive the BOOT_COMPLETED intent. Tested with AOSP API version 29.Asdic
K
41

I start my app when the BOOT_COMPLETED, so I know it's working. I add Log.d it won't show. I add Toast it show. Small differents in Manifest.xml

<receiver android:name="com.example.startuptest.StartUpBootReceiver">
    <intent-filter>
         <action android:name="android.intent.action.BOOT_COMPLETED" />
    </intent-filter>            
</receiver>
Koeppel answered 21/6, 2013 at 7:51 Comment(9)
I had left out the Default tagBayne
Thanks, this did the trick. android:enabled="true" android:exported="true" are also required so Android knows about this receiver.Pogonia
But aren't these the defaults. developer.android.com/guide/topics/manifest/…Tarantella
You'll receive the Log.d on another process console in the Android monitor because exported="true" makes the receiver as a new processGarrott
@Pogonia these two are true by default - if something started working likely you just turned on "run in background" on meizu flyme, or added application to protected on huawei or whatever may surprisingly happen on contemporary phones. Except maybe for priority=999.Nissie
<category android:name="android.intent.category.DEFAULT"/> and android:enabled="true" android:exported="true" aren't neededCounterproposal
In my experience android:exported is not required. But the enabled flag is required.Eggshaped
@Eggshaped enabled is true by defaultCounterproposal
export is providing components of your app to other appsCounterproposal
S
29

Each answer here add a small piece of information, so here is the summary of it all:

To make sure you will receive the BOOT_COMPLETED make sure you do the following:

  1. Add your receiver to manifest (don't forget the flags):

    <receiver android:name="com.yourpacakge.BootReceiver" android:exported="true" android:enabled="true">
        <intent-filter>
            <action android:name="android.intent.action.BOOT_COMPLETED"/>
            <category android:name="android.intent.category.DEFAULT"/>
        </intent-filter>
    </receiver>
    
  2. Add permission:

    <uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED"/>

  3. After installing your app, it needs to be lunch at least once, manually by the user, in order to receive Boot complete event.(More details)

Stage answered 16/8, 2015 at 6:30 Comment(3)
I am seeing that [on Marshmallow at least] if I Force Close my app, then the BroadcastReceiver onReceive never fires. Is this true, and if so is there any way around this?Wendiwendie
But why is the default needed?Hosbein
This stuff has nothing to do with Boot Receiver so you can remove it: <category android:name="android.intent.category.DEFAULT"/> and android:enabled="true" android:exported="true" They aren't neededCounterproposal
P
2

was struggling with the same problem, the reason is you are using Log.d to track you application in logcat, unfortunately when you restart your phone the application is receiving the BOOT_Complete but you can't see it because it's not logging to logcat.

try making a Toast with some text instead of Log.d to make sure if BOOT_COMPLETED is or is not received.

hope this Help.

Potty answered 21/6, 2013 at 5:41 Comment(1)
The Toast calls are not displayed either.Bayne
F
2

Heres a C# version if you guys want it. My tests show that it works pretty much flawlessly and the startup is quite fast. Though do note that adding it both in C# and in AndroidManifest.xml breaks it(for me at least).

I have also added some nice and useful examples that I wished I had found out from someone instead of learning it myself when reading through the documentaries and such.

[BroadcastReceiver(Enabled = true, Exported = true, DirectBootAware = true, Name = "com.nevaran.startup.StartUpBootReceiver")]
[IntentFilter(new string[] {
    Intent.ActionBootCompleted
    , Intent.ActionLockedBootCompleted
    , Intent.ActionMyPackageReplaced
    , Intent.ActionUserInitialize
    , "android.intent.action.QUICKBOOT_POWERON"
    , "com.htc.intent.action.QUICKBOOT_POWERON"
})]
public class BootReceiver : BroadcastReceiver
{
    public override void OnReceive(Context context, Intent intent)
    {
         if(    intent.Action.Equals(Intent.ActionBootCompleted)
             || intent.Action.Equals(Intent.ActionLockedBootCompleted)
             || intent.Action.Equals(Intent.ActionUserInitialize)
             || intent.Action.Equals("android.intent.action.QUICKBOOT_POWERON")
             || intent.Action.Equals("com.htc.intent.action.QUICKBOOT_POWERON")
           )
        {
            //run code here only if its started by the chosen actions
        }
        //some code that doesnt care about which action is triggered by
    }
}
Firooc answered 23/7, 2018 at 11:58 Comment(0)
C
0

To resolve this problem, you can use firebaseJobDispatcher to invoke automatically , firebaseJobDispatcher will have code to reactive your services, yes after a certain time services may stopped by OS, but your firebaseJobDispatcher will reactivate your services again. FirebaseJobDispatcher has lots of properties from where you can define the scope of this;

how it works, for more detail https://github.com/firebase/firebase-jobdispatcher-android

Clarissaclarisse answered 12/10, 2018 at 9:13 Comment(1)
firebaseJobDispatcher needs to be created programmatically. It can't be started automatically thus we need to listen to BOOT_COMPLETED event.Ward
K
0

Adding the following seemed to work for me along with the BOOT_COMPLETED intent action

        <action android:name="android.intent.action.QUICKBOOT_POWERON" />
Knoll answered 28/1, 2021 at 8:50 Comment(0)
M
-2

If you want to know the actual reason behind why BOOT_COMPLETE is not working or not receiving. I will suggest you to go to the OFFICIAL Android develop site. They have explained with exact solution.

Android developer - BOOT_COMPLETE

Magnanimous answered 30/8, 2017 at 16:47 Comment(0)
B
-3

Basically you need android:enabled="true" android:exported="true" flags in manifest to receive the broadcast.

<receiver android:name=".bootReceiver" android:enabled="true" android:exported="true">
        <intent-filter>
            <action android:name="android.intent.action.BOOT_COMPLETED" />
            <category android:name="android.intent.category.DEFAULT"/>
        </intent-filter>
    </receiver>
Blotchy answered 22/1, 2018 at 20:45 Comment(3)
This stuff has nothing to do with Boot Receiver so you can remove it: <category android:name="android.intent.category.DEFAULT"/> and android:enabled="true" android:exported="true" They aren't neededCounterproposal
@Counterproposal can you explain why there is no need in category.DEFAULT?Butterfly
@JohnnyFive because it works without and you can check some examples on android.com site, it's not neededCounterproposal

© 2022 - 2024 — McMap. All rights reserved.