I'm currently learning to develop for Android and I'm having a somewhat hard time figuring out when and how to use services. I have already seen the numerous questions asked about very similar things, but I can't quite find the exact answer to my questions.
I have an app which talks to a restful api. I fetch several lists which I would like to cache in memory and only update if the user hits a refresh button, or certain activities are created. If a list is refreshed, sometimes several activities need to be notified, so that they update their content (if they are on screen at the time). I store the data I retrieve in value objects.
On a non-android app I would usually create a sort of dataproxy class in a singleton pattern. I could ask the dataproxy to update its data via http request, and then it would send some kind of system-wide notification as soon as the data is changed, so the interested views can all be updated. I hope this makes sense.
My question is now: How do I do this the android way? Do I bind and unbind to a dataproxy service, which I can actively ask to fetch certain data? Should I do my non-persistent caching in this service or somewhere else? Do I need AIDL, or can I just use normal objects for moving data between a service and an activity? Although I find the android dev guide pretty well written and useful, I haven't found much information on services best practice.
Thank you in advance!
How do I do this the android way?
You assume that there is a single "android way".
Do I bind and unbind to a dataproxy service, which I can actively ask to fetch certain data?
You can either bind, or send commands via startService().
Should I do my non-persistent caching in this service or somewhere else?
If you're sure that you only want it to be in RAM, I'd lean towards static data members. Make the service be the "do-er", not the store.
That being said, I'd treat this more as a synchronization pattern, with the real store being a database or directory, with a cache in RAM. Users will find this less frustrating -- under your current plan, if they are in your app, then take a phone call for a while, they'll have to have you download all the data again.
Do I need AIDL, or can I just use normal objects for moving data between a service and an activity?
If they are all in the same process, normal objects is fine via binding, or use Intent extras for the command pattern.
Now, back to:
How do I do this the android way?
Option #1: Wrap your store in a ContentProvider and use ContentObserver for changes.
Option #2: Have your service send a broadcast to your package when the data changes, so the foreground activity can find out about the change via a BroadcastReceiver registered via registerReceiver(). Other activities simply grab a fresh look at the data in onResume() -- the only one that immediately needs to know of the data change is the one the user is interacting with, if any.
Option #3: Use the binding pattern with the service, and have the foreground activity register a listener with the service. The service calls the listener when data is updated. Once again, ather activities simply grab a fresh look at the data in onResume()
Option #4: Cook up your own listener system as part of your static data members, being very very careful to avoid memory leaks (e.g., static reference to an activity or service that is destroyed, preventing its garbage collection).
There are probably other options, but this should get you started.
The Google IO session mentioned by Andrew Halloran:
http://www.google.com/events/io/2010/sessions/developing-RESTful-android-apps.html
Check out the Google I/O session videos. I implemented REST api calls the easy BUT wrong way. It wasn't until watching this Google I/O video that I understood where I went wrong. It's not as simple as putting together an AsyncTask with a HttpUrlConnection get/put call.
Related
I have a case in my Android application in which I need to perform a long running task. At the end of that task I will use that info. I have multiple activities that need to access that info and I do not need to recalculate it each time.
The simple answer is create a 'static' class that can store the info. If the info is not yet there, it can start an AsyncTask to get the info. If the info has already been obtained/calculated it can just give back the info.
However I am wondering if a service is a better pattern/idea in this case. Can I use a service in Android, have that service obtain the data and allow other activities to ask that service for the data?
However I am wondering if a service is a better pattern/idea in this case
If the task will take longer than a second or so, I recommend the use of IntentService. That way, if your app moves to the background while the work is going on (e.g., incoming phone call), Android is less likely to terminate your process, allowing you to complete your work.
If the task will take longer than 10-15 seconds, I recommend the use of a WakeLock as well, perhaps in the form of my WakefulIntentService. Otherwise, the device may fall asleep while the work is being done.
and allow other activities to ask that service for the data?
You only want a service around while it is actively delivering value to the user. Sitting around waiting for activities to ask it questions is not actively delivering value to the user. IntentService automatically destroys itself when the work is complete.
When the data is ready, use an in-process event bus (e.g., greenrobot's EventBus, Square's Otto, LocalBroadcastManager) to tell interested parties that the data is ready. If you also need to hold onto the results past that point, use an appropriate feature of the bus (e.g., sticky events with greenrobot's EventBus, the #Producer pattern with Otto), or have a separate singleton cache.
If the information is needed at different points of the Application life cycle then, then I would suggest storing it using shared preference. That would give you the option of accessing the information next time you would start the App.
However, if you would need to notify an activity of the availability of the information I would use some bus in the application. Incase you wanted to use Otto be mindful that it has been discontinued in faver of Rx. a link to Otto's github page
I need a shared list of computers made available to all my app's activities. The list of computers needs to be upated by two background tasks of some kind, one that blocks on a socket waiting to receive data, and another task that periodically purges computers from the list. What is the proper Android way of doing this to avoid running into activity lifecycle problems? Specifically,
Can/should I use a singleton to maintain and expose the list to the activities and background tasks? (I'm familiar with thread synchronization issues and am prepared to deal with that.)
Can/should I use the IntentService class (two separate instances for the work I need to carry out) or is there a better way? Do I need to use a BroadcastReceiver in that case or could I still store the list in some common place, like a singleton?
How do I avoid keeping my services running when my application is put in the background?
Updated answer for updated question
You can use a Singleton if you don't have a problem with losing your data when your app get's killed (e.g. when you can rebuild the data on restart). In this case you should check that all your components run in the same process (which is default).
You should not use IntentService for intra-app-communication, however bound Services might be an option here
If you bind services from an Activity and unbind them in onPause, they get automatically stopped (if there are no other bound contexts and they weren't started with startService)
If you think your tasks are too complex to accomplish in the same Service, I would recommend two Services bound by an Activity and backed by a ContentProvider which e.g. can be backed by a database.
Old answer
The issues you expierenced might be a problem of Thread-safety (or the lack of it)
Two Intent Services just to share data within an application is definetly way over the target
A broadcast is the right way to notify components of a change
You might want to take a look at Content Providers
Another solution might be a service, which can be bound by all your other components
You can use Database to maintain the UDP packets with timestamp.
Also periodically check the last sync time from Database to check whether UDP packet is coming or not. Hope you know how to use Database.
I have an application that uses a webservice to get information and save the changes made by the user.
currently I have one service that runs while the application is open, and it has public methods for each operation. the trouble is that service is growing considerably and I'm thinking refactor, but the question is what is the best way?
I can think of the following options:
Deferred services the current service and that all are initialized at boot time application
Create small services and that these are initialized by local broadcast
although I have doubts about performance. Can give me some clue or example about which method is better, do not really care that changes are instantly synchronized, these are stored locally and can be synchronized when possible. Data sent are not many, so the synchronization is relatively fast
Synchronization processes are something like
Check if there is new data (I have several types of data, these are the ones that are growing)
Synchronize user preferences
Most likely there's no point of having Service running all the time. Instead, I'd go for IntentService. If possible, I'd also condifer using push notification (like GCM) so the server could let my app know that there's new data to fetch (or maybe even send it to me if you'd fit in the GCM payload limit).
im wondering if it would be a bad idea to create a Singleton that is used between some Android Activities and a Android Service. As far as I know the static fields, in my case the Singleton, is available as long as the whole Process is alive.
My plan is to use a singleton instead of Parcelable to share data between my activities and a Background service. So my Activity1 will add some data by calling MySingleton.getInstance().addData(foo); then I would sent an Intent to inform my Service that new Data has been added to the singleton. Next my BackgroundService would handle the intent and call MySingleton.getInstance().getLatestData(); then it would process the data (takes some time). The result of the service would next be "post" back by using the singleton and fire a broadcast intent, which are handled by the Activity1 (if alive) and the Activity1 will retrieve the result from the singleton.
Do you guys think thats a bad idea?
EDIT:
What I want to implement is an peace of software that downloads data from a web server parse it and return the result. So my Activity would create DownloadJob Object. The DownloadJob-Object would be put into the DownloadScheduler (Singleton) which queues and manage all DownloadJobs. The DownloadScheduler would allow to run 5 DownloadJobs at the same time and use a queue to store the waiting. The effective Download would be done by the DownloadService (IntentService), which gets informed over an Intent that the a new DownloadJob should now be executed (downloaded) right now. The DowanlodService would retrieve the next job from the DownloadSchedulers queue (PriorityBlockingQueue) and return the Result by setting DownloadJob.setResult(...) and fires up an broadcast intent, that the Result is ready, which will be received by the DownloadScheduler which would remve the job from the queue and inform the Activity that the download is complete etc.
So in my scenario I would use the singleton to access the DownloadJobs from the DownloadService instead of making a DownloadJob Parcelable and pass it with the Intent. So i would avoid the problem, that I have two DownloadJobs in memory (one on the "Activity Site" and one on "Service site").
Any suggestions how to solve this better?
Is it true that static instances, like DownloadScheduler(Singleton), would be used by freed by the android system on low memory? So would subclassing the Application and hold there the reference (non static) avoid this problem?
If you are using the singleton just as shared memory between a background service which I assume is performing operations on a different thread, you may run into synchronization issues and or read inconsistent data.
If the data in the singleton is not synchronized, you have to be careful because you are relying on your "protocol" to be sure that nobody is reading while your background thread is writing (which may lead to errors).
On the other hand, if it is synchronized, you are risking to face anr error because the activity which reads the data may be blocked waiting the service to finish to write the data in the singleton.
As the other said, you also have to keep in mind that your singleton may be freed if the os needs resources, and that your data may not be there anymore.
I'd rather use an event bus such as otto or eventbus
EDIT:
Using a singleton as the entry point of background (intent) service is the approach suggested in 2010 Virgil Dobjanschi talk about building rest client applications for android.
The suggested approach is having a singleton that performs as controller of ongoing requests. Please consider also that request to intent service are already queued by the os, so you can throw several intents that will be processed sequentially by the intent service.
Some time ago I also tried take that as a starting point for a library, which still remains unfinished. YOu can find the sources here
What I would certainly not do is to store your data in the singleton. The approach I would prefer is to store the data in some persistent storage (such as sql / preferences / file / content provider) and let the client know of the change through a broadcast message (or, if you are using a content provider, through an observer).
Finally, to some extent this is the approach followed by the robospice library, which looks quite mature and ships a lot of interesting features such as caching.
A better idea is to subclass Application and put any long living objects in there. By subclassing Application you can properly handle startup and shutdown of the application something you can't easily do with a singleton. Also by using an Application Activites and Services can share access to the models within your program without resorting to parcelables. And you can avoid all of the problems Singletons bring to your program.
You also don't have to resort to storing everything in a database which requires lots of boiler plate code just to shove a bunch of data in there. It doesn't do anything for sharing behavior between parts of your application and doesn't do anything to facilitate communication and centralization of activities. If you really need to persist state between shutdowns great use it, but if not you can save yourself a lot of work.
You could also look into using something like Roboguice which makes injecting shared models into your Activities and services.
You might find this helpful:
what's design pattern principle in the Android development?
Using a singleton like this is not necessarily a bad idea, but you will lose it's state if Android decides to stop your process. You may want to consider storing your state instead in a SQLite database or a persistent queue (take a look at tape for a good example).
I am new to Android. I’m attempting to write an application which will display multiple pieces of information about open stores. I get that information using a RESTfull API which passes JSON data.
Here is my question: What is the best service/threading implementation choice?
Here are my product requirements:
• I want to encapsulate all the API and JSON into a class that one or more Android “Activities” can call. I think this might dictate a service but this service will only need to run when my application is running and will not be accessible by other applications. The user will be required to authenticate into the remote system via the RESTfull API.
• It will have to be on a separate thread because of the possibility of the API calls taking too much time. I don’t think it will need to be multi-threaded since I don’t see more than one “Activity” will be interfacing with the service at a time.
• The service should look at caching some of the information it gets back so that when an “Activity” makes a call (“GetStoreList” for instance), it could return a list of stores it already queried earlier. I’m not sure if I should keep this information in memory or try using the SQLite functionality in Android. I could have several hundred stores in the list with ten to twelve other pieces of information associated with each store. Some of this information would be displayed in the “Activity” list view and some won’t. Since I don’t have any experience with SQLite, I’m not sure what the performance cost would be over storing the information in memory.
• There will be about a dozen or so methods that the service will need to encapsulate. For instance: once I get the store list, I may want to call the API again to find out if the store is currently open. Some of the information passed will be custom classes and therefore would require “Parceable” class definitions if I have to use IPC’s as part of my solution (if I understand the Android documentation correctly).
• I would also like to “Lazy-load” the list into my “Activity” so that I don’t have to wait for the full list before updating the user interface.
Possible Solutions (this is all guessing, so please don’t crucify me… that’s why I’m asking the question):
I could use a class extended from “Service.” It would have to handle the threading itself so that long internet calls via the RESTful API wouldn’t hang the system. Alternatively, I could do the thread manipulation first and call the API with the assumption that I can take as much time as I want. I think I would need to implement communication between the “Activities” and the service via IPC’s. This seems a little complicated to me. I’m not sure if I can use the “Messenger” class. It looks easier than the AIDL stuff.
I think I could use an “IntentService”. This would automatically create a separate thread and queue messages/tasks. I think I could communicate with the service (to get the lists of stores for instance) by “Binding” to the service. The problem I see is passing data back and forth and I’m not sure how I would cache the data between calls to the API since the service terminates after making the API call.
Anyway, I’d rather learn from someone who has already done this type of app instead of doing it the wrong way and coding it twice.
Thanks for the help.
AbstractThreadedSyncAdapter was made just for stuff like this. There's a fairly comprehensive (but complex example) here. Also, one of my favorite Google IO videos gives a pretty good overview of how to use it.
Your scenario is almost exactly the same as ours in my previous project. Here's what we came up with (I'm sure it's not original, but is patterned from one of those google io videos too)
A Service handles the request-response of RESTful calls to the server. This is triggered by the activity calling startService(Intent) that includes the parameters in a Bundle included in the intent. The Bundle contains information as to what API will be called, and what parameters are included.
The Service doesn't directly pass the result to the activity - instead it writes the result to an sqlite database. The activity will know that the transaction is finished by observing the db (via ContentObserver). Similarly, the Service can notify the activity once a transaction is completed via broadcast; the activity can catch this by registering a BroadcastReceiver - however the resulting data should still not be directly passed to the activity via Bundle, as there may be cases where the data is too large for the Bundle to contain (there's a limit for the length of a String that can be included in a Bundle) - you still want to put the result in the Provider. The activity should query for the data as soon as the Service notifies the activity that the result is there.
Additionally, you can include a "success" or "fail" flag in the Broadcast that the Service will throw for the Activity, so it will know if it still needs to query for result - this removes an additional overhead for failed transactions.
If you need to ask, No we didn't use AIDL for this architecture (but we did use it on another module that does facebook/ym chat over xmpp).
The "lazy-loading" I think can be asked in a different question, as it is an entirely different process.