Context
I've written an Android App to play single media file with its lyrics being displayed in the activity. The Activity screen also has a Play-Pause toggle button and a seek-bar to forward/rewind using drag. And the Activity launches the Started Service in its onCreate() method.
I'm attempting to layer the app confirming to MVP design pattern. I'm looking for sample code as guidance that fits this kind of a situation. Your help is much appreciated.
Things I'm keen to learn
In case like mine where the Activity and the Started Service have two-way communications using EventBus, where does the code for EventBus listener lie in? Is Presenter not having any role in this?
How is the code tested for EventBus related code - both unit and integrating testing?
What code comes in Activity? What comes in Service? And What does the Presenter contract with Activity and Service look like? Lastly, how does the implementation of this presenter look like?
How do you manage code for MenuOptions click events in the case of MVP?
Any reference to existing code-repository in Github/Bitbucket is really appreciated, if a detailed explanation hurts for you. Thanks in advance.
I, personally, wouldn't implement this with an EventBus. Anyway, here are my answers for your questions.
In case like mine where the Activity and the Started Service have two-way communications using EventBus, where does the code for
EventBus listener lie in? Is Presenter not having any role in this?
Yes, Presenter is registered to the EventBus to listen for incoming events and tells the view what to display. The other way round, if user clicks on Play / Pause button, this event is delivered to your service through the Presenter (maybe through EventBus. maybe through android intents that are delivered to the service, whatever ... but delivering this event i.e. through eventbus happens in Presenter ). So Activity is not communicating with Service directly. It's the presenter of your View (activity) that mediates between View (Activity) and playback service.
How is the code tested for EventBus related code - both unit and integrating testing?
You don't have to test the EventBus per se. It's already tested by the author of the library. So pass the EventBus as constructor parameter to your presenter and while unit testing you can pass a Mocked EventBus to your Presenter to check if your Presenter registers / unregisters correctly and you can fire up some events to see if the Event is handled by the Presenter correctly and the expected method on your View is invoked (Mock the View) and vice versa for sending Events (like Play / Pause) to the service.
What code comes in Activity? What comes in Service? And What does the Presenter contract with Activity and Service look like? Lastly, how does the implementation of this presenter look like?
See answer to 1. Activity just displays UI widget. Forwards clicks event to presenter. Presenter communicates with Service (for example over EventBus). The other way around: If your service change the state (like end of audio track reached) then it will inform the Presenter (i.e. trough EventBus) that audio playback is finished and Presenter tells the View to display the UI correspondingly.
How do you manage code for MenuOptions click events in the case of MVP?
As described in 1. and 3. If its going to change the state of your business logic (i.e. Play / Pause) it "sinks" from your View (activity) through your Presenter down to the business logic (i.e. playback service).
Related
I'm working on an Android app (in Java) and trying to use Google's recommended application architecture, but I can't seem to figure out where services fit in to this architecture. I've done a lot of looking online and there is no clear consensus on how this should be done.
For context, my application communicates with a BLE device. I've created BLEService which extends Service that establishes the connection with the device, and provides methods send data to the device. The device can also send data back (and thus needs to notify the app when data is received).
My question is, where should the ServiceConnection reside, and how should it be stopped/started? From my research, there are a couple options that each have their pros and cons.
The Service is started/stopped in the Activity, the Activity observes events from Service. The Activity forwards the events to the ViewModel for processing. This pattern keeps all of the Android components together, but gives more responsibility to the View than I believe it should. The View should only be responsible for handling the UI.
The Service is stopped/started in the ViewModel (perhaps by extending AndroidViewModel). The ViewModel observes events from the Service and processes the events. This pattern is nice because the ViewModel is handling the business logic, however if Service implements its events via LiveData, Google states that the ViewModel must not observe LiveData. Another option is for the Service to implement events via something like EventBus, but there are a lot of people against using EventBus because it is easy to abuse. I have also heard that ViewModel should not have any Android-specific code in it for testing purposes.
The Service exists in some sort of Repository/Model. The ViewModel forwards its sends and observes events from the Repository/Model. This solution is nice because interfacing with a Bluetooth device does seem like it fits the intended purpose of what a Model is. However, it suffers the same issue that the ViewModel must not observe LiveData. I have seen Transformations.switchMap suggested in this case, which causes a LiveData in the ViewModel to be updated in response to a change in a LiveData from the repository. I'm not totally clear on using this strategy, or how it would function in my specific use-case. There's also the issue that the repository needs access to Context, and I have heard it's bad practice to hold on to an instance of Context. Furthermore, I have also read that a Repository should not hold on to callbacks from the ViewModel.
I'm sure there's no perfect solution, but if someone could point me in a direction of best practices, particuarly in my use-case, that would be immensely helpful.
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).
I have started a thread which connected to bluetooth device and streams data. I actually started this thread from a service(Thread not started from activity). So know I need to communicate to activity to show the list of input streams. I am not sure if event bus can provide a such a high frequently changing data. Can some one give me a better existing examples of how to use display the streams.
Please don't ask me for the source code.
I believe Event bus can be a good solution, also check bound services:
https://developer.android.com/guide/components/bound-services.html
I advise you to look into LiveData from the Android architecture components. You can observe the result from the activity, and it will "unsubscribe" for you when needed (onStop()). You can read about the advantages on the link I provided.
You could extend a LiveData and implement the logic inside it (like this example), or just use it to dispatch the updates, then observe it on the Activity. The postValue() method will ensure that it gets dispatched on the MainThread.
I am developing an Android app that does Human Activity Recognition.
It basically works like that - Service constantly reads the accelerator data and stores the recognized activity (i.e. Walking, running) in a database. The user can see all of the recognized activities in an ListView in activity (accesses the database). Every User table in the database has a pa_goal (physical activity goal) field which the Service reads from the database and does some checks.
The user, of course, can change this goal from an activity. Since I will be implementing the MVP architectural pattern.
I am unsure where to put the Service? It surely isn't View. Any advice?
In a clean architecture, which is what I am assuming you are using MVP for, there is the idea of separating the framework from the business logic. This is essentially what a normal presenter allows you to do.
In this case its not a view you are dealing with but the principle is similar. You don't want all your business or application logic mixed in the Android code when you can separate them out for nicer, more single responsibility classes. So I would say that while it isn't a view you should still have a presenter type class (probably better to be called controller or manager maybe).
This class would be a POJO that controls how your service behaves which is easily testable with standard junit tests and service mocks. This class and the service could then be put into its own feature package and interact with the back end models the same way as your presenters.
So, in summary, the role is of another feature of your app that sites alongside the other features (which are usually just views in my experience).
Hope that helps
This article helped me in a similar situation, although may not be exactly yours, the idea is the same:
https://android.jlelse.eu/android-bound-services-and-mvp-12ca9f70c7c7
Basically, the author works around the fact that a bound service is tightly coupled to an activity, and it adds extra lifecycle calls to it.
I am in the same situation. Finally I decided to do something like this:
Activities or Fragments are out of scope, they do not know anything about MVP BUT i am going to use an event bus like Otto to send signals/events, So:
My classes which extends some kind of Presenter know nothing about Android Context but they will have an MvpView interface, with only onAttachPresenter and onDetachPresenter.
The class which extends Service will have a Presenter attribute and implements some MvpView interface with onSucess, onError, onStart, onComplete or something like that and same events for Otto (onSucessEvent, onErrorEvent, onStartEvent, onCompleteEvent).
So when I need to do something the Activity or Fragment will start the service, the service will "start" or talk with the Presenter and when the presenter finish with success will call to mvpView.onSuccess() and store the info inside a local DB with SQLite (storeIO maybe) and finally the Service will invoke Otto and pass the signal (without any data on it), probably onComplete.
Finally the signal will be catched by my UI (fragment maybe) and retrieve all the info inside a DB in SQLite.
So when the onSucess happens the UI will show the latest and best data BUT when onError happens will (at least) show some info (or not if you want) saying to the user "there was a problem but at least you can see something", bot onSuccess and onError will call onComplete after all.
Do not know if this is the best solution but in this case I think I am not going to deal with Activities or Fragments lifecycle and do not care about onSaveInstance and restore data when the user rotates the device. It will always fetch the latest data inside DB, and if something happens (no internet connection) you can at least show something when you receive the onComplete Signal.
Some facts I am still thinking:
The Presenter won't be a singleton class
Presenter knows nothing about Context but yes with MyApplication class
What happens if for one screen (Fragment) you have differents service with differents onSuccessEvents? Simply use some kind of action as an ID, to identify them.
Never make the Activity Fragment implements the MvpView, you will have to deal with the lifecycle.
I'm creating an app in an MVC pattern... and I'm trying to do most of the data getting and manipulation on the Model side of things so I don't clutter up the Activities with code that does not belong there, but the one thing that's tripping me up a bit is AsyncTask... from what I've seen it seems that this is called most of the time in the UI because it allows you to update. the problem with that is I am doing all my network calls using AsyncTask from my model not my activity. But I still want to update my UI when cretin things happen such as a network call returned something put it in the ui.. so is there a way to make a call back from a model to the Activity or something to that effect, so I don't have to put that code in the activity?
any help would be greatly appreciated.
What you need is an interface which acts as an update "listener" in your Model. That way, your activity can register with the listener when it is active and receive notifications of changes accordingly.
There are many examples (and built-in listener classes) - here is one:
http://www.tutorialspoint.com/java/java_interfaces.htm
Creating an interface in your Activity that is registered in your model allows your model to notify the interface of changed data in order to update properly. If you implement your model as a service or maintain instances of them in a service, then you can bind to the service and then register your listener assuming your model processing extends beyond the life of activities.
If not, AsyncTask is where model processing should occur and you can implement your model synchronously and use listeners to monitor it.