Is calling one Service from different Activities through AsyncTask ok? - android

I have a Service downloading data every second from a web server (This Service is launched from my main Activity). In my app there are other Activitys each of them needs to refresh their UI according to the data downloaded by the Service.
My idea is to give to each of my Activitys an AsyncTask which will retrieve a small amoumt of data from the Service every second. Then the AsyncTask will tell to the UI to update.
Until yesterday I was all doing through AsyncTask, but I read this morning on stackoverflow that retrieving data and giving it to several Activitys is more a Service job than an AsyncTask one.
So I came up with this (not-so-good-even-a-bit-crapy) solution because I can't find how to notify my Activitys when the data is retrieved by the Service.
I read about broadcast receiver, listener, intent... but can't figure out how I can make my Activity's "subscribe" to this one service periodically.
Thanks for your help.
PS : is it ridiculous to code sample each of my keywords in my writing like that :) ?
PS2 : use case of my app is retrieving temperature, pressure etc... from web services and monitoring each of these quantities in a different Activity (I can't monitor them all in the same Activity).

Data can be refreshed over activity from service thru Handler.
In service you can create getter & setter of the handler.
Set the handler of the activity when your activity starts that will make the service to have the handler of the activity which is currently visible.
Use this handler instance to notify about data to the activity.
Follow this link for handler.

So here is how I achieve what I want (Thanks to Vineet Shukla) :
In the Activity "ServiceConsumerActivity", add :
public static RefreshHandler mRefreshHandler;
class RefreshHandler extends Handler
{
#Override
public void handleMessage(Message msg)
{
showServiceData(); //from which I call a method of the Service for getting the fetching value
}
};
In the Service, add :
Message mMessage = new Message();
ServiceConsumerActivity.mRefreshHandler.sendMessage(mMessage);

Related

Android get data from a Service in MainActivity

Do You know if there is any way to start a Service from the MainActivity, send some data and when the service is done, get the data from the Service. For example:
//MainActivity.class
private ArrayList myList = new ArrayList();
public void fetchDataFromInternet()
{
Intent intent = new Intent(this, DataFromInternetService.class);
intent.putArrayListExtra("MYLIST", myList);
startService(intent);
//In DataFromInternetService the app fetches data from the internet and puts them in the myList.
/*
TODO:
1. Get the data from the service after the it has finished.
*/
}
//Note: The service runs only 1 time.
Also, If this is not possible, what alternative do You suggest, in which MainActivity has access to the data from the DataFromInternetService.class.
Note: I don't want to use LoaderManager, I use Services to do background tasks that don't effect the UI.
To communicate with your service you can use Bound Service:
Please check this:
https://developer.android.com/guide/components/bound-services.html
or you can send your data within: broadcast receiver, database, shared preferences. It depends on your needs.
Instead of using a service to run stuff on the background you should use Async Tasks
you can do the following:
new AsyncTask<Void,Void,Void>(){
doInBackground(){
//DO STUFF
}
onPostExecute(){
//Do What You want with the results
}
}
}
If you want to communicate with your service you have to use bound service and bind to it in your activity. Then create handlers for your activity and also for your service. Using these handlers you can notify your activity once the download is finished.
Please let me know if you managed to solve your problem or some further instructions are needed.
That's the kind of question where any discussion at this point was already finished few years ago, but still bothers us every time we need to choose the most comfortable approach for our app. I don't thing that I should dive into code samples or low level explanations. You can find more than needed information by yourself. One thing I can be helpful(I hope so) is to share my approach.
When I'm facing issues like how to pass data between two different components? - I treat such situations kind of straight-forward. You need to notify your hungry component(activity in our particular case) that's fetching was finished an it can get his info from a trustworthy place. Or to be more cruel, pass the data directly to it. This can be achieved by different implementations/solutions but the abstract ideology remains the same.
What can you do? Here are some links :
Read docs?
Trust Mr. Snowflake?
Broadcasts?
Magic with handler?
I'm even not talking about binding a service or using Event Bus.
And still there are even more valuable solutions, but those are enough.

