mobappdev (fall 2013): uris, mimes, & uri processing on android
TRANSCRIPT
URIs, MIMEs, & URI Processing on Android
Vladimir Kulyukin
www.vkedco.blogspot.com
Outline● Uniform Resource Identifiers (URIs)● Multipurpose Internet Mail Extensions (MIMEs)● URI Processing on Android
URI Elements URI Matching Codes & Mimes Matching URIs
Non-Standard MIME Subtypes on Android
● A Content provider must list which columns it supports● There is no standard way of listing columns● Typical methods of listing columns:
Constants and documentation Interfaces and documentation
● Documentation or naming conventions should be used to indicate column types, because there is no formal way to indicate column types
Uniform Resource Identifiers
Uniform Resource Identifier (URI)● A URI is a string of characters that identifies a resource● Uniform – means that different types of resource identifiers can
be used in the same context even when their access mechanisms are different
● Resource – means anything that has an identity (e.g., a document, an image, a service)
● Identifier – means that it is a reference to a resource with an identity (e.g., a sequence of characters with specific syntactic restrictions)
Common Abbreviations: URI, URL, URN
● URL – Uniform Resource Locator● URN – Uniform Resource Name● Although the terms URI, URL, & URN are frequently used
interchangeably, URL and URN are technically subsets of URI● URL is the subset of URIs that identify resources via their
primary access mechanisms (aka protocols) (http, ftp, gopher, etc.)
● URN is the subset of URIs that are required to remain globally unique and persistent (even when the resources cease to exist)
URI Examples
● ftp://ftp.org.sample/rfc/rfc1001.txt● gopher://univ.edu/classes/cs● http://some_server:8080/public/home.html● telnet://my_company.net/● mailto:[email protected]● news:comp.infosystems.www.servers.unix
Hierarchical & Relative URIs● Absolute URI refers to a resource
regardless of the context in which it is used● Relative URI refers to a resource within a
specific namespace (e.g., absolute vs. relative file paths)
● Some URI schemes support hierarchical naming systems
● URI naming hierarchies use the “/” delimiters
Generic URI Syntax
<scheme>://<authority><path>?<query>
Example 01
● ftp://org.vkedco.mobappdev/resources/README.txt ● SCHEME: ftp● AUTHORITY: org.vkedco.mobappdev● PATH: /resources/README.txt● PATH_SEGMENTS: resources; README.txt● PORT: -1 // not specified so defaults to -1● QUERY: null // not specified so defaults to null
Example 02content://org.vkedco.mobappdev.content_providers.books/book_title/id
● SCHEME: content● AUTHORITY: org.vkedco.mobappdev.content_providers.books● PATH: /book_title/id● PATH_SEGMENTS: book_title; id● PORT: -1 // not specified, defaults to -1● QUERY: null // not specified, defaults to null
Example 03content://org.vkedco.mobappdev.content_providers.books/book_title/id/10
● SCHEME: content● AUTHORITY: org.vkedco.mobappdev.content_providers.books
● PATH: /book_title/id/10● PATH_SEGMENTS: book_title; id ; 10● PORT: -1● QUERY: null
Example 04content://org.vkedco.mobappdev.content_providers.books/book_title?title=essential_rumi
● SCHEME: content● AUTHORITY: org.vkedco.mobappdev.content_providers.books
● PATH: /book_title● PATH_SEGMENTS: book_title● PORT: -1● QUERY: title=essential_rumi
Example 05http://vkedco_content_server:8080/book_title?title=essential_rumi&author=rumi
● SCHEME: http● AUTHORITY: vkedco_content_server:8080
● PATH: /book_title● PATH_SEGMENTS: book_title● PORT: 8080● QUERY: title=essential_rumi&author=rumi
URI Member Access
<scheme>://<authority><path>?<query>
● Uri.getScheme()● Uri.getAuthority()● Uri.getPath()● Uri.getPathSegments()● Uri.getPort()● Uri.getQuery()● Uri.getQueryParameter()
Getting URI ElementsString getUriInfo(Uri uri) {
StringBuilder sb = new StringBuilder(""); sb.append("URI: " + uri.toString() + "\n");
sb.append("SCHEME: " + uri.getScheme() + "\n"); sb.append("AUTHORITY: " + uri.getAuthority() + "\n");
sb.append("PATH=" + uri.getPath() + "\n"); sb.append("PATH SEGMENTS:\n");
List<String> pathSegments = uri.getPathSegments();
for(int i = 0; i < pathSegments.size(); i++) {
sb.append("path_sgmnt[" + i + "]=" + pathSegments.get(i) + "\n");
}
sb.append("PORT: " + uri.getPort() + "\n");
sb.append("QUERY: " + uri.getQuery() + "\n");
sb.append("TITLE_PARAM: " + uri.getQueryParameter("title") + "\n");
sb.append("AUTHOR_PARAM: " + uri.getQueryParameter("author") + "\n");
return sb.toString();
}
URI Design Criteria● URI should be a sequence of characters and not always
a sequence of octets (in CS, octet is a sequence of 8 bits, aka byte)
● URI may be transcribed from a non-network source and should consist of characters sensitive to constraints imposed by keyboards and locales
● URI should be remembered by people (should have meaningful components)
URI Design Steps● Choose the scheme, e.g., content, http, etc.● Design an authority● Design MIMEs (Multipurpose Internet Mail Extensions)
or use existing ones● Design match codes to manage uri matching● Use UriMatcher objects to add and match URIs
Logical URI Matching Steps● Publish Authority & Paths● Publish URI Matching Codes● Publish Mimes● Create a UriMatcher and add to it a URI described as
a triple <AUTHORITY, PATH, MATCH_CODE>● An input URI is given to the UriMatcher, if a match is
successful, MATCH_CODE is returned● A MATCH_CODE is used to return an associated type
Multipurpose Internet Mail Extensions (aka MIMEs)
MIME Types● A Web site returns a MIME type for a given URL● A Browser starts a URL handling program depending on
the URL's MIME type● MIME types work on Android in the same way they work in
HTTP: a content provider can be asked for the MIME type of a given URI
● When asked about the MIME type, the provider returns a two-part string according to the standard web MIME conventions
MIME Types ● RFC document on the MIME standards is available at
http://tools.ietf.org/html/rfc2046● A MIME type has two parts: a type and a subtype:
text/html text/css application/pdf
● Complete list of registered types and subtypes are at http://www.iana.org/assignments/media-types
MIME Types
● Primary registered content types are application, audio, example, image, message, model, multipart, text, video
● Each primary type has subtypes● If a vendor has proprietary data formats, the subtype
name begins with vnd: application/vnd.ms-excel● If it is a standard data format, the subtype does not start
with any prefix: text/html or application/pdf
Non-Standard MIME Subtypes ● Subtypes that start with x- refer to non-standard types that
do not have to be registered● These two types are typically defined bilaterally defined by
collaborating applications/agents application/x-tar audio/x-aiff video/x-msvideo
Non-Standard MIME Subtypes on Android ● For a single record, the Android MIME type is as follows:
vnd.android.cursor.item/vnd.yourcompany.contenttype
● For a collection of records, the Android MIME type is as follows:
vnd.android.cursor.dir/vnd.yourcompany.contenttype
● Examples: vnd.android.cursor.item/vnd.google.note vnd.android.cursor.dir/vnd.google.note
URI Processing
source code is in UriTestActivity.java
Sample Problem
Suppose we want to create a resource that allows its clients to retrieve books, book titles, and book authors. What URIs do we need to support this resource?
URIs: Scheme, Authority, Paths● Scheme: content● Authority: org.vkedco.mobappdev.content_providers.books● Paths:
book_title/id // retrieve all book ids
book_title/id/# // retreive a specific book title id
// (e.g., book_title/ids/1, book_title/ids/2, etc)
book_author/author // retrieve all authors
book_author/author/# // retrieve a specific book author whose id is #
book_cover_image/cover_image // retrieve all images
book_cover_image/cover_image/# // retrieve a specific image
Publishing Authority & Paths
// AUTHORITY & PATHS
static final String AUTHORITY = "org.vkedco.mobappdev.content_providers.books";
static final String BOOK_ID_PATH = "book_title" + "/id";
static final String BOOK_TITLE_PATH = "book_title" + "/title";
static final String BOOK_AUTHOR_PATH = "book_author" + "/author";
static final String BOOK_COVER_PATH = "book_cover" + "/cover_image";
Publishing Authority & Paths
// AUTHORITY & PATHS
static final String AUTHORITY = "org.vkedco.mobappdev.content_providers.books";
static final String BOOK_ID_PATH = "book_title" + "/id";
static final String BOOK_TITLE_PATH = "book_title" + "/title";
static final String BOOK_AUTHOR_PATH = "book_author" + "/author";
static final String BOOK_COVER_PATH = "book_cover" + "/cover_image";
Publishing Matching Codes// URI Matching Codes; these are returned if a match is successful
static final int CODE_BOOK_ID_ALL = 0;
static final int CODE_BOOK_ID_SINGLE = 1;
static final int CODE_BOOK_TITLE_ALL = 2;
static final int CODE_BOOK_TITLE_SINGLE = 3;
static final int CODE_BOOK_AUTHOR_ALL = 4;
static final int CODE_BOOK_AUTHOR_SINGLE = 5;
static final int CODE_BOOK_COVER_ALL = 6;
static final int CODE_BOOK_COVER_SINGLE = 7;
Publishing MIMEs// This mime is associated with CODE_BOOK_ID_ALL
static final String BOOK_TITLE_ID_ALL_MIME = "vnd.android.cursor.dir/vnd.vkedco.mobappdev.book_id_all";
// This mime is associated with CODE_BOOK_ID_SINGLE
static final String BOOK_TITLE_ID_SINGLE_MIME = "vnd.android.cursor.item/vnd.vkedco.mobappdev.book_id_single";
// This mime is associated with CODE_BOOK_TITLE_ALL
static final String BOOK_TITLE_ALL_MIME = "vnd.android.cursor.dir/vnd.vkedco.mobappdev.book_title_all";
// This mime is associated with CODE_BOOK_TITLE_SINGLE
static final String BOOK_TITLE_SINGLE_MIME = "vnd.android.cursor.item/vnd.vkedco.mobappdev.book_title_single";
Publishing MIMEs// This mime is associated with CODE_BOOK_AUTHOR_ALL
static final String BOOK_AUTHOR_ALL_MIME = "vnd.android.cursor.dir/vnd.vkedco.mobappdev.book_author_all";
// This mime is associated with CODE_BOOK_AUTHOR_SINGLE
static final String BOOK_AUTHOR_SINGLE_MIME = "vnd.android.cursor.dir/vnd.vkedco.mobappdev.book_author_single";
// This mime is associated with CODE_BOOK_COVER_ALL
static final String BOOK_COVER_ALL_MIME = "vnd.android.cursor.dir/vnd.vkedco.mobappdev.book_cover_all";
// This mime is associated with CODE_BOOK_COVER_SINGLE
static final String BOOK_COVER_SINGLE_MIME = "vnd.android.cursor.dir/vnd.vkedco.mobappdev.book_cover_single";
Adding URIs to UriMatcher
// 1. Create a UriMatcher
UriMatcher mUriMatcher = new UriMatcher(UriMatcher.NO_MATCH);
// 2. add a new URI to the UriMatcher: AUTHORITY/BOOK_ID_PATH
// if a match is successful, then BOOK_ID_ALL is returned
mUriMatcher.addURI(AUTHORITY, BOOK_ID_PATH, BOOK_ID_ALL);
Basic URI Matching Patternvoid matchUri(Uri uri) {
int uri_match_code = mUriMatcher.match(uri);
switch ( uri_match_code ) {
case CODE_BOOK_ID_ALL:
// do something with this URI
break;
case CODE_BOOK_ID_SINGLE:
// do something with this URI
break;
// handle other cases
}
Getting Associated URI MIMEsstatic String getUriMIME(Uri uri) {
int uri_match_code = mUriMatcher.match(uri);
switch ( uri_match_code ) {
case CODE_BOOK_ID_ALL: return UriTestActivity.BOOK_AUTHOR_ALL_MIME;
case CODE_BOOK_ID_SINGLE: return UriTestActivity.BOOK_AUTHOR_SINGLE_MIME;
case CODE_BOOK_TITLE_ALL: return UriTestActivity.BOOK_TITLE_ALL_MIME;
case CODE_BOOK_TITLE_SINGLE: return UriTestActivity.BOOK_TITLE_SINGLE_MIME;
case CODE_BOOK_AUTHOR_ALL: return UriTestActivity.BOOK_AUTHOR_ALL_MIME;
case CODE_BOOK_AUTHOR_SINGLE: return UriTestActivity.BOOK_AUTHOR_SINGLE_MIME;
case CODE_BOOK_COVER_ALL: return UriTestActivity.BOOK_COVER_ALL_MIME;
case CODE_BOOK_COVER_SINGLE: return UriTestActivity.BOOK_COVER_ALL_MIME;
}
return "NONE";
}
References ● http://developer.android.com/guide/topics/providers/content-providers.html● http://tools.ietf.org/html/rfc2046● http://www.iana.org/assignments/media-types● http://www.faqs.org/rfcs/rfc2396.html