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.
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.
I have a listview that I’m populating from a sqlite database via LoaderManager and also I want to be able to filter this list.
I’m following the example from the android documentation: http://developer.android.com/guide/components/loaders.html#example
But I hit a road block at this point:
if (mCurFilter != null)
{
baseUri = Uri.withAppendedPath(Contacts.CONTENT_FILTER_URI, Uri.encode(mCurFilter));
}
I don’t know what CONTENT_FILTER_URI should look like.
All the examples that I could find are talking about filtering phone contacts using Phone. CONTENT_FILTER_URI, but in my case I need a custom CONTENT_FILTER_URI similar to the
CONTENT_URI = Uri.parse("content://" + AUTHORITIES + "/" + DataBase.TABLE);
from my extended ContentProvider class that I have implemented.
So what format must it have?
I don’t understand much from the documentation:
http://developer.android.com/reference/android/provider/ContactsContract.Contacts.html#CONTENT_FILTER_URI
Thank you.
Turns out I was over complicating things. I reused CONTENT_URI.
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
For a project we use the feed framework libs-for-android. The demo is very good but we can't find out how to grab the link elements in the feed. We try
private static final String[] PROJECTION = {
Entries._ID, Entries.TITLE_PLAINTEXT, Entries.SUMMARY, Entries.CONTENT,
Entries.ALTERNATE_HREF, Links.HREF
};
but Links.HREF is null. Does anyone have a suggestion? The xml can you find here (Atom feed)
Short answer: Does Entries.ALTERNATE_HREF contain the value you're looking for?
Long answer: The columns in the projection must all come from a single table (in this case, Entries). Cursors are flat, so to access nested elements the caller must either perform a second query, or pack child elements into a string or blob column. Another option is to define a column like ALTERNATE_HREF, which is basically just shorthand for the href attribute of the first rel="alternate" link element. There are a couple more columns like this defined in AtomContract, including Entries.ENCLOSURE_HREF and Entries.RELATED_HREF, but you might need to write your own AtomContract and AtomContentHandler if the data you need is not exposed.
The answer is the "short answer". I write my own AtomContract and now the link is stored in Entries.ALTERNATE_HREF
Thanks libs-for-android!
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.