49

My app uses a BroadcastReceiver to get sms in this way:

SmsBR.java

public class SmsBR extends BroadcastReceiver {

    @Override
    public void onReceive(Context context, Intent intent) {
        Bundle bundle = intent.getExtras();
        if (bundle != null) {
            Object[] pdus = (Object[])bundle.get("pdus");
            final SmsMessage[] messages = new SmsMessage[pdus.length];

            for (int i = 0; i < pdus.length; i++) {
                messages[i] = SmsMessage.createFromPdu((byte[])pdus[i]);
            }
            if (messages.length > 0)
                //doSomething();
            }
        }
    }
}

Manifest.xml

<application android:icon="@drawable/icon" android:label="@string/app_name">
    <activity android:name=".Activity" 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=".SmsBR">
        <intent-filter>
            <action android:name="android.provider.Telephony.SMS_RECEIVED"></action>
        </intent-filter>
    </receiver>
</application>    

In this way SmsBR is always ON. I want to register it when a service starts (onCreate()) and unregister it when the service is destroyed (onDestroy()). How can I do this?

Melquiades
  • 8,496
  • 1
  • 31
  • 46
supergiox
  • 1,586
  • 7
  • 19
  • 27

3 Answers3

119

Edit:

For an Activity:

In order to register your broadcast receiver from within your app, first, remove the <receiver> tag from your AndroidManifest.xml file. Then, call registerReceiver(BroadcastReceiver receiver, IntentFilter filter) in your onResume(). Use unregisterReceiver(BroadcastReceiver receiver) in your onPause() to unregister the Broadcast receiver.

For a Service:

Remove the receiver tag from the manifest file. You can then register your Broadcast receiver with the same method in the onCreate() and unregister in the onDestroy().

EDIT: Sample Code:

public class MyActivity extends Activity {
  private final BroadcastReceiver mybroadcast = new SmsBR();

  public void onResume() {
    super.onResume();

    IntentFilter filter = new IntentFilter();
    filter.addAction("android.provider.Telephony.SMS_RECEIVED");
    registerReceiver(mybroadcast, filter);
  }

  public void onPause() {
    super.onPause();

    unregisterReceiver(mybroadcast);
  }
}
WindsurferOak
  • 4,861
  • 1
  • 31
  • 36
  • So I've to use an instance of `SmsBR` and (un)register it? Which IntentFilter should I use for received sms? – supergiox Sep 16 '11 at 01:05
  • Yep, that's right. Use an instance of SmsBR, preferably make it final, and register/unregister it. I've added the sample code for you. Regarding the IntentFilter, use pretty much the same filter that you had in your manifest file. – WindsurferOak Sep 16 '11 at 01:17
  • @WindsurferOak Hi, found this post very helpful. I too have a class which extends broadcast receiver and need to unregister it. I am getting an error with " registerReceiver(mybroadcast, filter);" The method is undefined for the type CLASS_NAME" Can you advise? – GrumP Aug 13 '12 at 14:14
  • 1
    Is it necessary to unregister the broadcast receiver in android? – Deepak Sharma Jul 30 '13 at 10:24
  • Yes it is necessary to unregister it. Also, great example! One small addition the calls to super.onResume() and super.onPause() respectively are missing. – netcyrax Jan 30 '14 at 07:02
  • 1
    What would happen if I do not unregister the broadcast receiver? Would it remain active even after the phone reboots ? – Jaydev Nov 15 '16 at 05:25
26

onDestroy() is not guaranteed to be called. When you start Activity from Activty, onPause() and onStop() method called instead of onDestroy().

onDestroy() calls when you hit back button or call finish() method.

Hence, broadcast receiver should be registered in onStart() or onResume(), and unregister receiver in onPause() or onStop().

If you unregister receiver in onDestroy() method, it might cause a memory leak in App.

vivek
  • 1,034
  • 11
  • 14
  • 5
    onStop is not guaranteed to be called either, therefore you should deregistert in onPause. – barq Jun 14 '17 at 06:00
  • @barq not true. On API 11+ onStop is guaranteed to be called. https://stackoverflow.com/questions/29395169/is-activity-onstop-guaranteed-to-be-called-api-11 – Michał Dobi Dobrzański Nov 21 '19 at 14:26
0

First remove receiver tag from manifest, then: for service :

@Override
public void onCreate() {


    myReceiver = new SmsBR();
    IntentFilter filter = new IntentFilter();
    filter.addAction("android.intent.action.SMS_RECEIVED");// add any actions you want
    registerReceiver(myReceiver , filter);

 }

@Override
public void onDestroy() {
    super.onDestroy();
    if (myReceiver != null)
        unregisterReceiver(myReceiver);
}

for Activity:

public class MyActivity extends Activity {
  private final BroadcastReceiver mybroadcast = new SmsBR();

  public void onResume() {
    super.onResume();

    IntentFilter filter = new IntentFilter();
    filter.addAction("android.provider.Telephony.SMS_RECEIVED");
    registerReceiver(mybroadcast, filter);
  }

  public void onPause() {
    super.onPause();

    if (mybroadcast!= null)
       unregisterReceiver(mybroadcast);
  }
}
Maher
  • 342
  • 3
  • 10