479

How to use/locate LocalBroadcastManager as described in google docs and Service broadcast doc?

I tried to google it, but there is no code available to start with?

The documents say that I should use it if I want to do broadcast internally with in my app's process but I don't know where to look for this.

Any help/comment?

Update: I know how to use Broadcasts but don't know how to get LocalBroadcastManager available in my project.

ROMANIA_engineer
  • 54,432
  • 29
  • 203
  • 199
waqaslam
  • 67,549
  • 16
  • 165
  • 178
  • Waqas, have you registered the receiver in manifest. If yes, please let me know how? – Mudassir Apr 03 '12 at 08:44
  • 2
    I dont think you need to register receiver for such broadcasts in manifest, because if you do, then that receiver will also listen for global broadcasts. – waqaslam Apr 03 '12 at 08:51
  • 3
    True. Then this means, I have to do it in code as given in the answer below; `LocalBroadcastManager.getInstance(this).registerReceiver(mMessageReceiver, new IntentFilter("custom-event-name"));` – Mudassir Apr 03 '12 at 08:54
  • 2
    `LocalBroadcastManager` has been deprecated. I replaced mine with the EventBus library which is much nicer, imo. – Kris B Jan 14 '20 at 04:35

13 Answers13

887

I'll answer this anyway. Just in case someone needs it.

ReceiverActivity.java

An activity that watches for notifications for the event named "custom-event-name".

@Override
public void onCreate(Bundle savedInstanceState) {

  ...

  // Register to receive messages.
  // We are registering an observer (mMessageReceiver) to receive Intents
  // with actions named "custom-event-name".
  LocalBroadcastManager.getInstance(this).registerReceiver(mMessageReceiver,
      new IntentFilter("custom-event-name"));
}

// Our handler for received Intents. This will be called whenever an Intent
// with an action named "custom-event-name" is broadcasted.
private BroadcastReceiver mMessageReceiver = new BroadcastReceiver() {
  @Override
  public void onReceive(Context context, Intent intent) {
    // Get extra data included in the Intent
    String message = intent.getStringExtra("message");
    Log.d("receiver", "Got message: " + message);
  }
};

@Override
protected void onDestroy() {
  // Unregister since the activity is about to be closed.
  LocalBroadcastManager.getInstance(this).unregisterReceiver(mMessageReceiver);
  super.onDestroy();
}

SenderActivity.java

The second activity that sends/broadcasts notifications.

@Override
public void onCreate(Bundle savedInstanceState) {

  ...

  // Every time a button is clicked, we want to broadcast a notification.
  findViewById(R.id.button_send).setOnClickListener(new View.OnClickListener() {
    @Override
    public void onClick(View v) {
      sendMessage();
    }
  });
}

// Send an Intent with an action named "custom-event-name". The Intent sent should 
// be received by the ReceiverActivity.
private void sendMessage() {
  Log.d("sender", "Broadcasting message");
  Intent intent = new Intent("custom-event-name");
  // You can also include some extra data.
  intent.putExtra("message", "This is my message!");
  LocalBroadcastManager.getInstance(this).sendBroadcast(intent);
}

With the code above, every time the button R.id.button_send is clicked, an Intent is broadcasted and is received by mMessageReceiver in ReceiverActivity.

The debug output should look like this:

