Android Content Provider and Many-to-Many DB relationship - android

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.

Related

Where do application logic and constraints go when creating ContentProviders?

I'm starting to learn Android development, and also have been trying to follow the DDD design patterns. One thing that has me confused is where application logic goes with respect to ContentProviders.
ContentProviders look a lot like repositories to me, but a lot of times I don't want to expose my repositories directly. There may be some additional application logic inside a Service which the repositories/database.
Most of the examples of ContentProviders I find show them accessing the database directly. Is it wrong to have a Service or Application object in between the ContentProviders and database?
For example I'm trying to create a personal finance/budget app (e.g Mint/Quicken etc..). I'm going to have a database of transactions and a corresponding TransactionProvider. In most cases transactions are independent from one another. Yet if two transactions are marked as part of the same "Transfer" there there will be some fields that I will want to keep in sync between the two transactions. If someone changes the category or amount of one transaction, I want to make sure the same values are updated for the transaction for the other account of the transfer.
A ContentProvider can execute arbitrary code on its insert(), update(), delete() and query() methods. They are not necessarily mapped one-to-one with the corresponding database operations, and neither do the structure definitions (i.e. fields) themselves. You could, for example:
Update more than one table when you insert, update or delete.
Keep normalized tables in SQLite, but present a non-normalized interface for querying.
Not store data in a database at all (for example to expose/manipulate the files available in your application's private storage).
&c.
So you can, indeed, include whatever business logic you want in the "backend" of the ContentProvider. In your case that would mean updating associated records to keep them in sync.
Just to clarify, since you're starting Android development, it's not necessary to build a ContentProvider if you just want to store data in SQLite -- you can use SQLiteDatabase directly for that. A ContentProvider is generally to expose your own data to other applications, or for specialized cases such as search suggestions.
From Creating a Content Provider:
Decide if you need a content provider. You need to build a content
provider if you want to provide one or more of the following features:
You want to offer complex data or files to other applications.
You want to allow users to copy complex data from your app into other apps.
You want to provide custom search suggestions using the search framework.
You don't need a provider to use an SQLite database if the use is
entirely within your own application.
If you're building a financial data app, you probably don't need one. Do you want other applications to be able to access that data?

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.

How do REST URIs work internally?

I'm trying to create a REST API to interact with a MySQL database. I want to use this API to access the database from an Android or iOS device without (obviously) exposing the database directly through the application. But I'm having problems wrapping my head around a key aspect about REST and the implementation of an API designed on its principles.
I understand the concepts of REST from the theory stand point. What I've been struggling for days trying to grasp is how a REST URI maps to something located on a database server.
If I make a GET request to a server for a resource with a given URI, say http://www.example.com/resource, internally, where does this go to on the server? The way I understand it, is that it goes to the root directory, then to the "resource" directory. From there it returns all the files within that "resource" directory. I'm simply confused because the resource is located on the database server and not the server where the API is being called from. Does the resource path/hierarchy represent actual directories on the server or is it an abstraction of the resource? If the latter, then what do I do with that abstracted resource name to make it map to a table or row in a database? It's been frustrating not being able to find concrete implementation examples of this where I can easily understand how this URI path works internally.
You can use a framework to do a lot of the work for you, but what happens under the hood is no magic. In some way, the URIs map to some database tables. They don't refer to a certain directory structure, but try to explain a hierarchical relationship between the resources.
For example, let's say that we're modelling a university. The elements in the database are stored in one of two tables, either Faculties or Courses. The Faculties table consists of rows describing the Faculty of Law, Faculty of Medicine and so on. It has a unique faculty_id column and then columns to describe whatever we need. The Courses table has a unique course_id column and a foreign key faculty_id column, to tell which faculty the course belongs to.
A RESTful way of designing this API might be
/faculties to get a list of all faculties, retrieved with SELECT * FROM Faculties
/faculties/2 to get the information about a certain faculty, retrieved with SELECT * FROM Faculties WHERE faculty_id=2
/faculties/2/courses to get all the courses belonging to a certain faculty, retrieved with SELECT * FROM Courses WHERE faculty_id=2
/faculties/2/courses/15 to retrieve a certain course, if it indeed belongs to faculty 2, retrieved with SELECT * FROM Courses WHERE faculty_id=2 AND course_id=15
The exact implementation of this depends on the programming language (and possibly framework) that you choose, but at some point you need to make choices about how you should be able to query the database. This is not obvious. You need to plan it carefully for it to make sense!
The result from the database will of course have to be encoded in some way, typically XML or JSON (but other representations are just as fine, although maybe not as common).
Apart from this, you should also make sure to implement the four verbs correctly so that they match the SQL commands (GET=SELECT, POST=INSERT, PUT=UPDATE, DELETE=DELETE), handle encoding negotiation correctly, return proper HTTP response codes and all the other things that are expected of a RESTful API.
As a final piece of advice: If you do this neatly, it'll become so much easier for you to design your mobile apps. I really can't stress this enough. For example, if you on a POST request return the full entry as it now looks in the database, you can immediately store it on the phone with the correct ID, and you can use the same code for rendering the content as you would if it had been downloaded using a GET request. Also, you won't trick the user by updating prematurely, before you know whether that request was successful (mobile phones lose connection a lot).
EDIT: To answer your question in the comments: Creating an API can be seen as a form of art, and should probably not involve any coding in the design stage. The API should be meaningful and not rely on a particular implementation (i.e. a different database choice shouldn't affect your API). Your next task will be to create ties between the human-readable structure of the API and your database (regardless of whether it's relational or something else). So yes, you will need to do some translation, but I don't see how the query string would help you. The typical structure is api.my.website/collection/element/collection/element. Queries can be used for filtering. You could for example write example.com/resource?since=2012-06-01 to retrieve a subset of the elements from your 'resource' collection, but the meaning of this particular query is to retrieve something you couldn't express with an unique ID.
The way I understand it, you think that incoming requests must always go to separate files based on the way PHP and HTTP servers work. This is not the case. You can configure your web server to route every request to a single PHP file and then parse $_SERVER['REQUEST_URI']. Depending on your choice of HTTP server your mileage might vary, but this is essentially what you want to do.
By googling I found a list of frameworks for PHP but I don't know any of them. There are others, though, and I also recently heard someone mention Apify, although I can't tell you much about that either. PHP is probably one more the more common choices for implementing an API. cURL, however, is a library/tool that's only designed to connect to other websites, as far as I know. You can certainly use the command line version of it to debug your API, but I don't think you'll have much use for it on the server side.
I think you should start with what framework you want to built the REST application from. Rails, RestEasy for java, Codeigniter, all have the basis for good REST routing capabilities.
This includes abstracting URL's from the underlining resource either from database or even business processes. They accomplish this using URL mapping, or creating a Facade for abstractions.
Generally REST does not really differ from tradational GET/PUT/POST with query parameters. Infact Apache URL rewrites usually are used to support REST style routing. I recommend you should pick up one of the frameworks and study how they implement this functions. Rails i thing has significant strength among other frameworks.

problem to understand content provider

dear i am confused the use of content provider in android applications.i go through various sides and read it but i am still confused about content provider ..can any one explain it in some simple way ,how to use it?
Content providers store and retrieve data and make it accessible to all applications....whats that means?
can it means any package name or in same pakage name...
if i am making another app of diffrent package name then that c.p. is available also in that package?
OK, first of all, a content provider will be used if and only if you want to use the same data through several applications. You can still use it if you want to implement it in your application.
Now, by definition a ContentProvider "Content providers manage access to a structured set of data. They encapsulate the data, and provide mechanisms for defining data security." (According to Android Developer Guides)
So in other words, it's like a new layer of abstraction that you are adding to your data, assigning a new man-in-the-middle that will request everything you ask it to do (read, write, update your database, files, or webservices). And this man-in-the-middle is not only available for you, it's also available for other apps if you set the tag android:exported to true in the <provider> in your manifest file.
A ContentProvider needs you to implement:
A contract: Basically a class with public static variables with your tables names and the fields of info for those tables.
A data model: Normally a database in SQLite but you can implement it also with third party libraries like SugarORM, GreenDao, Retrofit, local files, etc).
Your custom ContentProvider: Extend ContentProvider and inside here set the calls to your data model.
This is a good tutorial on how to make your own ContentProvider:
http://www.grokkingandroid.com/android-tutorial-writing-your-own-content-provider/
There are also a few libraries that will help you create a ContentProvider automatically (I find it amazing because it takes you like 10 min to set up everything, instead of creating your own ContentProvider from scratch which could take you days).
My personal favorite is Schematic:
https://github.com/SimonVT/schematic
I hope it helps. Kind regards!
how to use it?
you actually don't use it directly, but via the content resolver (which will, according to the URI you give it, query the right ContentProvider) :
getContentResolver().query("content://com.myapp.myprovider/data/", ...);
will find your content provider if that one is registered to handle URIs that match "content://com.myapp.myprovider/data/"
if i am making another app of diffrent
package name then that c.p. is
available also in that package?
If you decide to publish the content provider, it is available outside of your application (this is a setting in the manifest).
what is the major benifit of using c.p.?
It is a common design pattern in Android to offer access to data. Major benefit is that you can abstract access to your data and decide whether to open it to other applications or not. For instance, without content providers, you could not access the media stored on the phone or the contacts of the phone.
Since a package is meant as a unique identifier for an application, how can you create an app with the same package name? If this was your question, I think I've answered it. If you don't understand something else - feel free to ask. Good luck!
P.S. Consider accepting some answers, your accept ratio is low.

