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.
Related
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.
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 writing an android app right now using EventBus greenrobot. For example I have an Activity it's a publisher in our situation and we have some custom class - just simple class and it is subscriber. Let's assume that I'm posting event from activity. As far as i understand we don't have any instance of custom class, because right now it's decoupled from activity. So how can I make to have instance of this class always.
Or may be I'm using Eventbus incorrectly.
Every time you post an event, the subscriber has to be ready to get that event doing:
eventBus.register(this)
So that class always has to be initialized (from your Activity or from some other part in your app)
So, this is probably a very basic design question, but Im just not sure how to go about it.
Normally, when I use event listeners, I define it in whatever class, then I override the necessary methods in my Activity and instantiate the class and the listener as needed.
However, in this case, I have my MainActivity class (that also implements the listener), a class (called testClass) that implements the listener, and a broadcast receiver class. The broadcast receiver class instantiates the calls the testClass. Now, what I am trying to do is to update a TextView in MainActivity when a given function is called in the testClass.
Not sure how to go about this.
Hope this wobbly issue description makes sense.
This is a problem I've tackled in the past when using a background Service to update data that is displayed on screen. The general pattern I use is to add a member variable to your processing class (in this case, I think it's your TestClass) that is a Map (named something like mCallbackMap) with android.os.Handler as the key and your listener object as the value (normally this will be an interface that you define). The Handler, which is created in the Activity and thus associated with the main thread, is needed because you can't change the UI of an Activity from outside the main Thread; you'll use the Handler to post a runnable to the main thread instead of manipulating it directly.
When your activity gets going, probably in onCreate, onStart, or onResume, you'll register it as a callback with your TestClass by using the mCallbackMap's put() method. Simply instantiate a Handler, which you'll also store as a member variable of your activity, and use it as the key and your Activity as the value. You'll need to remove the callback in onPause or onStop so you don't leak the activity after it's out of view.
Then, once TestClass finishes handling whatever the broadcast gives it, you'll iterate through your mCallbackMap (maybe you have more than one callback, maybe you don't) and call Handler.post(Runnable). In the Runnable's run() method, you call the callback's methods as appropriate.
I have an application with several activities and I want to be notified when the phone goes online (doesn't matter which activity is the user in). I've found a Broadcast Receiver to do it, but I'd like to know if there is a way to declare this BroadcastReceiver only once, I want to avoid having to place the code in each activity (I have more than 20 activities!).
Thank you.
Create a parent abstract class which extends Activity and define the broadcast receiver implementation there. Later, modify your activity classes to extend that parent class.
As in documentation, If we declares the broadcast receiver in manifest file then it automatically runs behind.
Thing is that now you need to handle the onReceive() method of the receiver.
Another way is that you make a separate java class and import wherever you want.