Multiple SyncAdapter to Same Service? - android

In the Google info, it says that the service exists to perform a sync once requested by the adapter. If this is the case, would it be possible to do this with multiple adapters? If so, then how?
I imagine that there could be something like a command pattern where all adapters are given a SyncAdapterInterface and then we have a reference to the manager that manages all these adapters. However, the only control as to which adapter gets activated would be through the intent in onBind.
Is this the best way to do it?

No, there's a 1:1 relationship between all of the sync components so you can't have multiple services/SyncAdapters bound to the same content authority. However, there's no reason that you can't call multiple disparate components in your AbstractThreadedSyncAdapter's onPerformSync(). Do note that the onPerformSync method does run on a separate thread and calls should be done synchronously (as the system only holds a wakelock for you while onPerformSync is running) which precludes starting other services.

Related

Multiple intent services and activities accessing the same data

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.

When to use Android Loaders

Loaders
monitor data source and deliver new results
After a configuration change : no need to re-query the data
I read the android guide about Loaders.
I read Alex Lockwood 4 parts tutorial . Tested his sample app too.
Tried to read the Google App for I/O 13, there's a Stream feature and reading its code find out it uses Loaders since it provides code to create a StreamLoader. Here is the Link
I suppose they use it to monitor for new data and add them to their view.
Same for Alex's app. There's an observer and when there is new data entries triggers a refresh for the UI.
So far it seems to me, Loaders are ideal choice for a "livescore" app. When there's a new update ( which means a new data entry ) it appears on your screen.
Maybe something like Twitter. New messages for you, custom Observer to notice for changes, custom Loader brings the data and an adapter to display them. No need to "pull-to-refresh".
But then again Twitter has its own RESTful API which kinda does the same job. No need for a pointer to the new data. ( don't know how they do it but I guess somehow the "push" new data to your device ).
So my question is :
Loaders are best option when we want to observe a data source and change our view so it will display the new data?
Are there any examples/app I can check dealing with that logic : monitor the data source -> get the data -> refresh UI
Any characteristic cases ( like the one with the "livescore" previously mentioned by me ) that when we have to deal with them we have to choose Loaders?
The second part of the Loaders ( configuration change, keeping the data ) I think its clear. No one want's to re-download an Image gallery when the user rotates the device.
Thank you and excuse my confusion
The best way I can describe a Loader is a Handler that is always on. Both Loaders and Handlers pass data between objects.
I agree with what you said about the "livescore" app.
The Loader monitors the source of their data and delivers new results when the content changes.
To answer your questions:
1) Loaders are best option when we want to observe a data source and change our view so it will display the new data?
A: Yes. if your data source is constantly updating. For example, like a stock-ticker app. If your data isn't constantly updating, then no, don't use a loader. For example, if your data source is only retrieved once, then there's no need for a Loader.
2) Are there any examples/app I can check dealing with that logic : monitor the data source -> get the data -> refresh UI
A: https://www.youtube.com/watch?v=3d9BeWqlfTk
Yes, they are what you want to use for the flow you're describing. Tangentially, there's also AsyncTasks and Services that have similarities.
AsyncTasks
Description (from docs):
AsyncTask is designed to be a helper class around Thread and Handler and does not constitute a generic threading framework. AsyncTasks should ideally be used for short operations (a few seconds at the most.)
Caution: Another problem you might encounter when using a worker thread is unexpected restarts in your activity due to a runtime configuration change (such as when the user changes the screen orientation), which may destroy your worker thread. To see how you can persist your task during one of these restarts and how to properly cancel the task when the activity is destroyed, see the source code for the Shelves sample application.
If you specifically just want a wrapper to basic threading boilerplate, use an AsyncTask otherwise I'd suggest you use an AsyncTaskLoader if you need a general purpose way to run intensive operations in an Activity or Fragment. You get the same benefits from AsyncTask, but it handles lifecycle issues for you. There are also specialty loaders, such as CursorLoader that will are made to handle specific data sources and have conveniences for interacting with certain UI elements.
Services
Description (from docs):
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.
You would use a service to handle data being pushed to a phone. Otherwise, the user would have to open your app to get any pushed data. Services do not interact with your UI. So a common design pattern is to use a Service to gather data from a server (whether pushed real time or if you poll) and store it in your database for use both when your app is opened or when not. There are many other use cases for Services, but this one is probably the most popular.
Conclusion
So no, you aren't required to use a Loader to load data or do long running operations on a background thread and pass the results (or progress) to your UI thread, but they are the best option for most use cases.