01-16 10:35:42.413: D/sender(356): Broadcasting message
01-16 10:35:42.421: D/receiver(356): Got message: This is my message! 
Shiki
  • 16,688
  • 7
  • 32
  • 33
  • 7
    thanks. got it working already. but the problem i faced was to get hold on LocalBroadcastManager class. Since its a support package class, so i wasn't able to use it in my ordinary package till i added Compatibility Library from Android Tools. Once its added, all went just fine. anyway, thanks for the answer – waqaslam Jan 16 '12 at 07:29
  • 199
    please note that **`onDestroy()` is not guaranteed to be called!!!** You must use `onPause()` (because only `onPause()` is guaranteed) and `onResume()` (because it's the match for `onPause()`) – 18446744073709551615 Apr 26 '12 at 13:58
  • 1
    @18446744073709551615 Isnt it possible to register on `onCreate()` and unregister on both `onDestroy()` and on `onSaveInstanceState()` ? – AsafK Dec 08 '13 at 13:41
  • 1
    onCreate() is not called e.g. when the user goes to the settings page and returns back. But if the user changes the screen orientation while on the settings page, onCreate _is_ called. As to unregistering in onSaveInstanceState()... OMG... This is not the intended use, which means that the Google guys may change something and break your code. – 18446744073709551615 Dec 09 '13 at 06:49
  • 5
    Folks, note what the google docs now say about an Activity after onPause(): Killable = Pre-HONEYCOMB _Starting with Honeycomb, an application is not in the killable state until its onStop() has returned._ – 18446744073709551615 Dec 09 '13 at 06:53
  • 63
    `onDestroy()` is no problem. The case in which it is not called is when the app is killed, and it does not matter if you don't unregister in that case since not even the list of registered receivers survives that. – zapl Mar 01 '14 at 18:44
  • 1
    This is extremely useful! By the way, it's important to note that the line " LocalBroadcastManager.getInstance(this).sendBroadcast(intent);" is important, because the LBM's context is what receives broadcasts from the LBM. If you use other context, you will not receive message. – EpicPandaForce Jun 03 '14 at 09:15
  • 2
    of course using LocalBroadcastManager to communication between activities is a bad idea ... best pratices tells that recivers should be unregstered in onPause, because any interaction with UI after this point makes no sens ... also storing Activity references in some static class longer then it is visible is bad practice (weak references is ok but LocalBroadcastManager internally is not using em) ... Conclusion: **You should never use LocalBroadcastManager to comunication between Activities** – Selvin Jul 23 '15 at 12:35
  • 1
    of course it works because simple `Log` statement in receiver ... [here](https://gist.github.com/SelvinPL/620e6c05cd59dc7c16c2) we have something common(on button click in `Sender` we add some data to `Adapter` in `Receiver` = UI interaction) the code will end with nice `java.lang.UnsupportedOperationException` ... @18446744073709551615 got right ... we should unregister receiver in `onPause` ... but then we will not get intent :) ... **only people who do not understand activities's lificycle upvote this question** ... – Selvin Jul 23 '15 at 13:51
  • 4
    @Selvin I hope you're aware that you can make the BroadcastReciever weakly referenced to the receiving activity and make it unregister itself if it's been orphaned. You don't need to unregister it in onPause, onDestroy is fine as long as you don't use your BroadcastReceiver to keep your activity in RAM. Your example shows a bad practice with an inner class leaking it's outer class, it's not unique to BroadcastReceiver and is something programmers always have to guard against. As for modifying the GUI, you can store a state for when the activity is resumed, you don't have to modify the GUI. – JohanShogun Jul 26 '15 at 12:25
  • I also want to point out that I don't specifically advocate it's usage for communication between activities (although there are exceptions to every rule) but I do feel like I have to point out that you're example is only a problem because you rely on poor programming practices in it. – JohanShogun Jul 26 '15 at 12:30
  • @18446744073709551615 If you use `onPause()` to unregister the receiver then the activity can't receive broadcasts in the background right? Doesn't that kind of defeat the purpose? Am I missing something here? Genuinely asking. – Jack May 25 '16 at 15:20
  • @Jackyesterday The shown code is a toy. It defines an activity that can receive broadcasts while it is on screen. The broadcast receiver in ReceiverActivity has access to the activity because it is an inner class. A real broadcast receiver uses its _context_ parameter as the only available Context. A real broadcast receiver can either notify a service via a service intent, or start an activity via an activity intent. (continued below) – 18446744073709551615 May 27 '16 at 08:05
  • @Jackyesterday (continued) (I mean that the class specified in the intent may specify a service or an activity, and these two cases are very different because an application that uses services is very much different from an application that uses only activities.) So in real code there would be cumbersome packing/unpacking data to/from an Intent. (Just think: in 1960-es our ancestors believed that a name and a list of parameters is just enough.) – 18446744073709551615 May 27 '16 at 08:06
  • If you need to change views or replace fragments, you need to register it in onResume() and unregister in onPause(), otherwise it can throw an “IllegalStateException: Can not perform this action after onSaveInstanceState”. This will also cut down on unnecessary system overhead. – heloisasim Aug 21 '16 at 19:25
134

I'd rather like to answer comprehensively.

  1. LocalbroadcastManager included in android 3.0 and above so you have to use support library v4 for early releases. see instructions here

  2. Create a broadcast receiver:

    private BroadcastReceiver onNotice= new BroadcastReceiver() {
    
        @Override
        public void onReceive(Context context, Intent intent) {
            // intent can contain anydata
            Log.d("sohail","onReceive called");
            tv.setText("Broadcast received !");
    
        }
    };
    
  3. Register your receiver in onResume of activity like:

    protected void onResume() {
            super.onResume();
    
            IntentFilter iff= new IntentFilter(MyIntentService.ACTION);
            LocalBroadcastManager.getInstance(this).registerReceiver(onNotice, iff);
        }
    
    //MyIntentService.ACTION is just a public static string defined in MyIntentService.
    
  4. unRegister receiver in onPause:

    protected void onPause() {
      super.onPause();
      LocalBroadcastManager.getInstance(this).unregisterReceiver(onNotice);
    }
    
  5. Now whenever a localbroadcast is sent from applications' activity or service, onReceive of onNotice will be called :).

Edit: You can read complete tutorial here LocalBroadcastManager: Intra application message passing

Boon
  • 40,656
  • 60
  • 209
  • 315
SohailAziz
  • 8,034
  • 6
  • 41
  • 43
  • 17
    +1. if your Broadcast Receiver is in a fragment, register it using `LocalBroadcastManager.getInstance(getActivity()).registerReceiver(onNotice);` and unregister it using `LocalBroadcastManager.getInstance(getActivity()).unregisterReceiver(onNotice);` – PeteH May 30 '13 at 06:47
  • 3
    Are you sure that LocalBroadcastManager is included in Android 3.0 and up? Can not find it anywhere except support lib – mente Nov 18 '13 at 11:59
  • 5
    strangely, LBM is only included in the support library. – Jeffrey Blattman Dec 04 '13 at 00:57
  • So it is not necessary to include android-support-v4.jar to target 11 and up in order to use LocalBroadcastManager? – IgorGanapolsky Feb 27 '14 at 16:46
  • @PeteH you missed IntentFilter in registereRecevier method. – Sinan Dizdarević Oct 28 '15 at 11:33
  • 1
    super.onPause() should be last statement when overwriting onPause method. Unregister before super.onPause to avoid unpredictable bug – Thupten Nov 23 '16 at 03:57
  • 2
    I believe you may want to move your lifecycle to `onStop` because in Android API 24+ with “Multi-Window/Split-View” (enabled by default on API 26+ affaicr), the activity not being interacted with is in the paused state. Source: https://developer.android.com/guide/topics/ui/multi-window.html#lifecycle – Martin Marconcini Nov 17 '17 at 21:30
  • @Martin Marconcini does your recommendation to use onStop() to unregister the LBM imply that onStart() should be used to register the LBM? – AJW Mar 29 '18 at 01:20
  • 1
    @AJW preferably, yes. The more you mirror these calls, the easier it is to understand their lifecycle. – Martin Marconcini Mar 29 '18 at 01:21
  • @Martin Marconcini Also, should onStop() and onStart() only be used for API 24+ and use onPause() and onResume() be used for API < 24? – AJW Mar 29 '18 at 01:23
  • 2
    @AJW I wouldn’t. There’s really no reason to do that (that I can think of). It really depends on your use case. For the most part, onStop/Start tends to be better given that a Dialog will trigger onPause and it may not be desired to “unsubscribe” to things (only to resubscribe moments later) because a Dialog appeared. Or in some cases yes, so… ensure that’s what you want ;) – Martin Marconcini Mar 29 '18 at 01:25
47

On Receiving end:

  • First register LocalBroadcast Receiver
  • Then handle incoming intent data in onReceive.

      @Override
      protected void onCreate(Bundle savedInstanceState) {
          super.onCreate(savedInstanceState);
    
          LocalBroadcastManager lbm = LocalBroadcastManager.getInstance(this);
          lbm.registerReceiver(receiver, new IntentFilter("filter_string"));
      }
    
      public BroadcastReceiver receiver = new BroadcastReceiver() {
          @Override
          public void onReceive(Context context, Intent intent) {
              if (intent != null) {
                  String str = intent.getStringExtra("key");
                  // get all your data from intent and do what you want 
              }
          }
      };
    

On Sending End:

   Intent intent = new Intent("filter_string");
   intent.putExtra("key", "My Data");
   // put your all data using put extra 

   LocalBroadcastManager.getInstance(this).sendBroadcast(intent);
Philipp Jahoda
  • 50,880
  • 24
  • 180
  • 187
waqas ali
  • 1,238
  • 1
  • 11
  • 17
27

In Eclipse, eventually I had to add Compatibility/Support Library by right-clicking on my project and selecting:

Android Tools -> Add Support Library

Once it was added, then I was able to use LocalBroadcastManager class in my code.


Android Compatibility Library

waqaslam
  • 67,549
  • 16
  • 165
  • 178
21

localbroadcastmanager is deprecated, use implementations of the observable pattern instead.

androidx.localbroadcastmanager is being deprecated in version 1.1.0

Reason

LocalBroadcastManager is an application-wide event bus and embraces layer violations in your app; any component may listen to events from any other component. It inherits unnecessary use-case limitations of system BroadcastManager; developers have to use Intent even though objects live in only one process and never leave it. For this same reason, it doesn’t follow feature-wise BroadcastManager .

These add up to a confusing developer experience.

Replacement

You can replace usage of LocalBroadcastManager with other implementations of the observable pattern. Depending on your use case, suitable options may be LiveData or reactive streams.

Advantage of LiveData

You can extend a LiveData object using the singleton pattern to wrap system services so that they can be shared in your app. The LiveData object connects to the system service once, and then any observer that needs the resource can just watch the LiveData object.

 public class MyFragment extends Fragment {
    @Override
    public void onActivityCreated(Bundle savedInstanceState) {
        super.onActivityCreated(savedInstanceState);
        LiveData<BigDecimal> myPriceListener = ...;
        myPriceListener.observe(this, price -> {
            // Update the UI.
        });
    }
}

The observe() method passes the fragment, which is an instance of LifecycleOwner, as the first argument. Doing so denotes that this observer is bound to the Lifecycle object associated with the owner, meaning:

  • If the Lifecycle object is not in an active state, then the observer isn't called even if the value changes.

  • After the Lifecycle object is destroyed, the observer is automatically removed

The fact that LiveData objects are lifecycle-aware means that you can share them between multiple activities, fragments, and services.

Darish
  • 11,032
  • 5
  • 50
  • 70
  • 1
    you are right about leaking contexts to whole world, but I would like to know what would be a suitable replacement when I want to communicate from a foreground service that is running even without an activity, but when activity comes in, they need to communicate? – ateebahmed Mar 28 '19 at 15:29
  • 3
    Create a singleton class with a LiveData object and post your data from the service. Once the activity launches, activity can easily observe the LiveData without any harm. eg: MyServiceData.getInstance().getMyData().observe ... – Darish Mar 29 '19 at 06:48
  • 4
    I will miss LocalBroadcastManager. If it was confusing to developers at Google, perhaps they need to stop over-engineering things? – Andrei Drynov Oct 31 '19 at 23:22
  • @Darish Would this singleton class be equivalent to storing it in the Application object? Why is this kind of global state in these cases not considered bad practice? – xuiqzy May 23 '20 at 21:14
14

How to change your global broadcast to LocalBroadcast

1) Create Instance

