What is content provider? - android

I just followed tutorial in developer.android.com to create sync adapter to provider feature "synchronization between local db with server db", and after bloody trial and error i managed to make it work (onPerformSync has called successfully).
And now for next step to create sync feature, from what i have read in several articles, I need to create a content provider. I already read https://developer.android.com/guide/topics/providers/content-provider-basics.html but I still dont get it how does it work.
from this link https://developer.android.com/guide/topics/providers/content-provider-basics.html, it raised several questions in my head:
what table they are talking about? are they talking about sqlite table or some "another" table?
content://user_dictionary/words what uri is this? is this uri to table file where sqlite stored? if it's, how do I know mine? I mean where did my sqlite store table that I created?
from what I read (if i got it right), ContentProvider just like a repository. do they have same functionality? I already created my repository using anko https://gist.github.com/mockiemockiz/a552a669d28a3c90c144bc1542b86a5e , can I use that code / convert that code to be ContentProvider that able to tell sync adapter the data has changed?

I just followed tutorial in developer.android.com to create sync adapter to provider feature "synchronization between local db with server db", and after bloody trial and error i managed to make it work (onPerformSync has called successfully).
FWIW, SyncAdapter is not especially popular.
what table they are talking about?
The word "table" shows up 40 times on that page. We have no way of knowing which of those 40 concerns you, and they use the term in multiple ways.
what uri is this?
That is a Uri pointing to a collection of data ("table") in the user_dictionary ContentProvider.
is this uri to table file where sqlite stored?
That is for the developer of the ContentProvider to decide. The ContentProvider API does not stipulate where the data is stored. It could be stored in SQLite, or a JSON file, or whatever. Convention says that a collection of data exposed by a ContentProvider maps to a SQLite table or view, but that is not required.
if it's, how do I know mine?
You know it is your ContentProvider if you used user_dictionary as your authority (see android:authorities in the <provider> element in the manifest).
I mean where did my sqlite store table that I created?
That is up to you. ContentProvider has nothing to do with SQLite, unless you write code that ties a ContentProvider implementation to SQLite.
ContentProvider just like a repository
Not really, at least in terms of how I use the term "repository". A ContentProvider is a wrapper around some data storage mechanism, to allow outside parties to have controlled access to that data.
can I use that code / convert that code to be ContentProvider that able to tell sync adapter the data has changed?
That would be rather difficult. This is one of the reasons why few developers use SyncAdapter.

Related

get rid of ContentProvider per database table

In my (Android) project we have an ContentProvider per database table.
Every ContentProvider extends AbstractContentProvider, which has some virtual methods which gets some information about the database table (e.g. the table column names). Thanks to this, we can have some nice checks during insert/delete/etc operations on each table ContentProvider.
But on the other hand, adding a new database table consists of writing a lot of redundant code - after writing a schema we need to create a ContentProvider with analogous among different tables methods and add it to the manifest.
We would like to get rid of this boilerplate and to be able to retain current behavior. Can this be done? A solution we thought we'd use was to first change all ContentProviders AUTHORITIES to the same one and register only one contentProvider in manifest, but this apparently is not possible.
Do you have any other ideas to achieve this goal?
you should ideally use single content provider and expose multiple URIS - one for each table.
Implementation for CRUD methods for all the URIs are similar and can be done in a generic way. No code duplication is required to handle multiple URIs. Reason being SQliteDatabase has similar APIs/parameters that maps with ContentProvider API parameters

Can I use SQL for Android contacts database to execute complicated update?

Assume that I want to update dirty flags of some contacts linked to a group.
To do this,
From 'data' table, records having the group ID should be queried.
Should update using contact ID in the fetched records.
But if I can use SQL, it can be done with one SQL statement.
Is it possible?
Thanks in advance.
No, I don't think so.
See, Android API doesn't let you access the SQLite database behind the contacts (although it is there) but rather abstracts data access by means of ContentProviders (And there's a good reason for that: giving developers access to the SQLite db would be way too insecure -- any app with proper permissions could e.g. drop the contact tables and thus cause major malfunctions of other apps)
It's not much more complex to run update statements on those though (well, apart from the fact that SQL statements are kind of broken down into methods and parameters), the ContentProvider class has .update() method for just that, the tricky part is the WHERE part of the call, you'll have to take a good look at the ContactsContract class.

Android: What is better, using a SQLiteCursorLoader or implementing a ContentProvider?