Centralized data access design logic

I am having trouble grasping the correct way to implement a centralized data access for different resources.
I want to have a single class, call it DataAccess.class that will call from both a SQLiteDatabaseHelper.class and a ServerAccess.class depending on what is appropriate when I call it's methods.
I thought extending DataAccess.class from a Service was the best approach so I can use ASyncTask for the ServerAccess.class. Now I am having doubts. The DataAccess.class needs to be accessible by most of the Activities in my Application, and I want it to stop when the Application does.
According to the google developer resources it sounds like a Service is well used for ongoing operations in the background but I am unsure how to handle the life cycle given the scope that I am trying to incorporate. Can I make the Service call startService() and stopService() internally when I use the DataAccess.class methods? Does it make sense to call it every time I access the Service or should this only happen once at the start and stop of the Application?
Thanks for the help,
I would recommend
1) Use all AsyncTask based solution because Service - Activity Communication is limited. (Unless of course you need to run something in the background) BUT I would love to hear the counterargument to this, why use a service instead.
2) Don't use just one Facade like DataAccess but make it specific to your app functions (ie sort of like System Services in Android).
3) You should use factories just like Android does to get the DataAcccess object you need. This addresses second part of where you get DataAccess object. Follow same model as getting and Android System service.
4) Use Content Providers where indicated and manage as indicated in Android docs.
Update: I think these are sort of the Axioms of a good solution. Not the whole thing. I will update as we consider this in depth.

Android communication between two services

I know that an activity can communicate with a local service using the IBinder interface; I am trying to find a way for communication between two services.
Specifically, I have my main service starting an IntentService to handle file uploads. I want this IntentService to inform back to the main service once it is done uploading, and before it dies.
Any ideas about how this would happen?
You have to use BroadcastReceiver to receive intents, and when you want to communicate simply make an Intent with appropriate values.
This way you should be able to make a 2-way communication between any component.
In Android, there is a special way of completing tasks like yours. Look at AIDL (it's not well documented in official docs, but there are some extra sources on the web). This is a way of implementing two-way communication between any components placed in separate processes. In comparison to BroadcastReceivers, using this you'd get direct calls and callbacks, that will be less dirty than relying on something would come from somewhere in BroadcastReceiver.
To reach the needed effect, you'll have to define an interface for a callback and an interface for performing actions (with a callback supplied, or register/unregister methods). Than, after you received some command using the second interface, you should perform the job and post back the result through callback. To reach the asynchronous completion add a key work "oneway" before method signature (return type). To separate in and out params (if you need it), use "in", "out" and "inout" keywords near params.
As it comes to restrictions, only primitives, arrays and parcelables (and parcelable arrays) might be transferred between processes.
To control your callbacks lifecycle and operations atomicity, use RemoteCallbacksList for storing registered callbacks and notifying recipients using the duplicate of your list got from beginBroadcast.
If you have any troubles, you're free to ask here.

(best) Ways to deliver control messages to custom content provider

The android content provider has methods for the normal suspects {insert, delete, query, update} but if I want to send control messages there is no obvious mechanism.
Suppose one of the tables managed by the needs to be reset, cleared and reloaded.
How can this be done? I have several approaches each of them seems a bit hackish.
1) create an activity(or service/receiver) to to the job.
The activity does a bulk delete and insert.
This seems like the least hackish but when the content provider starts the database helper creates the tables and initializes them.
It seems inefficient to duplicate the initialization code in the content provider's database helper and in a separate activity.
2) hijack the content provider api.
A dummy table could be created where the insert (or update/query/delete) method would invoke otherwise inaccessible methods.
3) use multiple inheritance to make the content provider also an service (or activity).
This is probably closest to what I want but I don't know how to do this.
It feels dangerous, especially if it were an activity.
4) have a service content-provider pair
Similar to (3) but hopefully without the warts.
The service would have aidl for doing all the control kinds of things.
Such as, loading lookup tables, clearing tables, purging expired tuples, ...
If this were done, the service how would the service be started? by the content provider?
3) is not possible in Java.
4) would simply dump the ContentProvider and use the API supplied by the service.
There might also be:
5) Have the ContentProvider register a BroadcastReceiver via getContext().registerReceiver(), and send broadcasts to it for the different operations
I haven't tried that, but assuming the Context returned by getContext() supports it, it should work.

Categories

Resources