Is it possible (or recommended) to pass parameters to content providers via URIs in Android, similar to how web addresses use them? That is to say, can I use name/value pairs in content:// URIs?
For example, I have a search provider that can search based on names. I pass it a URI like this:
content://com.example.app/name/john
That would return anyone with "john" in their names, including John, Johnathon, Johnson, etc.
I want to have the option (but not requirement) to search by exact names and not find partial matches. I was thinking of doing something like this:
content://com.example.app/name/john?exact=true
That would tell the search provider to only return names that exactly match "John." But I haven't seen any other examples of parameters used like this within Android. Is there a better way? What am I missing here?
Thanks!
if you want to pass query parameters you can use the appendQueryParameter() method when constructing your URI
LoaderFactory.createCursorLoader(this,
MyProvider.MY_CONTENT_URI.buildUpon().appendQueryParameter(
MyProvider.MY_PARAM_NAME,
myParamValue).build(), projection, null,
null, null);
And then access the param value using the getQueryParameter()
String paramValue = uri.getQueryParameter(MyProvider.MY_PARAM_NAME);
No, as far as I have seen, any parameters get stripped from content provider urls (although I don't know why), I worked around this by adding parameters using a "/" and a certain prefix and parse them out manually, something like this:
content://com.example.app/name/john/paramexact/true
Related
I would like to access the content provider using URI, which is of the following form.
sUriMatcher.addURI("org.abcd.providers.contentprovider", "bookmarks", 1)
So, can I access it using the URI, "content://org.abcd.providers.contentprovider/bookmarks" ? What does the value "1" mean? How do I query the provider of this type, Thanks in advance.
The "1" is used internally in the ContentProvider. Its used to associate an URI with an number. Handy for using in a switch statement.
Why not using String matching? Well, an URI might have variable parts. For example "content://my.provider/bank/customer/2". The 2 is the Id of the customer. Or "content://my.provider/location/42/name". The variable part here is the 42. String matching goes out of control here. The UriMatcher on the other hand is able to match example 1 with addURI("my.provider", "bank/customer/#", 1) and example 2 with addURI("my.provider", "location/#/name",2). When we ask a configured UriMatcher to match a URI it returns the number associated with the matching URI.
But we are going out of track here. The number is not relevant to you as a consumer. You can query the provider with the context method 'getContentResilver().query(content://org.abcd.providers.contentprovider/bookmarks, /*other args */)'. See the documentation for more infos.
But you can only talk to the provider if its exported (nothing you can do about it) or it requires permissions that your application has. This includes no permissions at all.
To be RESTful, the URI to get the comments for a post, should be something like:
posts/#/comments
Where # is the post id that will change depending on which post your are interested in.
I want to apply some convention when designing the content URI of my content provider. The question is, how is the user of the content provider expected to construct such a URI in an elegant way?
A workable solution is :
//in PostProvider
public static URI CONTENTS_URI_POSTS = Uri.parse("content://" + AUTHORITY + "/posts");
public static String COMMENTS = "comments";
Then the user will use Uri.builder to combine CONTENTS_URI_POSTS + id + COMMENTS. However, this method exposes the details on how to construct a URI.
To hide the details, maybe I could add a method:
public static URI buildContentUriToGetPostComments(int post_id);
Any better idea? Thanks!
You could use different paths for posts and their comments:
content://<authority>/posts/#<post-id>
content://<authority>/comments/#<post-id>
This way you have an URI which looks more conventional and its simpler to handle in the content provider, you do not need to parse the URI but a standard UriMatcher will do.
Not to bring up something old, but I am having trouble implementing this one-to-many relationship as well... If I follow Stefans approach:
content://<authority>/comments/#<post-id>
What if I later want to add a URI to get a specific comment by id?
content://<authority>/comments/#<comment-id>
The above would create an identical match to the previous URI.
In my case, I tried to resolve this by using
content://<authority>/posts/comments/#<post-id>
However, this solution can cause problems. For example, if I want to load a cursor using both:
content://<authority>/comments/ (all comments)
content://<authority>/posts/comments/#<post-id> (comments by post)
and insert a comment using:
content://<authority>/comments
Not all users of the ContentProvider will be notified, as the URI pattern doesn't match.
To solve this, I make sure that my ContentProvider calls notifyChange with the appended ID to BOTH of the 'get all' URI AND the 'get by post id' URI... this is just one solution.
Any drawbacks to implementing it this way? In hindsight it would probably be easier to just rely on the user setting the foreign key in the selection string of the ContentProvider query... but like pierr I wanted to implement it as a single URI.
I have very basic understanding problem of Content types.
I went through lot of examples and text explaining the above term, but still have some basic understanding problem. Can some clarify me please.
In the android notepad example, and many others, it is mentioned vnd.android.cursor.dir/ resolves to a list of items in a directory and vnd.android.cursor.item/ refers to specific item in a directory.
Is this vnd.android.cursor.dir some standard constant defined by android. Where did this come from?, or can i change it like
vn.com.android.myexample.dir/
How is this even resolved and what is its purpose, why not use the full CONTENT_URI?
Sorry, i'm totally lost, and don't understand this.
Documentation: https://developer.android.com/guide/topics/providers/content-provider-basics#MIMETypeReference
The MIME types returned by ContentProvider.getType have two distinct parts:
type/subType
The type portion indicates the well known type that is returned for a given URI by the ContentProvider, as the query methods can only return Cursors the type should always be:
vnd.android.cursor.dir for when you expect the Cursor to contain
0 through infinity items
or
vnd.android.cursor.item for when you expect the Cursor to contain
1 item
The subType portion can be either a well known subtype or something unique to your application.
So when using a ContentProvider you can customize the second subType portion of the MIME type, but not the first portion. e.g a valid MIME type for your apps ContentProvider could be:
vnd.android.cursor.dir/vnd.myexample.whatever
The MIME type returned from a ContentProvider can be used by an Intent to determine which activity to launch to handle the data retrieved from a given URI.
Where did this come from?, or can I change it like vn.com.android.myexample.dir/
No, because "vnd" stands for vendor in MIME Registration trees, android in this case.
I really can’t get the meaning of mimeType. I know that it exists so that the getType method in ContentProvider knows what to match with it. But I’m still not sure what it means or how it’s used.
Any ContentProvider usually defines the type of data it handles (e.g. NotePadProvider handles a Notes data type defined in an inner class of NotePad). A MIME type is just a standardized way to define that data type by giving it a unique name. This allows the data type to be communicated to code that works with a ContentProvider in a standardized way.
It also helps a ContentProvider that handles several different types of data to keep things organized, e.g. a RailwayContentProvider might handle trains, stations and tickets and can use the MIME type to tell each one apart.
Why MIME types?
The use of MIME types is a natural consequence when you think about how a ContentProvider is accessed through URIs, i.e. something like an URL on the Internet. Just like on the Internet there are MIME types like text/html for web pages and image/jpeg for .jpg images, Android wants you to define a custom MIME type for any data type your ContentProvider handles.
An example custom MIME type
In the NotePad (linked above) class of the NotePad example project, you'll find:
public static final String CONTENT_TYPE = "vnd.android.cursor.dir/vnd.google.note";
This field defines a custom MIME type (recognizable by the type/subtype pattern).
Android suggests you use vnd.android.cursor.dir/... as the first part for any kind of "directory listing" (multiple items) and vnd.android.cursor.item/... as the first part for any kind of single item.
For the subtype, it's again suggested to start it with vnd. and then add something like your reverse domain name/package name, e.g. vnd.android.cursor.item/vnd.com.mydomain.myapp.mydata
To avoid all those vnd... strings in your code, there's also some constants in ContentResolver like CURSOR_DIR_BASE_TYPE and CURSOR_ITEM_BASE_TYPE.
Mimetype Multipurpose Internet Mail Extensions is tell you the description of the content
Text in character sets other than ASCII
Non-text attachments
Message bodies with multiple parts
Header information in non-ASCII character sets
and also whether is it Pdf/epub/html/text etc
If you mean mime type its to tell the receiving entity how to interpret a file. Just like you see .txt and know a file is a text file. This way you can serve a file with .anyExtension and have the browser still know it is a .txt
I am trying to create a content provider where the key contains forward slash "/". I searched about it for quite a while but there is no place/example illustrating it.
content://com.lily.provider/items/*
General example, which I understand:
content://com.lily.provider/items/ab
What I want to do: my key is a string with "/"
content://com.lily.provider/items/a/b
where a/b is the item id, which is in the same position as ab.
My question:
will content://com.lily.provider/items/a/b be matched to content://com.lily.provider/items/* ? why is that?
are there any work-around I could use to solve the problem
Will content://com.lily.provider/items/a/b be matched to content://com.lily.provider/items/* ? why is that?
Yes, it will match. The asterisk * means "match any characters, including slashes".
Are there any work-around I could use to solve the problem
If you want to match known prefixes, then you can just add more entries to your URI matcher (in this order):
content://com.lily.provider/items/a/*
content://com.lily.provider/items/b/*
content://com.lily.provider/items/*
If you insist on having slashes in the data, then you should URI-encode slashes that aren't being used as path separators to %2f.
Otherwise, I'm not sure what the problem is. The "/items/a/b" URI will match your original pattern as desired, and then you can parse the path component of the URI as you wish.