Should all data be exposed via ContentProviders? - android

So I come mostly from a web background and I'm trying to learn the architecture of android apps. Trying to grasp a proper understanding of content providers.
What I think I'm understanding is that content providers are pretty much your middle man between the activity/services and your data (DAO of sort). I also think that content provider are also to provide other applications access to your data (almost like a web service?)
What I'm not really getting is, what if you did not need this data exposed to other applications? Do I need to bother with content providers and all the uri defining etc? If not, is there a name for this ... pattern? (or lack of) Or am I better off just using ContentProviders and just accept the added benefit of exposing this data to other apps?
I know eventually I will want to sync data between the app and a external database. I saw a google IO presentation supporting the pattern of using a content provider for RESTful communication. But for the time being, I'm just trying to get comfortable with basic static data. Then hopefully swap it out to data from a REST service down the line once I get it.
Hope I'm not completely off here. Thanks.

Although it says that content providers are nice for sharing content they also give you a couple of other things free!
The best thing about content providers is that the system handles the threading issues for you :) when I ported my app over to Honeycomb i got lots of database errors (mind you ones that couldn't previously exist in gingerbread) I wasn't handling the access on different threads properly.
I quickly put a content provider on top of my database and well.. never looked back in that regards, it seems much easier once you've setup your content provider the code throughout the rest of the app is much nicer and you don't have to worry about concurrency

As written in the specs, and as you mentioned :
Content providers store and retrieve data and make it accessible to all applications. They're the only way to share data across applications; there's no common storage area that all Android packages can access.
So if the data you are storing should not be accessible by other applications there is no need to bother with ContentProviders. As you can see on Android Data Storage there are several ways in which you could store your data.
My opinion is that in your case, for usage of REST Services, and data that is not to be shared with other application you should use SQLiteDatabase. You can find a good example SQLiteDatabase example here.

Related

Do I really need Content Provider in my application

I am creating app that should have offline mode, so previously downloaded data should stored somewhere, the most common way is to store data in SQLite database.
Mostly SQLite database is used with Content Provider in android. I have clear understanding what is the purpose of content provider (to share data between different apps), but in my case application will never need to share the data with other apps in the system.
Content provider has the similar interface as HTTP request (GET,POST,PUT,DELETE).
My idea is to create facade class which can be used like this getAllLatestNews(); firstly it will try to get latest data from the internet, if it fails - data from database will be used and if request is successful it also will save retrieved data to the database. This class will be facade for separating different layers of application (not to make requests from activities directly).
But now I am a little bit puzzled deciding whenever I need Content Provider or not. I can use SQLiteOpenHelper classes to retrieve and save data to the database or even use ORM library to do this.
At first I wanted to implement REST API Pattern B by Virgil Dobjanschi. But now I am not sure about this, maybe it would be better to create facade for Robospice(in my case, network request in the service) requests and do persistence there ?
Please share you thoughts about this topic, I would be grateful for any help.
EDIT
I asked this question because I feel that it is not good practice to make requests directly from activities even if they are made in service under the hood, I want to separate different layers of my application in order to make it more flexible and maintainable.
As you don't intend to share your data, i would say that implementing a ContentProvider is overkill.
Personally im a huge fan of ORM libraries (Currently i use SugarOrm in several projects), so i would go down that road.
Then at app startup, you check whether or not you have an active internet connection, and based on that you either get the latest information online, or retrieve older information from the database.
To seperate the logic a bit, i would most likely implement the getting of online information in a service, which would then store it in the database and broadcast to the activity that the information is now available, and then the activity could retrieve the information from the newly updated database.
Content Providers are absolutely for sharing data between applications and are of no use without this purpose.
If you want to use those data only in your app privately, you could use SQLite databases. Also there other objects available:
Shared Preferences
Files
Content provider has the similar interface as HTTP request (GET,POST,PUT,DELETE)
I don't think so. It's more like to SQL language.

How to share data across a group of applications in Android

Consider the following scenario. A company releases many apps. And they want some data to be shared across all these apps. Any of these app can create or read these data, just like a common database. So company decided to create an android library which does this purpose. I searched for a few days and my analysis are given below.
SharedPreferences- not recommended and is deprecated. It does not serve the purpose too. All other apps need to know the package name of the app that created the data to create PackageContext. Here this is impractical as any app can create/update/read data and it is not possible to say who is who.
ContentProviders - This does not work for me. The reason being ContentProviders has to be present in each app. There can not be 2 content providers with same name in a device. In addition to that, ContentProviders are basically meant for one app creates data and other apps subscribe to it using Content_Uri.
Network connection - We do not want to do store data in any server.
External storage - This is the only option remaining. Should I go for this?
And interestingly the data has to be secured as well which is nowhere supported in any of the storage options.
Note: For iOS, we use keychain to implement the same functionality
Understanding the problem on Android
Ironically, due to the intense sandboxing on iOS, there's a straightforward way to make this happen there (App Groups) provided the apps that need to share data are all by the same developer. Likely because Android is more flexible on security, this actually ends up being a more difficult problem there. The Android team have so far not seen fit to provide a convenient and secure way to specifically share this kind of data because there's a low security workaround.
That said, there are plenty of ways to share data between applications without involving the cloud.
SharedPreferences
The original question states that SharedPreferences are deprecated. This isn't true, as far as I can tell, however the MODE_WORLD_READABLE and MODE_WORLD_WRITABLE contexts are deprecated which makes this approach subject to not working in the future. The mode has been deprecated for quite some time, though - since Android 4.2 (2012). There's no threat in the current Android docs to suggest they're actually phasing it out (sometimes deprecation just means "this isn't a great idea" not "this is going to be removed"). I suspect the lack of a more secure OS-level direct alternative for application data sharing at the settings level is probably the reason for preserving it in a state of deprecation for the last 5 years.
File Access
The simplest and most common way I'm aware of to implement data sharing between applications on Android is to simply request file access on the device and create a shared location on external storage for this data. (Don't be confused by the "external storage" designation - this is just how Android refers to shared data. It doesn't necessarily refer to an SD card.) You give the file a unique name, and you store it somewhere that your apps know where to look for it. Best way to get that path is something like:
Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOCUMENTS)
The obvious problem with this is security. While not deprecated by the OS, it introduces the same problem that the Android docs list as the reason for deprecating MODE_WORLD_* - it's inherently insecure and opens up potential exploits in your application.
You're placing your information where everything has ready access to
it.
You're asking for permissions that your app may not otherwise need.
You're reading files that you can't verify the origin of.
If your application isn't handling any sensitive data, maybe this doesn't matter to you (it might to your users). If you're planning to read data from those files, you should ensure you're providing maximum validation for that data before parsing. Check the size of the file, validate the formatting, etc.
Creating your own service
You could always create a Service or an IntentService. (There are subtle differences between the two, but IntentService is a subclass of Service that runs in a Worker thread while Service interrupts the main thread. IntentService also implements Intent support which provides the most straightforward interapplication communication on Android).
This service has its own private storage, for which it has full read/write access, but nothing else does. This service then provides an interface to receive Intents from other apps, and to return results (as Intents) to those apps. This is an extremely friendly way to implement interapplication data while maximizing data privacy and security of that data. If outlying apps mostly need to request very basic information from a central application, this is your entry-level option.
Implementing a BroadcastReceiver
Along the same lines is the BroadcastReceiver class. Depending on what sort of data you're intending to share between applications, and how familiar those applications may be with your specific approach, this another possibility. Again, you'll be managing the shared data under one application's private storage. Communication is done by Intents, so it's similar to an IntentService - except that applications may communicate with a BroadcastReceiver by issuing systemwide events (that is, they don't need to be explicitly communicating with your app or service - they're shouting out the world for a piece of info, and expecting an answer.)
Creating a ContentProvider
The Original Post seems to misunderstand what a ContentProvider is and how it works. You have to think of this type of item like you would a cloud solution - even though it's local to your device. Every app doesn't need a ContentProvider - they all need to communicate with a ContentProvider, and that ContentProvider maintains, updates and returns data.
This is probably the most "Android-y" solution for this particular usecase and offers the greatest expandability. You implement an independent process that handles data storage and responds to other applications. It is, however, a more evolved solution - and as such may be more a more challenging endeavor. If you need a real database service, rather than a fairly simple request/response type service, ContentProvider seems to be the best choice.
Seems like what you need is shared user id.
It allows application sandbox to be shared across multiple android applications if they are all signed by the same signature.
But, watch out for gotchas!
Yes. Probably using same path in external storage for all applications is the best way. A common portion of code could be used to know whether database there exists or not and therefore open or create new one. For security I recommend always to use 'user' and 'password' when connecting to DB, but if you think it is not sufficient I advise you to see this: http://www.hwaci.com/sw/sqlite/see.html