Exact Difference between "Content-Provider" and "SQLite Database"

i have done SQLite database programming for Android, but i dont know anything about
Content-Provider except this: "As i have referred Android Developer page , Android SDK explained about "Content-provider" as it is used to store and retrieve data."
But then,
What is the exact difference between "Content-Provider" and "SQLite Database"?
Which is best to store data, when ?
Any example or helps !!
I found one major difference, as follows:
Storing your data in a database is one good way to persist your data, but there's a caveat in Android-databases created in Android are visible only to the application that created them. That is to say, a SQLite database created on Android by one application is usable only by that application, not by other applications.
So, if you need to share data between applications, you need to use the content provider model as recommended in Android. This article presents the basics of content providers and how you can implement one.
I found this article at this link
Really nice information provided.
What is the exact difference between
"Content-Provider" and "SQLite
Database"?
ContentProvider is a facade -- an API you can implement that exposes databases to other processes. It can be implemented in a way where the data is stored in a SQLite database, but it does not have to be.
Which is best to store data, when ?
That is impossible to answer in the abstract. Generally speaking, unless something is requiring you to use a ContentProvider, just use a database.
I have made many good apps with thousands of users using them which simply used SQLite methods. But that was a while ago and I had to manually write lots of code which now can easily be taken care of by ContentProvider. Back then I was not in favour of using Content Providers because it seemed to only add complexity in the code.
However for last couple of years, as Android has evolved, I have moved to ContentProvider as it saves time and allows you do to more. I now use it extensively. Once you have a Content Provider class written, your life becomes much easier. With ContentProvider I can much easily deal with Cursor Loaders, Loader Callbacks and Bulk Inserts for which I had to write everything manually in the past and still it didn't work as efficiently. Especially when updating the list view, which is now automatically updated thanks to just one notifychange() method. This means now I don't have to type my own listeners and manually updating the content in list views and adapters. Plus, I don't need to worry about opening and closing of databases or worry about memory leaks. That's all handled by the Content Provider. The only problem which once in a while I face is that that you cannot do some complex queries in ContentProviders. In this case you can still use raw queries and use the old fashioned manual interaction with sqlite.
If you have previously written your own DbAdapter, Helper and Observer, you can safely carry them on to your new apps without spending time to convert everything to ContentProvider. But based on my experience, I would highly recommend to move to ContentProvider. It'll take some time to get used to it, but once you have got experience with it, you'll stay with it.
UPDATE 2017
I have now switched to Realm, a much better way to use databases on any platform. Spend a few hours learning it, and save countless hours in your app development career.
1. Content Providers are not Thread Safe
By default content providers are not thread safe. If you have multiple threads using a content provider you can see many different exceptions being thrown and other data inconsistencies. The easiest way to fix this is to use the synchronized keyword on each of the public methods exposed by the content provider.
In this way only one thread at a time can access these methods.
2. Play nice when doing lots of writes
I have the need in the new Serval Maps application to import data from binary files into the database used internally by the application. In order to do this and play nice with the rest of the application it is best to:
Spawn a new thread to undertake the import so other threads are not adversely impacted, in particularly the thread in charge of updating the UI; and
Pause briefly at the end of the each import to give other threads which need to use the synchronized methods more of a chance.
3. Content providers force you to think laterally sometimes
The way that content providers in Android work is to provide a layer of abstraction between the rest of your code and the underlying database. This is mainly due to the fact, as far as I can tell, that content providers can access data from places other than databases.
This means that you can’t execute raw SQL queries on the underlying database and you need to specify the various components of a SQL query using variables passed to the various methods such as the query method. If you have a task that doesn’t fit into the way that SQL is handled by a content provider you have two options:
Think laterally about the query, maybe you can get the data that you need by alternative queries and accessing the results from the cursor; and
Use a URI for accessing the data normally and a special URI that is matched to a specific query for those tasks that don’t have alternatives.
Content Providers are used when you want to share your data across applications.
If you have a database attached with an application and you want another application to use some data, you can implement a content provider that exposes the data
The main difference is: when your app needs to share information to another apps, use Content-Provider. SQLite only storage data for the app who creates it
I read this answer while looking for same doubt, so thought of sharing it.
it states -
It's good practice to provide the extra level of abstraction over your data to make it easier to change internally. What if you decide to change the underlying database structure at a later time? If you use a ContentProvider you can contain all the structural changes within it, where as if you don't use one, you are forced to change all areas of the code that are affected by the structural changes. Besides, it's nice to be able to re-use the same standard API for accessing data rather than littering your code with low-level access to the database.
So, using a content provider would be a good idea.
Think of advanced Content Management Systems. Each object (page, image, news article, event item, etc.) has a content, an address, user permissions, and ways to interact with it from different parts of the system. Content Providers do that for Android. You can now share files or images you may have stored in your application. You can also create custom sharable objects, like bussiness contacts, editable notes, etc. And specify security and the default application to deal with such object when you open them from any other application.
One difference is that Content Providers have platform support for Content Observers. Your going to need to implement your own Observable pattern for a SQLite database.
How to automatically re-query with LoaderManager
ContentObserver for SQLite?

Categories

Resources