Android BroadcastReceiver on startup - keep running when Activity is in Background
Asked Answered
S

6

59

I'm monitoring incoming SMSs.

My app is working perfectly with a BroadcastReceiver. However it is working from an Activity and would like to keep the BroadcastReceiver running all the time (and not just when my Activity is running).

How can I achieve this? I've looked through the lifecycle of the BroadcastReceiver but all that is mentioned in the documentation is that the lifecycle is limited to the onReceive method, not the lifecycle of keeping the BroadcastReceiver checking for incoming SMS.

How can I make this persistent?

Thanks

Sudiesudnor answered 13/3, 2011 at 14:56 Comment(0)
H
162

You need to define a receiver in manifest with action name android.intent.action.BOOT_COMPLETED.

<!-- Start the Service if applicable on boot -->
<receiver android:name="com.prac.test.ServiceStarter">
    <intent-filter>
        <action android:name="android.intent.action.BOOT_COMPLETED"/>
    </intent-filter>
</receiver>

Make sure also to include the completed boot permission.

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

Use Service for this to make anything persist. And use receivers to receive Boot Up events to restart the service again if system boots..

Code for Starting Service on boot up. Make Service do your work of checking sms or whatever you want. You need to do your work in MyPersistingService define it your self.

import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.util.Log;

public class ServiceStarter extends BroadcastReceiver {

    @Override
    public void onReceive(Context context, Intent intent) {
        Intent i = new Intent("com.prac.test.MyPersistingService");
        i.setClass(context, MyPersistingService.class);
        context.startService(i);
    }
}
Hibernaculum answered 13/3, 2011 at 14:59 Comment(8)
You might also want to make sure that you have the RECEIVE_BOOT_COMPLETED permission defined in your app manifest file for this to work.Caprice
Does this work if the application context is extending another one from a project library?Dilks
How is this a Service?Southport
its a broadcast that keeps your service running after device boot.Hibernaculum
It is also important to note that you will only receieve the boot complete broadcast if your app is installed to internal storage, and will not get the broadcast if allowed on external storage. If it is vital for your app to get the boot received broadcast, you might want to consider allowing internal installation only. developer.android.com/guide/topics/data/install-location.htmlTerrigenous
For some reason it doesn't work for me...What could be happening?Ader
@RuchirBaronia well you can check @Terrigenous answer. Please check if your android:installLocation is set to external on <manifest> tag.Pare
is it good to start service from broadcast receiver in MVP design architecture?Garey
L
8

Service or Boot Completed is not mandatory

In fact, you don't need to implement a Service or register to android.intent.action.BOOT_COMPLETED

Some examples shows how to register/unregister a BroadcastReceiver when activity is created and destroyed. However, this is useful for intents that you expect only when app is opened (for internal communication between Service/Activity for example).

However, in case of a SMS, you want to listen to the intent all the time (and not only when you app is opened).

There's another way

You can create a class which extends BroadcastReceiver and register to desired intents via AndroidManifest.xml. This way, the BroadcastReceiver will be indepedent from your Activity (and will not depend from Activity's Life Cycle)

This way, your BroadcastReceiver will be notified automatically by Android as soon as an SMS arrive even if your app is closed.

AndroidManifest.xml

<?xml version="1.0" encoding="utf-8"?>
<manifest>
    ...
    <uses-permission android:name="android.permission.READ_SMS"/>
    <uses-permission android:name="android.permission.RECEIVE_SMS"/>

    <application>
        ....
        <receiver android:name=".MyCustomBroadcastReceiver">
            <intent-filter>
                <action android:name="android.provider.Telephony.SMS_RECEIVED" />
            </intent-filter>
        </receiver>
    </application>
</manifest>

MyCustomBroadcastReceiver.java

public class MyCustomBroadcastReceiver extends BroadcastReceiver {

    @Override
    public void onReceive(Context context, Intent intent) {
        if(intent != null) {
            String action = intent.getAction();
            if(action != null) {
                if(action.equals("android.provider.Telephony.SMS_RECEIVED")) {
                    // DO YOUR STUFF
                } else if (action.equals("ANOTHER ACTION")) {
                    // DO ANOTHER STUFF
                }
            }
        }
    }
}

Notes

You can add others intent-filters to AndroidManifest and handle all of them in same BroadcastReceiver.

Start a Service only if you will perform a long task. You just need to display a notification or update some database, just use the code above.

Lael answered 14/7, 2016 at 4:0 Comment(3)
If the app crashes too often or the user force-stops the app, it won't be relaunched on broadcast eventsBurkhart
@W0rmH0le what happenes when he restarts the phone without launching the activity or the app? Does not he need a boot completed receiver ?Flexor
@Flexor Since desired intents are registered in AndroidManifest, android will invoke your broadcast receiver class even if you didn't open your app yet. You need boot_completed intent only if you plan to take an action as soon as device boot... But that is not the case.. he will take actions only when SMS arrives..Lael
T
2

Add Broadcast Reciever in manifest:

  <receiver android:name=".BootReceiver">
        <intent-filter>
            <action android:name="android.intent.action.BOOT_COMPLETED"/>
            <category android:name="android.intent.category.DEFAULT"/>
        </intent-filter>
    </receiver>

Create Class BootReciever.java

public class BootReceiver extends BroadcastReceiver {
   @Override
   public void onReceive(Context context, Intent intent) {
       if(intent.getAction().equals(Intent.ACTION_BOOT_COMPLETED)){

           // +++ Do Operation Here +++

       }
   }
}
Tightrope answered 17/1, 2020 at 20:26 Comment(0)
B
1

Beside @Javanator answer I would like to include a case for Android version of (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) In my case this is working for Android SDK 29 (10)

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
      context.startForegroundService(new Intent(context,FloatingWindow.class));
} else {
      context.startService(new Intent(context, FloatingWindow.class));
  }
Beside answered 25/9, 2019 at 18:46 Comment(1)
Or you could just use ContextCompat.startForegroundService(context, new Intent(...)).Jezreel
Z
0

use this code and also mention the broadcast in Manifest also:

public class BootService extends BroadcastReceiver {
    @Override
    public void onReceive(Context context, Intent intent) {
        if(intent.getAction().equals(Intent.ACTION_BOOT_COMPLETED)){
            Toast.makeText(context, "Boot Completed", Toast.LENGTH_SHORT).show();
            //write code here
        }
    }
}
Zulmazulu answered 25/10, 2019 at 9:2 Comment(0)
J
0

I just want to mention that in case of some Chinese phone brands (e.g. MI), you need to go to Settings and give autostart permission to your app.

Otherwise the battery optimisation feature will kill your service in background and broadcast receiver will not work.

So you can redirect your user to Settings and ask them to give that permission.

Joejoeann answered 23/2, 2022 at 11:20 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.