Android ContentProvider and Google IO Rest Talk

To all,
If you watch the Google IO session on building Android REST apps they are suggesting in all three design patterns to use Content Providers regardless if you need to share data or not.
If you look at the Content Provider class doc at http://developer.android.com/reference/android/content/ContentProvider.html they say you only need to use a content provider if you plan on sharing your data with other applications.
My application does NOT need to share any data with other applications so is using a Content provider overkill? And if so why does the Google IO REST video imply that it should be used in all scenarios?
-= Update =-
Talks are here https://dl.google.com/googleio/2010/android-developing-RESTful-android-apps.pdf.
There's no real right or wrong answer to this question but I'm strongly in the use a content provider camp for the reasons below.
You get a well-defined, easy-to-use CRUD interface for your data. Once you've written a Contract and your Provider methods, it's just a couple of lines to start retrieving data. When you come to work on the project later, or you hire another developer, you'll be up to speed in minutes.
Lots of classes in the Android framework are designed to work with content providers. In particular, CursorLoaders are brilliant, and you'll have to do a fair amount of work to emulate their functionality on your own. Good luck with managing the cursor lifecycle within an activity, in addition to writing all of your own data retrieval code and asynchronous tasks. There are various nuances and things to take care of. This will take a while.
Updating or inserting rows often? It's pretty easy to notify ListViews and other Cursor consumers of changes via the ContentProvider. If you're not using a ContentProvider, you'll have to write your own Observers and manage it yourself.
Want to integrate the Quick Search Box, or apply some powerful filtering to a ListView? Again, it's simple if you're using Cursors and ContentProviders, and a whole load of work if you're not.
If, in future, you decide to open up your data to other apps, you'll end up writing a ContentProvider anyway. Remember, you can still use ContentProviders without allowing other apps to modify your data.
I could (and may) expand on this post further but hopefully you get the idea. Google use providers in great apps like iosched for a reason.
In my experience, implementing a Content Provider can be a lot more work then simply working with a database directly. One of the reasons Google could say that an application should use a content provider could be because they believe in expansion. An app that implements a Content Provider would have an easy time expanding its data to other apps.
Because it is a REST talk, another reason could be because Google is starting to focus on a lot of cloud storage ideas. If you can implement a Content Provider, you can change your data retrieval functionality while still keeping a lot of your existing code. A Content Provider generally separates the data retrieval functionality from the actual data, leaving it much more flexible. If you wanted to switch your data to the cloud, it would be much easier having implemented a Content Provider within your application.
In my opinion though, most applications don't need to query the large amounts of data that make cloud storage desirable. It depends on the application, but I think you'll be OK avoiding a content provider if your data is meant to be kept in-house.

