I am having trouble understanding content providers in Android.
Do you use intents to call content providers as well as managed queries?
Also, an activity has an intent filter. The intent filter has a element which has a mimeType attribute. How does Android know which content provider this mimetype is referring to?
The tag in the manifest just lists an authority but not the full content_uri. Further, the content_uri is typically defined in an encapsulated class that seems to only consist of constants but no methods, so I don't see how that links over to the content provider class.
Thanks
I answered some of these questions earlier today on android-developers. Let me try it again here.
Do you use intents to call content
providers as well as managed queries?
No.
How does Android know which content
provider this mimetype is referring
to?
It asks the ContentProvider, via getType(), to provide the MIME type for the Uri that is in the Intent.
The tag in the manifest just lists an
authority but not the full
content_uri.
That is all that is needed for Android to find the right ContentProvider on which to call getType().
Related
As I understand, in Android, the implementation for a content provider does not and possibly should not be concerned with which application is requesting the data. As long as the calling application has the required permission to access the data the implementation should just return data based on what URI is being requested. However, I am trying something different in my content provider and need to find out which application is calling the provider before responding to the query for data. Is there a way for my content provider to find this out? Any help will be much appreciated.
Assuming you are only interested in finding out whether it is your application accessing the provider or a third-party application accessing the provider, you can call ContentProvider.getCallingPackage() and see if the package name returned matches your application's package name.
EDIT: For API Level 18 and before, there is one workaround method that I know. It is a workaround so it's not ideal, but it works: append some extra piece of data to the URI to identify your application.
So for example, if a URI for your provider would normally be content://com.example.app/table1, your app would use the URI content://com.example.app/table1/identifier. You would add both URI patterns to your UriMatcher using a different code for each pattern. Make the URI without the identifier publicly available through your contract class, but keep the identifier private. Third-parties will construct the URI according to what is publicly available in your contract class, and therefore, will not include the identifier in the URI. When you construct the URI, include the identifier. So both URIs will point to the same data, but you can differentiate between your own app and third-party apps based on which code the matcher returns from match(Uri uri). It will not interfere with the ContentResolver either since the resolver only examines the authority portion of the URI. Again, this assumes you only care about distinguishing calls from your app.
What is the reason for content provider authorities?
How/why do I want to use them other than I HAVE to declare them in the manifest?
I've tried to do my homework on this question and cannot find a decent, cohesive discussion on this topic.
Here is the best I could find (in additi on to the four books on Android development I own):
https://stackoverflow.com/search?q=content+provider+authority
Content Providers, Authority and and URI matching
Get a list of available Content Providers
http://developer.android.com/guide/topics/manifest/provider-element.html
http://developer.android.com/guide/topics/providers/content-provider-creating.html
The Authority is used to interact with a particular content provider, that means it must be unique. That's why is a good practice to declare it as your domain name (in reverse) plus the name of the package containing the provider, that way is less likely that other developer creates an app with a content provider declaring the same authority.
You declare it in the manifest so your app and other apps (if you let them) can manipulate
data through your content provider in the form of a uri:
content://authority-name/data-in-the-provider
It works similar to domains in http urls:
http://domain-name/data-in-the-site
I am also looking for explanation and to add to answer provided by ILovemyPoncho, I hit this particular answer and I quote:
and what exactly is android:authorities asking for?
A system wide unique identifier for your provider. Or better worldwide
unique. All providers are registered with the system and they need to
be unique or the second app that wants to use the same name can't be
installed.
You use that string in the end to communicate with your provider via
an Uri like
Uri uri = Uri.parse("content://" + "your.authoritiy.string")
Let's put it this way: There is an invisible hand that facilitates your request to your app's ContentProvider.
For example:
Uri uri = mContext.getContentResolver().insert(NotifireContentProvider2.NOTE_URI, values);
Basically, what you are saying here to the Android OS is insert data given the URI containing the authority you have defined in the XML. The OS will search for this particular content provider and send the request to it. You insert method on the ContentProvider will be called and you must match the URI to handle it accordingly.
Also, what if, you're content provider is so simplistic that others have similar authority as well. I haven't encountered those two problem I mentioned but I reckon it won't be pleasant.
Authority is there to make sure that the OS understand which provider will provide the data to the requesting app and to make sure that is the provider providing it.
I've read Android dev guide and notice that we can implement different classes for the content provider. So,
There are many content providers or just one content provider in one Android app?
How to properly implement different content provider classes like that?
Here is what I read from the dev guide:
You implement a provider as one or more classes in an Android
application
http://developer.android.com/guide/topics/providers/content-provider-creating.html
You can implement as many as you want, as you can see from the documentation here. To register a content provider, you need to add its corresponding <provider> tag in the Android Manifest.
In most cases, however, you won't need multiple content providers. One is usually enough, as it can handle multiple tables. You should only really need more than one if you want your app to provide public access to 2+ separate data entities.
You can use (provide as well as use) as many content providers per app as you need. They need different content URIs, of course.
In addition to the uses outlined in the document (your link) you can use content providers for other purposes as accessing data storage. The content URI can have parameters, so you can use a content provider similarly to a web service.
You can create as many content providers as you want. But do you need them al?
What content provider classes do you want to implement? If you read the page very good you should have seen that it contains links to two pages:
http://developer.android.com/guide/topics/providers/content-provider-basics.html - Content Provider Basics
http://developer.android.com/guide/topics/providers/content-provider-creating.html#ContentProvider - Implementing the ContentProvider Class
I suggest you first read those pages. Google is giving some more information about Content Providers, tutorials and examples:
http://android10.org/index.php/articlesdatastorage/252-content-providers-using-and-creating-them
http://thinkandroid.wordpress.com/2010/01/13/writing-your-own-contentprovider/
http://www.vogella.com/articles/AndroidSQLite/article.html
http://about-android.blogspot.com/2010/04/content-provider-example-1.html
There is no rule as such that you have to implement only one content provider per application. If your project demands, then you can do so.
If you want to implement multiple content providers in your application package, then make sure that authorities part of each content provider is unique, to route the incoming data requests to each content providers properly.
But having too many content providers can really confuse you and not required.
The only scenario that I see to have multiple content providers is, if you are having multiple databases in your application and you want to share all those databases with outside applications. Where you can use separate content provider for each database to share it with outside world.
Hope it helps.
I've been trying to work on a custom content provider and I have a few questions.
How is the Android framework using Authority property? Why is it required to declare it in the manifest, shouldn't the class name be enough?
Who/what process calls the getType() method in the ContentProvider implementation?
What is the need of the urimatcher? Should it be used if the underlying database has only a handful of tables?
You are required to declare it in the manifest because data access permissions are listed in the Market entry. I.E. "Has permission to read contact information".
getType() is called when you want to get the MIMETYPE of a column accessed by a ContentProvider. This is called when you use MyContentProvider.getType(myUri)
Hope this helps!
This is a deep magic question.
I understand that a call to a ContentResolver method takes a URI specific to the ContentProvider, but how does android actually make the association?
I am guessing that any URI matching the authority provided with the ContentProvider in the AndroidManifest.xml is involved.
Is the request sent to every provider containing that authority?
If I try to create providers whose authority prefixes another authority will that be a problem?
Is there a way to see if the ContentProvider is running? I'm thinking maybe a dummy response on the getType() method would indicate liveness.
Class ContentResolver maintains a mapping from Content Authorities to ContentProvider classes. The data for that mapping comes from the <provider> elements of the various installed applications' AndroidManifest.xml files. ContentResolver uses this mapping to identify which Provider class is the right one to use for a given URI that comes in. Think of ContentResolver as being sort of like DNS. It figures out which server (provider) is the right one to answer your query.
Only one ContentProvider will match, because contentAuthorities (the "domain name" part of the content: type uri) are required to be unique. They are not hierarchical. Treat them as a unique string which must exactly match. The reason they look hierarchical is to allow an easy way of guaranteeing uniqueness, akin to the way Java package names are ensured to be unique.
Per the 'Description:" section for the tag documentation:
The Android system identifies content
providers by the authority part of a
content: URI. For example, suppose
that the following URI is passed to
ContentResolver.query():
content://com.example.project.healthcareprovider/nurses/rn
The content: scheme identifies the
data as belonging to a content
provider and the authority
(com.example.project.healthcareprovider)
identifies the particular provider.
The authority therefore must be
unique. Typically, as in this example,
it's the fully qualified name of a
ContentProvider subclass. The path
part of a URI may be used by a content
provider to identify particular data
subsets, but those paths are not
declared in the manifest
As for what happens when you make a provider with a contentAuthority that's identical to another one... Well, stuff breaks. Specifically, it will refuse to install whichever package goes on second, saying:
WARN/PackageManager: Can't install because provider name com.xxx.Provider
(in package com.xxx) is already used by com.zzz
So.... Don't do that.
There is no way to see if the ContentProvider is running. It is started and stopped automatically by ContentResolver as needed. When you start making requests for a specific contentAuthority, the associated provider will be started if it isn't already running. It will be stopped automatically by ContentResolver, some time later once it has sat idle and it looks like it might not be needed for a while.