I want to bind my custom firebase service to the MainActivity class. if it was a normal service, it would be easily done by making the service implement the onBind method, but it is not available because this method is set final in the superclass of FirebaseMessagingService class. I want to bind the service in order to use the LiveData variable set inside this class in the MainActivity class.
I have searched for best practices here and read this documentation about bound services but no luck. I tend to use LiveData somehow but I feel it is not working until I somehow manage to bind the service. am I missing something?
As suggested in a comment by #CôngHải, I can use a singleton object with LiveData inside it to communicate between service and activity without the need of binding the service to activity.
Related
I have:
a MainActivity
a OtherActivity
a DatabaseService, which is instantiated in MainActivity and which holds Sqliteconnection and functions like List<data> getData()
How do I pass the DatabaseService to my OtherActivity ?
So far my DatabaseService was a Singleton and I referenced that Singleton from the OtherActivity, but I dont like that Solution.
I can't also pass it with putExtra, because the Object is too complex to serialize.
There should be a more easier way to inject or pass the Service to the activity.
Does anyone have any hint for me ?
What you need to do is binding your activities to the service (in your case: DatabaseService). Highly recommend you follow [this dev guide] https://developer.android.com/guide/components/bound-services and choose the simplest way to create a bound service: extending the binder class. So for short, what you need to do:
implement your service following the sample LocalService
config in AndroidManifest.xml:
<service android:name=".YourNewService" android:enabled="true"/>
for activities needs to interact with the service, just implement them similar to BindingActivity of the guide. (No worries on service instantiation, singleton, etc.)
Please note that you always can create a base BindingActivity class that handles all binding cores and let other activities extend the base binding class.
Happy coding!
I am trying to learn & implement MVVM with databinding in my app. But I am facing difficulties in understanding/deciding few things.
I have one header view in my app which I need to use in multiple activities, so I basically created this
view_header.xml
HeaderViewModel.java (implements java.util.Observer)
HeaderDataModel.java (extends java.util.Observable)
where HeaderViewModel is bound with view_header.xml.
Now I include the view_header.xml in activity_xyz.xml & set ViewModel of Header View from that XyzActivity like this,
xyzViewBinding.setHeaderVm(new HeaderViewModel(new HeaderDataModel(mContext)));
Now I have questions based on this:
1) As HeaderDataModel needs context to work with SharedPreference & BroadcastReceiver, I initialize it inside the XyzActivity instead of HeaderViewModel- Is this correct approach?
2) I had to rely on broadcast receiver to update my header view, so I registered it inside the constructor of HeaderDataMode. Now as my HeaderDataModel is Observable, whenever I receive broadcast, I call notifyObservers() so that the observer(HeaderViewModel) detects it & updates it view.- Is this correct approach?
3) as I register receiver in constructor of HeaderDataModel, I created onDestroy() method inside data model where I unregister it & I call this onDestroy from XyzActivity’s onDestroy().- Is this correct approach?
As HeaderDataModel needs context to work with SharedPreference & BroadcastReceiver, I initialize it inside the XyzActivity instead of HeaderViewModel- Is this correct approach? - No, It is wrong. You must initialize it in HeaderDataModel so later on if you want to update HeaderDataModel, you can easily do it.
I had to rely on broadcast receiver to update my header view, so I registered it inside the constructor of HeaderDataMode. Now as my HeaderDataModel is Observable, whenever I receive broadcast, I call notifyObservers() so that the observer(HeaderViewModel) detects it & updates it view.- Is this correct approach? - Yes as i told it in first point.
as I register receiver in constructor of HeaderDataModel, I created onDestroy() method inside data model where I unregister it & I call this onDestroy from XyzActivity’s onDestroy().- Is this correct approach? - Yes. make public ondestroy() method in HeaderDataModel class.
I have an Activity called MainActivity that starts a Service called MainService. It is also binds the Service, so MainActivity can access methods and public variables within MainService. Is it possible to do it the other way round, i.e. the Service is able to access the Activity's methods?
I wish to implement it this way because I have a variable in MainActivity that is set upon onResume(), and on first startup the service has not yet started by the time onResume() runs, so at that point in time the service is still null.
This answer assumes that the Service in question runs in a different process:
Yes, it is possible. The general idea is that not only your Activity binds the remote Service through some AIDL defined interface, but it also implements additional AIDL interface which the Service is aware of, and sets itself as a callback target of the remote Service.
You'll have to have 2 AIDL files: the first one describes the interface of the Service, and the second one describes the interface of the Activity.
The implementation of such a scheme is very similar to "remote Service callbacks" described in this answer, though "callback" method would no longer be void, but return the value you're interested in.
Design considerations:
The above scheme will allow you to get values from Activity, but I don't think you should take this path. From the description of your use case, it looks that you only want to pass some value to the Service when Activity gets resumed. Since your Service is bound anyway, you can simply add a method setSomeValue(int value) to its AIDL definition and call this method from onServiceConnected() callback.
Yes it's possible.
You have to prepare method in your service to return back your activity just after service is bound:
public void bindActivity(MyActivity activity){...}
Then after service is bound to activity just call this method with MyActivity.this as parameter.
However...
You probably should not do it. Much more clear solution is using LocalBroadcastManager to pass events and data or use some more efficient solutions like Otto to do this same, but still - without direct access to one component's fields / methods from another.
I'm creating an Intent for a Service that I have:
_myServiceIntent = new Intent(this, typeof(MyServiceCls));
This works, but MyServiceCls has dependencies. Is there any way for me to pass these in to MyServiceCls rather than create instances of them in the default constructor?
The simplest way of sending data to a service is through intents, but that will mean the parameters are serialized/parceled, so not helping ...
I see two ways of doing it:
The complicated solution: You could create a binded service with remote messenger; once the service is connected, you can send to the Incominghandler a Message for each reference you need. But thinking again, I believe that will serialize the object and the service might get another instance ... So, maybe the simple solution is the best for you:
The simple solution: Why don't you use an IoC (Inversion of Control) mechanism? You could integrate RoboGuice, AndroidAnnotations or Dagger.
2.1 If you don't want (it's not the time right now) to integrate above APIs, you could have a singleton class in the project that keeps the instances you need, you would initialize this class in Application.onCreate(), lazy load (or not) the objects you need and provide getters for each. And then in your service you call call get for each of those objects you need from singleton class.
in my project I've a class that extends VpnService class. Since I can't call findViewById() method, how can I modify a textview in my layout from this class?
You can't. You somehow tell the activity, if it is still around, to update the TextView. Possible means for this include:
Using LocalBroadcastManager
Using an event bus like Otto
Using a Messenger tied to a Handler
Etc.
Note that usually there is no guarantee that this activity exists, unless the service is only running while the activity is in the foreground.