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.
Related
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.
The Android Dev Guide says
Content providers are also useful for
reading and writing data that is
private to your application and not
shared.
Generally, Content Providers are used for providing data to different applications or sharing data among them. I was wondering if there is any use to having private providers and not wanting to share it. Are there any benefits provided that a direct access to DB or file system don't provide?
Thanks,
Rajath
It automatically schedules all your server-side and synchronization DB access in a background thread. However, in your application frontend, the Content Resolver/Provider will normally execute queries/transactions from the UI thread by default. You must perform all transactions asynchronously (i.e. using a CursorLoader) to ensure that your application runs smoothly on the UI side
It localizes re-entrant DB access from the any threads that access through ContentProvider, so that all locking can happen entirely in your ContentProvider override calls, rather than keeping track of it in a DB layer, a service, and a UI layer.
As part of the above, it also provides a nice singleton interface to your data -- If you have ten Activity classes in your app, you just go through ContentResolver static calls from each one, versus needing to deal with opening/closing a SQLiteDatabase in each activity as you jump from one activity to another in your app.
ContentProvider is tied very tightly to the SyncAdapter model -- Meaning it's pretty much the only way to go if you want to keep your database in sync with a server-hosted database out on the net. (your app mirrors a REST api type of situation)
It ties into ContentResolver's ContentObserver interface -- This is an interface where (among many other useful things) a view can register as observing a specific set of data (through the Cursor to that data). Then, if you drive a change into the ContentProvider, the CP can notify the CR, which can in turn notify any relevant cursors, which in turn will requery and cause the view to update. This is much cleaner than having to manually keep track of your views so you can invalidate and redraw them.
As for re-entrant locking of the DB, it doesn't do it completely, but it helps -- your ContentProvider class implements four simple functions (CRUD interface) and, if you choose to override it, a fifth, batchAdd() -- This localizes your locking. The bone simple answer is to simply tag all four/five of those function declarations "synchronized" at the function level and you're done. Much cleaner than trying to figure out locking out from 20 places that access your DB in 5 different Activites.
For example,a multiprocess application use scenario(like: music play service usually run in a remote process), between the two process that in one application share database should use private ContentProvider.
I am working on a program that has the following situation.
You want to look up a recipe, so the Activity will call the db ContentProvider.
The recipe isn't stored locally, so it will call out to a web service to get the data.
This data will be stored in the database as I am assuming that if you don't want to keep a local copy you will choose to delete it later, but you may want to shop and cook without going to the Internet constantly.
So I think my design may be getting overly complicated.
I currently have a Service that will call the REST service, and a ContentProvider to go to the database.
I am now considering replacing the Service with a ContentProvider, as I don't need a long-running Service as it should infrequently go out.
So, the Activities would call the db ContentProvider, and if the query is empty then the ContentProvider would call the REST ContentProvider, as the Activity shouldn't care where the data comes from, and the db ContentProvider would then store the information before returning back to the Activity.
Is this the best approach for my scenario, or is it bad form to have ContentProviders chained together?
I think that is quite reasonable. However, I think you could still keep the Service but just always expose the data through the ContentProvider. One glitch here is that you will have to start(or bind) the service in the ContentProvider and you will have problems when testing your Provider using ProviderTestcase2<Provider> as the MockContext does not support starting the service.
It seems a good approach. Currently I'm developing something similar and I've found this great article, where the author explains everything step by step, saying which thing for what is used for, what is the best approach and so on. Take a look at it if you are having some troubles implementing something:
http://programming-android.labs.oreilly.com/ch11.html
I have a simple approach question about Android design.
I envision a scenario where I provide a service and an activity. Both the service and the activity need to read/write to the same data. The basic idea is a live playlist: the service that is playing the list "pops" a song from the list when it's done playing, but the the app can also edit the list by adding or deleting songs.
I considered using a ContentProvider for the actual playlist, thinking it would be simple, but all ContentProvider examples I can find on the internet seem morbidly overcomplicated or involve solely SQLite.
Another approach would be to keep a simple file in my resources, and access that from both the service and the app.
Which approach seems to be better here? If I should indeed use a ContentProvider, can someone please direct me to the simplest possible implementation, preferably not involving SQLite? From my prior looks, ContentProvider seems overcomplicated for my simple purpose.
Thanks for any opinions!
-Chase
A ContentProvider may persist the data it's entrusted with however it likes. Typically, that means SQLite, because the mapping to the ContentProvider interface is intuitive.
However, as long as your ContentProvider implements the insert(), update(), delete() and query() operations, (or implements as much as the app that uses the provider needs to have implemented to do it's job) you can persist the data that goes in and out using whatever mechanism you like. Feel free to store it in a SQLite database, a file, or whatever.
Just keep in mind that your ContentProvider may be subject to being killed and restarted, maybe even being garbage collected and re-constructed later, so you need to use something that's robust against the class going away and being reinitialized.
In your case, you probably don't care about persisting across reboots (who cares about the playing music list being there after you reboot) so some sort of list in a static variable ought to be sufficient.
I've been watching Virgil's presentation at the Google I/O on REST-heavy applications.
Google I/O 2010 - Android REST client applications
Though the notepad tutorial makes database calls directly from the UI layer, Virgil suggests making database calls in a Service.
At the moment, my Activity's onCreate method uses an extended ContentProvider to access an SQLite database to query a Cursor to attach to the Activity's ListView.
I'd like to move this code into a Service. Easy enough. My question is, what is the appropriate way to transfer the Cursor back to the UI layer? I've seen many questions posed and there always seems to be someone suggesting there is a more appropriate way to do it. What is that way?
More specifically, I so far gather that the Activity should register as some sort of listener. When the Cursor is retrieved in the Service, a notification is set to the UI layer to access it. Where does the Service shove it so the Activity can grab it?
Also, my considered architecture is to have an extended Service, which is called by Activities. Inside this Service, database transactions will be made through the use of an extended ContentProvider, any listening Activities will be notified, and threads will be launched to hit web services. So, I have 1 extended Service, 1 extended ContentProvider and several extended Threads for different web services. Does this seem acceptable?
I am simply using the managedQuery call inside my Activity to get the Cursor. It's a fairly light operation and I don't think it will hold up the UI.
I've created a Service which then calls a web service to find new data. If new data is found, it is placed in my database and sendBroadcast is called. My Activity has a registered BroadcastReceiver which hears the broadcast and calls requery() on the Cursor.
Have you consider implementing Loaders?
I have an application which uses Intent services to fetch data from a server and store
them using a ContentProvider. Then the fragment or activity which needs the data implements
LoaderCallbacks<Cursor> (onCreateLoader, onLoadFinished and onLoaderReset).
At onCreateLoader I instantiate a CursorLoader object and return it while at onLoadFinished I make sure that the data from the Cursor are displayed in my Fragment/Activity.
Check the official loaders guide.