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!
Related
I am developing an application, which can query content providers of other installed applications. I got the provider name using GET_PROVIDERS, but how do i get the uri with which i can actually query? Kindly help.
Thanks in advance.
how do i get the uri with which i can actually query?
Contact the developers of the app and ask them.
There is no way to determine, automatically, what valid paths might be for the Uri. So, while you know the scheme and a candidate authority from PackageManager, everything else from there is non-discoverable. Similarly, you have no idea whether the ContentProvider in question is providing streams, database records, or both.
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.
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.
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().