I have a problem trying to figure out the best way to complete a simple app following the Android best practises. Here is the scenario:
1) I have an activity where the user enters something, its then send to a background Service
2) The background service performs some checks on the input and spawns a new AsyncTask to process the input.
3) The asynctask updates a Status Hashmap in the service with its progress and status
4) There is an second activity that binds to the Service to display a list of currently running tasks from the service and their progresses. The idea is that even if this activity is closed the service will continue to run the tasks and when the activity is reopened the refreshed stats will be shown.
I have problems in 3 and 4. What is the best way to communicate to the Service from within the AsyncTask's onProgressUpdate method and at the same time update the listing activity if its opened, if its not opened its simpler, just update the service tracking maps and when the activity is opened it will read them and update.
Im not sure what is the standart approach to handle "Events" of that sort. Do you have to use a Broadcast listener and subscriber or its too much for this simple purpose?
If you want to communicate between the service and an activity, you could broadcast updates from the service within the AsyncTask.onProgressUpdate method (alternatively within the AsyncTask.onPostExecute(Result) method) and listen for the updates using a broadcast receiver within your activity.
Instead of me copying and pasting a lotta code, check out Vogella's tutorial on services, especially the exercise (7. Exercise: Using services and service communication), found here
www.vogella.com/tutorials/AndroidServices/article.html#tutorial_intentservice
Within the exercise, you're looking for the DownloadService.publishResults(...) method which sends out a broadcast from the service to whichever broadcastreceiver is listening for updates, and the use of the BroadcastReceiver in MainActivity, which handles the updates from the service.
Related
I am new to Android and I have a kind of design question. So I understand that it is recommended to use Fragments. I also understand that an Activity "owns" a Fragment.
So my question is the following:
Assume we want to make a long running background call e.g. HTTP to a server.
The results should be displayed in the UI.
So what is the best/standard practice?
1) Should the object doing the long running calls be "owned" by the Activity and the results send back to the Activity and then from the Activity to the Fragment so that the UI is updated?
2) Or should the object doing the long running called be "owned" by the Fragment and the results are send back to the Fragment for the UI to be updated? So the Activity is completely unaware of this?
Neither, IMHO. The object doing the long running should be managed by a Service, where you are using WakeLock (and, if needed, WifiLock) while the long-running HTTP operation is running. An IntentService might be a good candidate, as you need a background thread anyway.
The service, in turn, can use some sort of in-process event bus (LocalBroadcastManager, greenrobot's EventBus, Square's Otto, etc.), to let the UI layer know about any significant events that occurred from that HTTP operation. Whether the activity or the fragment is the one to subscribe to the events on the bus depends on what needs to happen for the event. If a fragment's widgets need to be updated, the fragment would subscribe. If the mix of fragments change, or some other activity-level UI change is needed, the activity would subscribe.
All of this assumes that by "long running" you mean something taking over a second or so.
For the long running task it's recommended to implement a sticky Service that contains a thread for the ServerSocket listener. Next I'd recommend to process requests by dedicated Thread's which are managed by a thread pool (check for instance this example).
In order to display results in your activity there are several approaches possible:
send a local broadcast from your service or thread which gets processed by registered BroadcastReceiver's which are part of your UI component (either Fragment's or Activity's)
bind your Service to the Activity (which might contain further fragments) and propagate information to containing fragments. There are three ways to go.
Note: In this post it's being said it's better to bind to the Application
pass data via Intent or a SQLiteDatabase
What I like and prefer is using local BroadcastReceiver's but this is just my personal preference.
It depends on your requirements, what might be the best solution.
I'm using a variation of the design recommended by #CommonsWare. I have an ApiClient class that listens to the event bus for requests to invoke API methods asynchronously. Any parameters that are needed for the API call go into the bus request message.
The ApiClient uses Retrofit to make the async API call, and posts a 'result message' containing the result to the event bus on success, and an 'error message' if there's an error. Each API call has it's own triplet of bus messages - xxxRequest, xxxResponse, xxxError.
So, when an Activity or a Fragment (or other, non-ui class) wants to invoke the api, it registers to the bus for the xxxResponse and xxxError messages, and then posts an xxxRequest message to the bus.
The only potential down-sides are:
The ApiClient is a singleton, and is owned by the Application class, just so that it doesn't get garbage collected.
You wind up with a large number of Message classes - I deal with this by putting them into their own package.
What is the purpose with Service class?
Many examples with Bluetooth Low Energy uses Service classes for all Bluetooth communication, connecting, disconnecting, scanning for devices etc. Activity classes always call method from this Service class.
What about implementing all Bluetooth communication directly in an Activity class instead?. Why does nobody implement like that and uses a Service class instead?
From the documentation:
A Service is an application component that can perform long-running operations in the background and does not provide a user interface. Another application component can start a service and it will continue to run in the background even if the user switches to another application. Additionally, a component can bind to a service to interact with it and even perform interprocess communication (IPC). For example, a service might handle network transactions, play music, perform file I/O, or interact with a content provider, all from the background.
Basically it is a loosly coupled component independet from activitys lifecylce. The problem is in Android you can't really control when an activity will be created/destroyed, so for example if you are loading somenthing in an activity and you receive a call, your activity might get destroyed and the result of your update will be lost, or even worst your loading task won't finish and holds on to the activity and it can't be garbage collected and you create a memory leak.
So you use service for long running background tasks, but you just let them run as long as you have to, to avoid, again, memory leaks and be nice to your resources.
Caution: It's important that your application stops its services when it's done working, to avoid wasting system resources and consuming battery power. If necessary, other components can stop the service by calling stopService(). Even if you enable binding for the service, you must always stop the service yourself if it ever received a call to onStartCommand().
what about implementing all Bluetooth communication directly in an Activity class instead
you most likely end being killed by the framework for doing too much on UI thread (aka ANR - Application Not Responding). See Keeping Your App Responsive article on develoer site.
Anything that is not directly related to UI (like networking of any kind) should be offloaded to separate task. Be it AsyncTask:
This class allows to perform background operations and publish results
on the UI thread without having to manipulate threads and/or handlers.
or IntentService:
IntentService is a base class for Services that handle asynchronous
requests (expressed as Intents) on demand.
. The Service (not IntentService) is for slightly different purpose:
A Service is an application component representing either an
application's desire to perform a longer-running operation while not
interacting with the user or to supply functionality for other
applications to use.
Service class is used to perform , background non UI operations like playing audio file.Further service is the component that will run in background even if your activity gets destroyed ,While using Bluetooth we really do some non UI phone level operation and hence we use Services .
Activity class isn't a good place for any kind of communication tasks. It can be killed as soon as user switches to another activity. It shows UI, that means that we can't do much work in Activity's thread. Sometimes you can use somthing like
Thread t = new Thread(new Runnable() {
#Override
public void run() {
// do something here
}
});
t.start();
or more complicated things with AsyncTask but this is suitable for short-time actions.
Service will not be killed so fast, so it's good for background work of any kind. Just read Android documentation about services.
I am developing a Multiplayer Online word game on Android and would like to implement a thread that checks for server side events like the following:
Player join a game.
Player left a game.
Player won a game.
etc...
The thread will be responsible for listening for all kinds of events and dispatching events to the responsible activity If it's visible to the user.
In other words to be more clear, I've got a list of event and each activity must register to a subset of these events.
Events:
E1 - E2 - E3 - E4
Activities:
Activity 1 interested in E1 and E2.
Activity 2 interested in E1, E2 and E3.
Activity 3 interested in E3 and E4.
I am asking about the best design approach to implement a thread that runs in the background and can dispatch events to all activities?
Some Ideas:
-Implement an AsyncTask on the application level.
-Send broadcast intents to a custom actions.
-A service is not the best approach because it should be created to run in the background when the user is not interacting with your application.
Can you propose a best practice approach?
A good approach for this is to use a Service combined with AsyncTasks.
While a Service is useful while the user is not interacting with your application, that certainly isn't its only use. A Service is the logical home of anything that does not require a UI.
In data driven apps, I have used Services as API adapter layers. It is nice because I can launch it from any activity without worrying about whether it is already instantiated or whether I need to do any cleanup work after I'm done. The framework manages the service's lifecycle and tracks clients.
I think your case is similar. Each activity can use bindService and unbindService to register for updates as long as it needs. The service will continue to do its thing as long as any Activity is bound. The service can keep track of which activities need updates using the Intents received in onBind and onUnbind, and send them updates via specific Intents, or, more appropriately, the service can fire broadcast intents and the Activities can register for what they need.
Within the Service, you would run AsyncTasks (probably running them on AsyncTask.THREAD_POOL_EXECUTOR so you get more than one thread) to do your updates. Remember that the service itself is launched on the UI thread.
Another nice benefit to using a service is that it doesn't require an Activity to run. One use for this that comes to mind is post-shutdown cleanup. If you need to post scores or analytics or something when the user exits, you can allow the activity to close quickly and finish the longer-running work in the background.
Activities can request those longer individual tasks from the Service using startService, and the service won't exit until it calls stopSelf (or stopSelfResult).
The combination of start/stop and bind/unbind really allows for clean management of the service. It will run when and only when it needs to, and you can keep all your API access in one place.
Edit:
As if this wasn't a stout enough wall of text, I've come up with another good reason to use a Service. From the developer guide on processes & threads:
Because a process running a service is ranked higher than a process
with background activities, an activity that initiates a long-running
operation might do well to start a service for that operation, rather
than simply create a worker thread—particularly if the operation will
likely outlast the activity...
What I want to be able to do is toggle the visibility of an element in my activity FROM a service.
How can I pass the current activity to my service class in order to send back messages/call functions in my activity?
What happens if the user exits the app and the service is still running, but obviously without a running activity to call functions within?
Thank you.
I don't think it's a good idea. Here's a good answer about notifying an activity from a service: Notify activity from service.
To answer your first question, you wouldn't be doing anything to the UI from your service. You have a few options for communicating between an activity and a service. You can set up a BroadcastReceiver. You can bind the service to your activity and use Android's AIDL to set up handlers for the communication. Plus others.
To answer your second question - make sure to stop your service in your onDestroy method. Alternately, if you've bound the service to an activity, the service will stop once the final activity that the service is bound to stops.
I'm developing an android app (if you want more info http://www.txty.mobi) and I am having some problems with dialogs management. I'm quite new to Android so the way I'm doing things completely wrong. If the case please just say so pointing me to the right documentation to follow.
Background:
The main blocks of the app so far are one activity and one Service (which derives from IntentService).
The actvity needs to interact with the service in just two occasions: start/stop the service. The intent service will self regulate its lifetime using the AlarmManager.
A typical flow when clicking on start/stop:
1) the activity on its onResume registers a broadcast receiver to events sent by the service (unregisters it in the onPause)
2) the activity starts a indeterminate progress dialog
3) the activty sends a single shot alarm event (either start or stop) which will be send **straight away to the service
4) the service does what it needs to do to start
5) the service emits a broadcast event basically saying "done"
6) the activity receive this event and gets rid of the dialog.
The Problem:
The activity can lose its foreground status let's say if the user switches focus or a call is received, so the onPause method is called (at this point the activity could even be killed by the system to claim memory). obviously if this is the case the activity will never receive its broadcast event because the receiver has been unregistered. This will leave the app in the awkward situation, when the activity is brought again to the front, of having a dialog that you can't kill nor will never get rid of.
The (possible??) solution:
The way I am handling this now (apart for keeping the broadcast receiver in place) is by creating a utility class that uses preferences to keep track of which operations are being executed and their status:
Activity
- in the onResume using my utility class gets the list of operations the activity is waiting for
- check their status
- if they are completed perform some actions accordingly (in my case get rid of dialog!)
- delete the operation from the preferences.
- just before asking for a operation to the service it saves it to the preference using my utility class.
Service
perform operation and save state of the operation to the preference using my utility class.
emit broadcast.
Disasters happen!
Now this saves me in a normal situation, but if a disaster happens (i.e. with the task killer app you kill everything) the service might be killed before it can save the status of the operation I am stuck as before (the activity will think the operation is still going on so it won't touch the dialog). So as for now I add a Dismiss button to very dialog just in case :)
Now all of this looks too complicated for what I think should be a fairly common thing to do. That's why, as said at the beginning of the post, I might (very likely!) be completely wrong.
Any ideas? Apologies if this question has been asked already, I looked around but didn't find anything. Please point me to any resource online explaining this.
Thanks and sorry for the lenghty post :P
Luca
Have you tried using a StickyBroadcast? This caches the latest broadcast, so it can be received onResume. Please see this post.