Search code examples
javaandroidbroadcastreceiverandroid-servicelocalbroadcastmanager

LocalBroadcastManager is now deprecated, how to send data from service to activity?


I have a service that needs to notify the main activity. I use LocalBroadcastManager, and it works fine, but LocalBroadcastManager has been deprecated.

This is my actual code in the service:

public void onTokenRefresh() {
      
    /* build the intent */
    Intent intent = new Intent(ACTION_TOKENREFRESHED);
    intent.putExtra("token", "xxx");
    
    /* send the data to registered receivers */
    try{
      LocalBroadcastManager.getInstance(this).sendBroadcast(intent);
    } catch (Throwable e){
      //no exception handling
    }  
  
  }

In the main activity, I get informed of the notification like this :

context.registerReceiver(broadcastReceiver, intentFilter);

What can I use now to remove the deprecated warning? All examples I found regarding sending data from service to activity use LocalBroadcastManager. Can someone give me a workable model for migrating my existing code?

NOTE

In my example, The onTokenRefresh is called from inside a background thread. That is very important because it means I can simultaneously receive several onTokenRefresh, and I must forward all these tokens to the activity. Most of the offered solutions use live data but make a declaration like :

public static final MutableLiveData<String> tokenLiveData = new MutableLiveData<>();

Background Thread1:
tokenLiveData.postValue(Token1);

Background Thread2 (at same time):
tokenLiveData.postValue(Token2);

Will forward ALL tokens received simultaneously to the main activity that observes the tokenLiveData? Will the main activity always receive for sure token1 and token2?


Solution

  • Make a service class and define a LiveData to replace the LocalBroadcastManager responsibility like so:

    //This service sends an example token ten times to its observers
    public class MyService extends Service {
        //Define a LiveData to observe in activity
        public static final MutableLiveData<String> tokenLiveData = new MutableLiveData<>();
    
        @Override
        public IBinder onBind(Intent intent) {
            return null;
        }
    
        @Override
        public int onStartCommand(Intent intent, int flags, int startId) {
            //You need a separate thread if you don not use IntentService
    
            Thread thread1 = new Thread() {
                public void run() {
                    for (int i = 0; i < 10; i++) {
                        //send random strings az an example token ten times.
                        //You can remove this loop and replace it with your logic
                        String token1 = UUID.randomUUID().toString();
                        new Handler(Looper.getMainLooper()).post(() -> sendTokenToObserver("Thread1: " + token1));
    
                    }
                }
            };
            thread1.start();
    
            Thread thread2 = new Thread() {
                public void run() {
                    for (int i = 0; i < 10; i++) {
                        String token2 = UUID.randomUUID().toString();
                        new Handler(Looper.getMainLooper()).post(() -> sendTokenToObserver("Thread2: " + token2));
                    }
                }
            };
            thread2.start();
            return START_STICKY;
        }
    
        //Post token to observers
        public void sendTokenToObserver(String token) {
            tokenLiveData.setValue(token);
    
        }
    }
    

    Then start the service in the activity and observe the LiveData like below:

    public class MainActivity extends AppCompatActivity {
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
    
            //You can observe the emitted token here and do what you want(Show in view or notification). 
            //I've just logged it to the console.
            startService(new Intent(this,MyService.class));
            MyService.tokenLiveData.observe(this, token -> Log.d("token", token));
        }
    }
    

    You can also start the service from another activity and observe it in the MainActivity;