I have to show the contents of a SQLite database in a ListView, and seeking the web I have found 2 options:
Using SQLiteCursorLoader, or
Implementing a Content Provider like here
Android Dev docs say a content provider is not needed to access a database, and it should be use to share data with other apps (what I do not need). What do you think is better in terms of efficiency, error-prone and simplicity?
Thank you guys!
Obviously sharing data is the most frequent reason people put for using a content provider.
There have been some bugs in sqlite and multiple users, although not absolute usually a content provider is in a single thread and can solve this issue and yes this is when your sharing data between apps.
A content provider can give you a level of abstraction and possibly have less code maintenance, especially with internal database structure changes.
It allows you to perform asynchronous queries with a CursorLoader, off loading your UI Activities, which is the design recommendation.
In conjunction with a database helper, it makes it easier to get your table and column names correct and narrows down where you have to look and maintain code.
The use of a database helper or contract between your application and content provider can provide some security, as you provide the methods to your and any other application on how the data get updated.
This can also give you some better data integrity, dependent on how complex your database structure is. It leaves the guess work out of was I supposed to update Table A first and then Table B or the other way around.
It can help with table joins and views so you only have to figure that out once and represent them as a URI.
You can created a URI to handle a raw query inside of a content provider to supply results, that otherwise might have been hard to write with the normal URI structure as it's presented in most tutorials. This is also useful if you have to write a correlated query.

Content Providers or direct database?

I was wondering whether we can use the databases like (contacts.db, mmssms.db) directly instead of content providers ?
I have a reason to ask so. In my recent project, I was supposed develop a contact app. I used content provider for contact management. As I have learnt via content providers, I can query only table at a time via URIs, there is no way (at least, I didn't find) to join two tables and then get a query resolved.
And I had read, that databases are only visible to the applications that originally created them, so do my app would be able to access these databases ?
I am just a hobby developer for my own phone. I have no intention to make an app that directly uses the databases. I can pull the database from device, analyse them via sqlite. It is not that I am up against the content providers or they don't suit my need write now, it is just that it can be done or not ?
Any opinions ?
Content Providers give you a lot more than just database access. Being able to use Loaders to automatically reload your data (and update your UI) when the underlying data changes can vastly simplify your applications.
The goal of Content Providers is more to create a single, controlled layer for accessing your data. There is nothing stopping you from creating a custom URI that joins multiple tables together and returns the resulting joined result.

Android Content Provider and Many-to-Many DB relationship

I have a simple Notes app which is similar in functionality to the Android NotePad sample. One addition is that every note can have Tags. A Note can have several Tags and a Tag can belong to several Notes - thus making this a many-to-many relationship.
I have completed the DB Design using Foreign Keys and a Mapping Table. Now, I wish my app to plug into the Android Search Framework, which necessitates the use of a ContentProvider to expose my data.
Are there any best practices to be followed for this scenario? I did find a few related questions on SO, but most of them dealt with one-to-many relationships (this one for example). I did conclude from these questions that it is best to have a single ContentProvider per DB, and then use the Matcher concept to resolve multiple tables within the DB. That still leaves other questions open.
Given a Note ID, I would like to return all the tags associated with that Note. How do I go about setting up the ContentUri for such a case? Neither of "content://myexample/note/#" and "content://myexample/tag/#" would serve the purpose.
None of the 6 ContentProvider methods which I override would suit such a purpose, would they? I can of course, introduce a new method, but that would not be understood by the consumers of my ContentProvider.
Thanks in advance for your suggestions.
Now I find some cool stuff about the many-to-many entry relationship in Android ContentProvider. The answer comes from the Google I/O 2011 Offcial Android Client source code.For example, in the Google I/O app, there is a entry called Session and another entry is Speaker. One Session maybe have several Speaker and one Speaker will attend several Session.
So,let's have a look about the google's solution:
https://github.com/google/iosched/blob/2011/android/src/com/google/android/apps/iosched/provider/ScheduleProvider.java
https://github.com/google/iosched/blob/2011/android/src/com/google/android/apps/iosched/provider/ScheduleContract.java
https://github.com/google/iosched/blob/2011/android/src/com/google/android/apps/iosched/provider/ScheduleDatabase.java
Maybe this answer will help you guys.
Yes you need to implement it using ContentProvider when you want to implement search.
You can use your existing content provider to retrieve the tags associated with a note.
you can define another URL say in the form "content://myexample/note/tag/#" to get all the tags associated with a particular node.
You will need to add another URI that has to be matched in your URI matcher.
say something like GET_NOTE_TAGS = 3;
In the getType method of your ContentProvider, return the appropriate mime type. I would guess that this wil be the same as the mime type for tags, since you are returning the same tags.
Then in your query/update/delete/insert methods parse the incoming URI to match it with "content://myexample/note/tag/#". Then implement your query appropriately on your database or your content and return the tags that you need to return.
The "content://myexample/note/tag/#" schema is just an example and you can use multiple URIs within the same ContentProvider.
You also stated that you have to join tables. that can be done using db.query and if it becomes complicated you may use rawqueries, to get the data as you need from the database.

Categories

Resources