LocalBroadcastManager localBroadcastManager = LocalBroadcastManager.getInstance(this);

2) For registering BroadcastReceiver

Replace

registerReceiver(new YourReceiver(),new IntentFilter("YourAction"));

With

localBroadcastManager.registerReceiver(new YourReceiver(),new IntentFilter("YourAction"));

3) For sending broadcast message

Replace

sendBroadcast(intent);

With

localBroadcastManager.sendBroadcast(intent);

4) For unregistering broadcast message

Replace

unregisterReceiver(mybroadcast);

With

localBroadcastManager.unregisterReceiver(mybroadcast);
Rohit Singh
  • 16,950
  • 7
  • 90
  • 88
  • How can I register multiple IntentFilter?? – Parikshit Chalke Nov 16 '18 at 11:45
  • @ParikshitChalke: [link](https://github.com/carrot-garden/android_maven-android-plugin-samples/blob/master/support4demos/src/com/example/android/supportv4/content/LocalServiceBroadcaster.java) – XMAN Dec 08 '18 at 07:33
6

When you'll play enough with LocalBroadcastReceiver I'll suggest you to give Green Robot's EventBus a try - you will definitely realize the difference and usefulness of it compared to LBR. Less code, customizable about receiver's thread (UI/Bg), checking receivers availability, sticky events, events could be used as data delivery etc.

Stan
  • 6,511
  • 8
  • 55
  • 87
5

Kotlin version of using LocalBroadcastManager:

Please check the below code for registering, sending and receiving the broadcast message.

class MainActivity : AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        // register broadcast manager
        val localBroadcastManager = LocalBroadcastManager.getInstance(this)
        localBroadcastManager.registerReceiver(receiver, IntentFilter("your_action"))
    }

    // broadcast receiver
    var receiver: BroadcastReceiver = object : BroadcastReceiver() {
        override fun onReceive(context: Context?, intent: Intent?) {
            if (intent != null) {
                val str = intent.getStringExtra("key")
                
            }
        }
    }

    /**
     * Send broadcast method
     */
    fun sendBroadcast() {
        val intent = Intent("your_action")
        intent.putExtra("key", "Your data")
        LocalBroadcastManager.getInstance(this).sendBroadcast(intent);
    }

    override fun onDestroy() {
        // Unregister broadcast
        LocalBroadcastManager.getInstance(this).unregisterReceiver(receiver)
        super.onDestroy()
    }

}
Shalu T D
  • 3,921
  • 2
  • 26
  • 37