accessing UI elements of activities from another class

Ok first of all android is really confusing. The scenario is I have about two runnable classes which are created from a Login View and if logged in it will create another view which will have other data and even more activities can be created from there
Now I can pass the the Login view context when creating a thread for the runnable class and edit out UI elements in them like this:
((Activity)someContext).runOnUiThread(new Runnable(){
public void run()
{
TextView txtErr = (TextView) ((Activity)someContext).findViewById(R.id.errMsg);
txtErr.setText("Some message");
}
});
But the issue is there will be more activities that will be created and the runnable class is created at the time of logging in, and I can't keep passing contexts.
Is there a better way for accessing the UI elements of different activities from different threads?
P.S: the threads which will be accessing the UI elements doesn't extend Activity and are running in a separate thread.
EDIT
I think I need to make my question more clear... I am developing a client app for a messenger... The process goes this way... User clicks on login button which creates a thread in a separate class named ClientThread for handling socket connection and keeping the connection alive till the user logs out or connection drops. The ClientThread class loops till the socket is connected and whenever some data is received the data is passed to another thread in a class named ProcessDataThread which do the parsing of data and will update the UI accordingly.
Now in a response from server if the user is logged in I want to create an activity from that class and keep a context to that activity in ProcessDataThread as I will be updating UI on further responses from server. And if login fails ProcessDataThread will display a message on the main activity saying login failed, now I was able to achieve the later by passing the context from the MainActivity to the two threads when clicked on Login like this:
global_constants.clientObject = new ClientThread(this);
global_constants.clientThread = new Thread(global_constants.clientObject);
global_constants.clientThread.start();
And then from ClientThread to ProcessDataThread
global_constants.updateConversationHandler.post(new ProcessDataThread(SharedBuff, cntxt));
But how will I create more activities from a non-activity class and do all update them or find a UI element etc...
Not sure if I understand you, but it sounds like you are trying to control the view of an activity from outside of the Activity. This sounds hacky to me. I'd let each Activity manage its own UI.
A good way of doing decoupled communication between objects is the observer pattern, aka an "event bus" or "event dispatcher" system. An example of how to do this on Android is here: http://www.therealjoshua.com/2012/03/event-dispatching-sending-messages/
Basically, the code that's generating the error should dispatch a message. The Activity can listen for this message, and then update its own UI as needed.
EDIT
Thanks for the clarification. I think the observer pattern can still help here. Basically, your data processing threads shouldn't know anything about the UI. Just have them post an event for the error, optionally with additional info on the error. If you want, your event dispatcher class could even make the actual event calls on the UI thread itself using a Runnable like you showed, so that the listener can always assume that they are being called on the UI thread, if this is important for your design. This way you don't have to pass the context to the thread at all (at least not for purposes of updating the UI) - let the worker thread just be responsible for the work, and the activity can be responsible for its own UI.
Another option you could use is an android Handler (see http://developer.android.com/reference/android/os/Handler.html)
In this case, the work is still done in another thread, but the Activity receives a handleMessage callback from the thread at the appropriate time. I haven't used this myself but from the documentation it looks like it can get the job done for what you need.
In either case IMO, the responsibility for updating the UI should lie with the Activity, not the worker thread.

Refresh current view after asynctask started in another activity

I have a situation where I have multiple activities that deal with a single global list of objects.
From activity A, I can start an asynctask which sends an HTTP Get request to retrieve an XML message then parses the XML file into a series of objects.
My aim is to be able to refresh all views, only if the underlying data structure changes.
This should ideally mean that I can launch activity A, call an asynctask, move onto activity B, C D etc, and when the asynctask completes (no matter what activity I am on) the current view should be updated.
I've looked into broadcast listeners but I am not sure I am on the right direction with this, would it be possible for somebody to explain if this is possible?
Thanks
Since AsyncTask instances are dependent of the caller Activity, I think this is not the correct approach. In your case, as you need to recover the result within any Activity, I'd use an unbound Service so it might be accessed whenever you want, wherever you want.
You might also use a local BroadcastReceiver which would send a signal to all of your Activitys and, those registering the action that sent your AsyncTask/Service, would perform the necessary actions you may need. Be careful as if your Activity has not been started, obviously that Activity won't be able to process what you've sent since that receiver should be unregistered.
Just post a runnable to the handler of the current Activity.
Your activities can implement a common interface, where a function "updateUI" or whatever exists, and that way your runnable can be one line, and be agnostic as to the current active instance.
As you probably know the postexecute part of the asynctask runs on the UI thread of the activity that launches it. Since that activity may be dead, just post to the handler in the "doinbackground" part of the async task and keep postexecute blank.
interface Updateable{
public Handler getHandler();
public void updateUI();
}
From Async Thread
final Updateable curr_activity = ...
Handler handle = curr_activity.getHandler();
handle.post(new Runnable() {
#Override
public void run() {
curr_activity.updateUI();
}
});

help with binding a local service

I Need some help here, I have a service which I can start or stop whenever I want and using the onStart() command to pass some extras using putExtras() from my activity
But I need some serious basic instructions on how to interact with the already created service.
Please don't refer me to another webpage which already have some implementations, just give me the needed code to interact from my UI activity to the service:
something like this:
public class myActivity extends Activity {
Object ReceivedObjectFromService;
onCreate()
{
some stuff here
myMethod()
}
public class myMethod()
{
//do some stuff with the ReceivedObjectFromService
//Don't know how to call this method from the service btw
}
please some help, I don't understand the tutorials on how to interact service to activity or viceversa
Interaction with already created service is no different to starting a brand new service. You just simply call startService() so your client code is no different.
Now, the part which is different is the service itself. In your service, onCreate() must start a background thread or a timer to carry on doing a work. onStart() will receive all startService cases and must in fact add the data it receives in the Intent to an internal list or queue and then in the timer's callback start processing from this queue.
Now you can pass any messages or data you want (even closing the service) using startService and passing data in the Intent that your service understands.
Hope this helps.

Android Service interacting with multiple activities

I'm trying to refactor/redesign an Android app. Currently, I've one UI activity (Activity 1) that creates a DataThread. This thread is responsible for network I/O and interacts (provides data) with the UI activity via a handler.
Now, I want to add another activity (a new UI screen with Video) - Activity 2. Activity 1 is still the main activity. Activity 2 will be invoked when the user clicks a button on Activity 1. Activity 2's data also comes from the DataThread.
My idea is to put the logic of my DataThread inside an Android Service (DataService). My question is - can more than on activity bind to my DataService at the same time? Is there a way to tell the service to provide data to a specific activity only?
Any other ideas are welcome?
Thanks in advance.
Definitely more than one activity can bind to your service. You will get an onBind() for each one that binds. Your service would then ideally handle the logic of interacting with multiple activities by identifying them using an ID or the intent (with your own IDs for each activities as extras) from onBind() in your service. You could then have the Service spawn off a background thread for each activity that binded to it.
I usually bind my service from the Application class and have some kind of controller class (like a "mediator" I guess...not sure how all these patterns are named) scoped in the application that handles communications between services and whatever the active Activity is.
This would involve writing your own Application class and telling the Manifest to use this one. I went into more detail on this process in a previous thread:
More efficient way of updating UI from Service than intents?
You could keep track of the "currently active" Activity by sending the Application class a reference to itself in onResume (also explained in the example above). This can be accomplished by deriving your Activities from a common base class that has a way of getting your Application class (casting from getApplicationContext), and in this base class' onResume, send a ref of itself to the application. Then, you can register activities by name with your DataServiceController, for example, and send messages to the current Activity only if it's registered with the Controller to receive them.

Categories

Resources