92

I am trying to start up a BroadcastReceiver within a Service. What I am trying to do is have a background running service going that collects incoming text messages, and logs incoming phone calls. I figured the best way to go about this is to have a service running that incorporates a broadcast receiver that can catalog either.

How do i go about doing this? I already have my service up and running.

K Guru
  • 1,292
  • 2
  • 17
  • 36
Utopia025
  • 1,181
  • 3
  • 11
  • 21

2 Answers2

132

as your service is already setup, simply add a broadcast receiver in your service:

private final BroadcastReceiver receiver = new BroadcastReceiver() {
   @Override
   public void onReceive(Context context, Intent intent) {
      String action = intent.getAction();
      if(action.equals("android.provider.Telephony.SMS_RECEIVED")){
        //action for sms received
      }
      else if(action.equals(android.telephony.TelephonyManager.ACTION_PHONE_STATE_CHANGED)){
           //action for phone state changed
      }     
   }
};

in your service's onCreate do this:

IntentFilter filter = new IntentFilter();
filter.addAction("android.provider.Telephony.SMS_RECEIVED");
filter.addAction(android.telephony.TelephonyManager.ACTION_PHONE_STATE_CHANGED);
filter.addAction("your_action_strings"); //further more
filter.addAction("your_action_strings"); //further more

registerReceiver(receiver, filter);

and in your service's onDestroy:

unregisterReceiver(receiver);

and you are good to go to receive broadcast for what ever filters you mention in onCreate. Make sure to add any permission if required. for e.g.

<uses-permission android:name="android.permission.RECEIVE_SMS" />
waqaslam
  • 67,549
  • 16
  • 165
  • 178
  • 1
    Ive noticed I cannot pass data by intent.setData(myUri) while sending sendBroadcas(intent) and braoadcastReceiver doesn't work in that case, is it right? – deadfish Nov 15 '14 at 19:18
  • I am little confuse about the service life-cycle when it has BroadcastReceiver (in my case download BroadcastReceiver) – K Guru Feb 05 '15 at 05:13
  • 2
    @waqaslam Did you set this BroadcastReceiver in your Manifest? – IgorGanapolsky Feb 05 '15 at 14:40
  • 3
    @IgorGanapolsky No, you don't need to register such receivers in manifest. – waqaslam Feb 05 '15 at 20:58
  • @waqaslam Your code uses an IntentFilter in the Service's onCreate() and registers the receiver. Further below though you mention filtering in "onStartCommand" Did you mean to say in "onCreate" or am I missing something? – AJW May 24 '18 at 23:25
  • @AJW Thanks for pointing out. It was a mistake which is fixed now :) – waqaslam May 25 '18 at 01:39
  • @waqaslam I have a similar question listed here: https://stackoverflow.com/questions/50520219/android-how-to-fix-broadcastreceiver-in-jobintentservice Any thoughts on how to fix? – AJW May 25 '18 at 03:59
  • Hey i wanna ask if i define BroadcastReceiver in Service not in mainactivity, will it will consume more battery , because there are two process are running for single app.. Or it will be ok my app will consume same amount of battery and ram in a device.. –  Nov 29 '19 at 06:07
  • 2
    @SayyedRizwan Your service and BroadcastReceiver will run under same process and most probably same thread (unless you create a new one). Battery consumption depends on how you have defined your thread (background/Foreground) and the amount of broadcasts coming in. – waqaslam Nov 29 '19 at 06:46
  • @waqaslam can you solve this question? https://stackoverflow.com/q/63350856/5359340 – FGH Aug 11 '20 at 06:47
  • I am not receiving any(!) intents in my broacast receiver. What could be the reason for this? – hugo der hungrige Dec 15 '21 at 18:03
27

The better pattern is to create a standalone BroadcastReceiver. This insures that your app can respond to the broadcast, whether or not the Service is running. In fact, using this pattern may remove the need for a constant-running Service altogether.

Register the BroadcastReceiver in your Manifest, and create a separate class/file for it.

Eg:

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

When the receiver runs, you simply pass an Intent (Bundle) to the Service, and respond to it in onStartCommand().

Eg:

public class FooReceiver extends BroadcastReceiver {
    @Override
    public void onReceive(Context context, Intent intent) {
        // do your work quickly!
        // then call context.startService();
    }   
}
Paul Burke
  • 25,496
  • 9
  • 66
  • 62
  • 7
    I want the broadcast to be within the life cycle of the service, so that the app is only querying messages/phone calls according to the service time line. Does this method enable that? it looks like you have set it up so the reception of the broadcast sets off the service. – Utopia025 Feb 05 '12 at 03:54
  • This implementation would start the `Service` if it was not already running, or pass a new `Intent` if it is (for retrieval in `onStartCommand`). If you only want it to run when the `Service` is live, you could programmatically enable/disable the `Receiver` component through the `PackageManager`'s `setComponentEnabledSetting()`. – Paul Burke Feb 05 '12 at 04:24
  • 4
    Waqas's answer may your best option, if you only want the `Receiver` alive when the `Service` is running. – Paul Burke Feb 05 '12 at 04:27
  • 3
    If you don't have an Activity, it won't work for API 3.1 and higher: http://ashimita.blogspot.com.tr/2012/04/broadcast-receiver-change-in-flow-since.html – elif Sep 24 '14 at 08:03
  • 2
    As of Android 3.1 the Android system excludes all receiver from receiving intents by default if the corresponding application has never been started by the user or if the user explicitly stopped the application via the Android menu. http://www.vogella.com/tutorials/AndroidBroadcastReceiver/article.html – Juraj Petrik Aug 14 '15 at 14:13
  • The problem is when you kill the application broadcast receiver will auto stop and app will not work after this. – pavel Jul 28 '18 at 08:31