2

An example of an Activity and a Service implementing a LocalBroadcastManager can be found in the developer docs. I personally found it very useful.

EDIT: The link has since then been removed from the site, but the data is the following: https://github.com/carrot-garden/android_maven-android-plugin-samples/blob/master/support4demos/src/com/example/android/supportv4/content/LocalServiceBroadcaster.java

EpicPandaForce
  • 79,669
  • 27
  • 256
  • 428
nindalf
  • 1,058
  • 2
  • 12
  • 15
0
enter code here if (createSuccses){
                        val userDataChange=Intent(BRODCAST_USER_DATA_CHANGE)
                        LocalBroadcastManager.getInstance(this).sendBroadcast(
                            userDataChange
                        )
                        enableSpinner(false)
                        finish()
Seroj Grigoryan
  • 159
  • 1
  • 2
0

By declaring one in your AndroidManifest.xml file with the tag (also called static)

<receiver android:name=".YourBrodcastReceiverClass"  android:exported="true">
<intent-filter>
    <!-- The actions you wish to listen to, below is an example -->
    <action android:name="android.intent.action.BOOT_COMPLETED"/>
</intent-filter>

You will notice that the broadcast receiver declared above has a property of exported=”true”. This attribute tells the receiver that it can receive broadcasts from outside the scope of the application.
2. Or dynamically by registering an instance with registerReceiver (what is known as context registered)

public abstract Intent registerReceiver (BroadcastReceiver receiver, 
            IntentFilter filter);

public void onReceive(Context context, Intent intent) {
//Implement your logic here
}

There are three ways to send broadcasts:
The sendOrderedBroadcast method, makes sure to send broadcasts to only one receiver at a time. Each broadcast can in turn, pass along data to the one following it, or to stop the propagation of the broadcast to the receivers that follow.
The sendBroadcast is similar to the method mentioned above, with one difference. All broadcast receivers receive the message and do not depend on one another.
The LocalBroadcastManager.sendBroadcast method only sends broadcasts to receivers defined inside your application and does not exceed the scope of your application.

matthias_h
  • 11,356
  • 9
  • 22
  • 40
Seroj Grigoryan
  • 159
  • 1
  • 2
0

I am an iOS dev, so I made a solution similar to NotificationCenter:

object NotificationCenter {
    var observers: MutableMap<String, MutableList<NotificationObserver>> = mutableMapOf()

    fun addObserver(observer: NotificationObserver, notificationName: NotificationName) {
        var os = observers[notificationName.value]
        if (os == null) {
            os = mutableListOf<NotificationObserver>()
            observers[notificationName.value] = os
        }
        os.add(observer)
    }

    fun removeObserver(observer: NotificationObserver, notificationName: NotificationName) {
        val os = observers[notificationName.value]
        if (os != null) {
            os.remove(observer)
        }
    }

    fun removeObserver(observer:NotificationObserver) {
        observers.forEach { name, mutableList ->
            if (mutableList.contains(observer)) {
                mutableList.remove(observer)
            }
        }
    }

    fun postNotification(notificationName: NotificationName, obj: Any?) {
        val os = observers[notificationName.value]
        if (os != null) {
            os.forEach {observer ->
                observer.onNotification(notificationName,obj)
            }
        }
    }
}

interface NotificationObserver {
    fun onNotification(name: NotificationName,obj:Any?)
}

enum class NotificationName(val value: String) {
    onPlayerStatReceived("on player stat received"),
    ...
}

Some class that want to observe notification must conform to observer protocol:

class MainActivity : AppCompatActivity(), NotificationObserver {
    override fun onCreate(savedInstanceState: Bundle?) {
        ...
        NotificationCenter.addObserver(this,NotificationName.onPlayerStatReceived)
    }
    override fun onDestroy() {
        ...
        super.onDestroy()
        NotificationCenter.removeObserver(this)
    }

    ...
    override fun onNotification(name: NotificationName, obj: Any?) {
        when (name) {
            NotificationName.onPlayerStatReceived -> {
                Log.d(tag, "onPlayerStatReceived")
            }
            else -> Log.e(tag, "Notification not handled")
        }
    }

Finally, post some notification to observers:

NotificationCenter.postNotification(NotificationName.onPlayerStatReceived,null)
Krešimir Prcela
  • 4,257
  • 33
  • 46
-4

we can also use interface for same as broadcastManger here i am sharing the testd code for broadcastManager but by interface.

first make an interface like:

public interface MyInterface {
     void GetName(String name);
}

2-this is the first class that need implementation

public class First implements MyInterface{

    MyInterface interfc;    
    public static void main(String[] args) {
      First f=new First();      
      Second s=new Second();
      f.initIterface(s);
      f.GetName("Paddy");
  }
  private void initIterface(MyInterface interfc){
    this.interfc=interfc;
  }
  public void GetName(String name) {
    System.out.println("first "+name);
    interfc.GetName(name);  
  }
}

3-here is the the second class that implement the same interface whose method call automatically

public class Second implements MyInterface{
   public void GetName(String name) {
     System.out.println("Second"+name);
   }
}

so by this approach we can use the interface functioning same as broadcastManager.

SHR
  • 7,940
  • 9
  • 38
  • 57