Android equivalent of NSNotification? - android

What's the equivalent of an NSNotification in Android?
I need to be able to send and receive the notification from arbitrary classes (not necessarily activities).

This pattern is called EventBus, and theres some libraries for that.

You can use LocalBroadcastManager or can implement Observer interface to accomplish your task as iOS NSNotification.

Related

How can I transfer data between two SDK's in the same app in Android?

Since localBroadcastManager is deprecated what can I use instead?
I couldn't find something general that I could register to and use the filter as used to with IntentFilter.
I read about SharedFlow and don't think it suits my needs.
I need a way to listen to events but I can know the Coroutine class created for that for example.

Using Kotlin Coroutines to replace LocalBroadcastManager for Firebase messaging

When using Firebase Cloud Messaging on Android, it is often desirable to notify the current Activity of an incoming push notification. One of the recommended ways to do this has been to use LocalBroadcastManager to send an Intent from the FirebaseMessagingService implementation to the Activity (StackOverflow example answer).
However, as of version 1.1.0-alpha01 (2018-12-17), LocalBroadcastManager is deprecated:
LocalBroadcastManager is an application-wide event bus and embraces layer violations in your app: any component may listen events from any other. You can replace usage of LocalBroadcastManager with other implementation of observable pattern, depending on your usecase suitable options may be LiveData or reactive streams.
While it is highly likely that this class will remain available for a while longer, I would like to start cleaning up our applications anyway, so I want to migrate to something better before Google actually removes the old way.
Right now, there are two main roles that these local broadcasts have in our apps:
Update the UI with the new data from the push notification. The way this worked was that each Activity that cares about the incoming push data has a broadcast receiver that listens for the appropriate message and updates its own view data.
Force the user to log out if the server sends a notification to end the session. This works with each activity having an instance of a broadcast receiver that listens for a logout event, ends the Activity, and starts the Login Activity.
As I see it, these use-cases have issues with both of their suggested alternatives:
LiveData is easiest to use in an Activity or Fragment as part of a ViewModel. However, ViewModel is only meant to be used from those classes that directly deal with the UI. Accessing the ViewModel from within the FirebaseMessagingService takes an ugly hack and is a really bad idea from an architectural perspective. Also, different activities and fragments have different ViewModel objects, and I don't want the service to need to access them all.
I can create a Kotlin object (a.k.a. Singleton) with a bunch of LiveData properties, have the FirebaseMessagingService update those LiveData objects from the incoming messages, and have the Activity observe those changes and copy them into its own ViewModel's LiveData properties. The problem with that is twofold: first, it requires me to have two identical LiveData objects for each piece of data, one in the ViewModel and one in the object; and second, it doesn't help me with handling the "log out event", because LiveData is meant to handle changing data, not listening to a stream of events. (I may be able to handle the second issue using this LiveData Event Wrapper, but that still feels like a bad hack over something that isn't meant to work this way.)
While reactive streams, such as RxJava, will probably do what I need, I already forced my team to learn Kotlin, Android Databinding, Android ViewModel, and a bunch of other new stuff in the last few months, and I don't think they can take much more. RxJava is also a large thing to add for just this one use, and we have no plans to rewrite the entire application to take advantage of it in order to justify its addition.
One suggestion I found was to use Kotlin Coroutines with Channels or Flows. These can be used very similar to reactive streams, but (unlike RxJava) are intended to be used with Kotlin and benefit from Kotlin's improvements over Java. This option is especially attractive now that Google has announced that they are focusing on Kotlin for Android development instead of Java.
While this seems to me to be the best option, I have not managed to find any feedback from others about whether it works and if there are side-effects and/or pitfalls to such an implementation. The only thing I found was an open issue on the kotlinx.coroutines repository about the need for providing an example of an application like this. While I'd love to contribute such an example, I don't think I know enough about it to create a good example, and I don't want my production apps to be the guinea pig. I also don't know whether it is better (or proper) to use explicit couroutines with Channel or to use suspend with Flow for this case.
In summary:
Are Kotlin Coroutines and their associated concurrency structures a good way to handle communication between Android Service and Activity?
If yes, which Kotlin type makes more sense to use, Channel or Flow?
Coroutines don't really help with the handoff of data from one software component to another. They help with the processing multiple units of asynchronous work using syntax that appears as if they were synchronous. That's the bottom line for coroutines. They're analogous to async/await syntax in JavaScript. While you might use a coroutine to access data from asynchronous sources, it doesn't give you any primitves to proxy that data on to other components.
LiveData probably works just fine for what you're trying to do. Don't conflate ViewModel with LiveData - they solve different problems. While you're correct that ViewModel should only be accessed by code that deals with UI, that guideline doesn't extend to LiveData. It's perfectly reasonable to expose a LiveData that reflects current data from FirebaseMessagingService that is later picked up by a ViewModel, transformed, and passed on to a view. This LiveData could be a singleton, or obtained via whatever dependency injection infrastructure you choose.
Bear in mind that LiveData is really only supposed to be used for managing changes in state. It's not a "stream" of data that your app can listen to. You will need to make sure that your infrastructure is state-based in order for this to work out well. FCM itself is not state-based, but if you want your views to respond to messages from FCM, you'll need to retain enough context between each message to make sure your UI responds consistently to new messages (or the lack of messages altogether).

Android EventBus library for print notification/callback

Is EventBus suitable for the tasks I am trying to complete? I need a callback whenever any application prints a document.
Yes it is good for getting callback.
But if you only need to use it single time then do not use EventBus library for that, you can use BroadcastReceiver or our own defined interface listener.
Because for using one time the library is not a good idea. If There are many use of callbacks then No-doubt EventBus is best.
I need a callback whenever any application prints a document.
Android does expose this information to apps.
Is EventBus suitable for the tasks I am trying to complete?
No, insofar as an event bus does not cause Android to provide you with information that it otherwise would not.

Passing Callback to an Activity in a library

A library that I am using has an Android activity. I would like to pass a callback to the activity to get notified of certain user events like when user enters a specific code or draws something on the screen. I am not able to find a way to pass callbacks to the android activity.
Note: I can edit the library, however, I prefer to leave the activity within the library for architectural reasons and ease of testing without integrating with the larger app.
What is the best possible way to solve this? Are there any Android design patterns?
What is the best possible way to solve this?
Modify the activity to post an event on an event bus (greenrobot's EventBus, Square's Otto, LocalBroadcastManager when these things occur. Then, listen for those events elsewhere in your app.
I prefer to leave the activity within the library for architectural reasons and ease of testing without integrating with the larger app
Then convince the developer of the library to modify the activity to post an event on an event bus (greenrobot's EventBus, Square's Otto, LocalBroadcastManager when these things occur. Then, listen for those events elsewhere in your app.
Or, convince the developer to offer some other means of accomplishing this (e.g., you subclass the activity and override certain methods to be notified of these events).
It sounds like you have access to the library src code, so create an AIDL interface for communication between your app and the lib. You can set up a callback via AIDL and have the lib send your app the data in real-time as it gets generated.
There's quite a bit of code involved but it is achievable. You can start here:
https://developer.android.com/guide/components/aidl

android LocalBroadcastManager and serialization

I understand that while android allows Serializable objects to be passed within Intents, it's not recommended for performance reasons.
however, if one is using LocalBroadcastManager, does the object ever get serialized, or parceled at all when passed in an intent? since LBM is not inter-process, there'd be no reason to invoke serialization (or parceling for that matter).
You are right, there should be no reason to invoke serialization or parceling when using LocalBroadcastManager, however, that class was designed as a replacement for the normal BroadcastManager in cases in which sending a broadcast through the system made no sense; I think the idea was to make it possible for devs to replace normal broadcast with local ones w/out too much effort.
If you are working on a new project and need this kind of functionality, I would recommend to use a bus library like Otto or EventBus, which solves the same problem in a better, more elegant way (IMHO).
A quick glance at LocalBroadcastManager's source-code would suggest that Serializable/Parcelable objects in Intents are not serialized or parceled.
https://android.googlesource.com/platform/frameworks/support/+/refs/heads/master/v4/java/android/support/v4/content/LocalBroadcastManager.java

Categories

Resources