When to use a Content Provider

I understand that Content Providers are made to allow publicly sharing data between applications. However, I'm wondering if anyone has thoughts about making a Content Provider to use just within your own app. Would there be any advantages to doing this? Any disadvantages?
In the past I've just implemented the SQliteOpenHelper to access data from my database, but I'm considering creating a Content Provider. I feel like the URI approach to requesting data is clear and concise. On the other hand, will using a Content Provider just for my application be redundant ( since within it I will have a SQliteOpenHelper class ) and more work than I need?
I would argue it is definitely a good idea to use a ContentProvider even if you don't intend to make it public.
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.
Also, there is always the chance that you might want to expose your data in the future. If you don't use a ContentProvider up front, it will be much harder to retrofit it in at a later date.
Then, there's the other parts of the Android where ContentProvider's are required/recommended such as when using SyncAdapters and if you want an App Widget that involves data access for instance.
In summary, there is very little overhead involved in writing a ContentProvider up front (once you have learned the API which is a good idea anyway) so it makes sense to do so, even for private data.
If you are not planning to share data, don't think about Content Providers. They are powerful but hard to write and it will be just silly to implement them if you are going to use them internally.
However, I'm wondering if anyone has thoughts about making a Content Provider to use just within your own app.
Of course... for instance, for an old TODO list app I wrote, I had to write a content provider to allow other apps retrieve and access the tasks states. It was part of the requirements, but more than that it made sense and made the app nicer.
Take a look at the MOTODEV Studio for Eclipse. It is a development environment that extends Eclipse. They have a tool where you can automatically generate a content provider for a database. If a content provider makes it easier to access your data and it doesn't have a significant impact on performance go ahead and use it. In most scenarios this will be the case.
In short,Content Providers helps in managing your data effectively. I would suggest to use them for the following reasons.
It acts as an abstraction layer between your UI and database. You can implement data validation in ContentProviders to validate the data entered by the user. It also lets you to modify the structure of the database without touching the UI and other parts.
They play along nicely with other android framework classes like SyncAdapter. For eg., you can automatically refresh a list, when a value in a database changes using ContentProviders along with CursorLoader. Without ContentProviders you have to implement a lot of functionalities like these on your own.
We can safely expose our private data to other apps. Using ContentProviders will allow us to share our data easily and safely with other apps.
So even if you don't need any of these functionalities now, you might need them in future and its good to go the extra mile and implement them right now.
I agree ContentProviders are a little difficult to grasp but they are definitely helpful, even if you want to use them internally for you own app. The best thing about it is that you can customize the contentproviders for suitable URIs.
Here's a scenario where you may have 5 tables in your database, but you need to join a few of them in certain orders before using them. And make a content URI for each of these joins. You could then each use these URIs as a table :)
I suggest you go ahead with Content Provider, you'll be amazed to see how powerful it is.
In my view point, the content-provider comes with plenty of advantages leave alone just sharing data with other apps. If you need to synchronize with the server using a Sync-Adapter, use google cloud messaging, auto update the UI when the underlying data in the DB changes using Loaders, implement search, use widgets... then the content provider is for you.
I prefer you follow the guideline on because one day you may need to implement some of the above features attached to the content-provider
By the way, you can quickly build you database and CP in less than 5 minutes using content provider generator
As said in documentation:
Creating a Content provider
You don't need a provider to use an SQLite database if the use is
entirely within your own application.
So why bother developing this overhead? You want easier and faster development, right? So one layer of abstraction (SQLiteOpenHelper descendent) is enough.
See Occam's Razor
Do not make an entities without very good reason.
Using a Content Provider can help in an additional level of abstraction - Putting it within your own application make add a significant development time to your project. However if you are using it to share data, application settings or configurations across multiple applications then the Content Provider is your choice.
Watch your security levels and I would recommend using SQLcipher to encrypt data-at-reset (DAR) if your Content Provider is writing to SQLite. (I've used a content provider in a few solutions and provided the ability to take a live "snap shot" of the operational values for debugging and testing.)
Do not use content provider if do not wish to share data with other apps. Use simple sqlitedatabase to perform database operations. Be careful while using content providers for storing confidential data because your confidential information may be accessed by other apps

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