Android Content Providers In Android security model one

  • Slides: 43
Download presentation
Android Content Providers • In Android security model, one application cannot directly access (read/write)

Android Content Providers • In Android security model, one application cannot directly access (read/write) other application's data. Every application has its own id data directory and own protected memory area. • Content provider is the best way to share data across applications. Content provider is a set of data wrapped up in a custom API to read and write. • Applications/Processes have to register themselves as a provider of data. Other applications can request Android to read/write that data through API. • Content provider API adheres to CRUD principle. • Examples for content provider are Contacts-that exposes user information to other applications http: //www. compiletimeerror. com/2013/12/content-provider-in-android. html#. VONZGPn. F 8 q. R 1

Android Content Providers App 1 stores its data in its own database and provides

Android Content Providers App 1 stores its data in its own database and provides a provider. App 2 communicates with the provider to access App 1's data. 2

 • Content providers are simple interfaces which uses insert(), query(), update(), delete() methods

• Content providers are simple interfaces which uses insert(), query(), update(), delete() methods to access application data. So it is easy to implement a content provider. • Writing a content provider with Content. Provider class. To create a content provider we have to 1. Create sub class for Content. Provider. 2. Define content URI 3. Implement all the unimplemented methods. insert(), update(), query(), delete(), get. Type(). 4. Declare the content provider in Android. Manifest. xml • Defining URI: Content provider URI consists of four parts: content: //authority/path/id content: // All the content provider URIs should start with this value 'authority' is Java namespace of the content provider implementation. (fully qualified Java package name) 'path' is the virtual directory within the provider that identifies the kind of data being requested. 'id' is optional part that specifies the primary key of a record being requested. We can omit this part to request all records. 3

 • A content provider is implemented as a subclass of Content. Provider class

• A content provider is implemented as a subclass of Content. Provider class and must implement a set of APIs that enable other applications to perform transactions. public class My. Content. Provider extends Content. Provider { } Content URIs • To query a content provider, you specify the query string in the form of a URI <prefix>: //<authority>/<data_type>/<id> • prefix: This is always set to content: // authority: This specifies the name of the content provider, for example contacts, browser, com. pritesh. My. Content. Provider • data_type: This indicates the type of data that this particular provides. For example, if you are getting all the contacts from the Contacts content provider, then the data path would be people and URI would look like this content: //contacts/people • id: This specifies the specific record requested. For example, if you are looking for contact number 5 in the Contacts content provider then URI would look like this content: //contacts/people/5. 4

Content Providers • Each Android applications runs in its own process with its own

Content Providers • Each Android applications runs in its own process with its own permissions which keeps an application data hidden from another application. • One application cannot directly access (read/write) other application's data. Every application has its own id data directory and own protected memory area. • Content provider API adheres to CRUD principle. • Content provider component manages access to a structured set of data, supplies data from one application to others on request which is handled by the methods of the Content. Resolver class. • A content provider can use different ways to store its data and the data can be stored in a SQLite database, in files, or even over a network. • They encapsulate the data, and provide mechanisms for defining data security. • Content providers are the standard interface that connects data in one process with code running in another process. 5

 • Content providers let you centralize content in one place and have many

• Content providers let you centralize content in one place and have many different applications access it as needed. • A content provider behaves very much like a database where you can query it, edit its content, as well as add or delete content using insert(), update(), delete(), and query() methods. In most cases this data is stored in an SQlite database. 6

 • When you want to access data in a content provider, you use

• When you want to access data in a content provider, you use the Content. Resolver object in your application's Context to communicate with the provider as a client. • The Content. Resolver object communicates with the provider object, an instance of a class that implements Content. Provider. • The provider object receives data requests from clients, performs the requested action, and returns the results. 7

 • You don't need to develop your own provider if you don't intend

• You don't need to develop your own provider if you don't intend to share your data with other applications. • However, you do need your own provider to provide custom search suggestions in your own application. • You also need your own provider if you want to copy and paste complex data or files from your application to other applications. • Android itself includes content providers that manage data such as audio, video, images, and personal contact information accessible to any Android application. 8

Content Provider Basics • A content provider manages access to a central repository of

Content Provider Basics • A content provider manages access to a central repository of data. • A provider is part of an Android application, which often provides its own UI for working with the data. • However, content providers are primarily intended to be used by other applications, which access the provider using a provider client object. • Together, providers and provider clients offer a consistent, standard interface to data that also handles inter-process communication and secure data access. 9

 • A content provider presents data to external applications as one or more

• A content provider presents data to external applications as one or more tables that are similar to the tables found in a relational database. • A row represents an instance of some type of data the provider collects, and each column in the row represents an individual piece of data collected for an instance. • For example, one of the built-in providers in the Android platform is the user dictionary, which stores the spellings of non-standard words that the user wants to keep. 10

 • • Sample user dictionary table. each row represents an instance of a

• • Sample user dictionary table. each row represents an instance of a word that might not be found in a standard dictionary. Each column represents some data for that word, such as the locale in which it was first encountered. A provider isn't required to have a primary key, and it isn't required to use _ID as the column name of a primary key if one is present. However, if you want to bind data from a provider to a List. View, one of the column names has to be _ID. This requirement is explained in more detail in the section Displaying query results. word app id frequency locale _ID mapreduce user 1 100 en_US 1 precompiler user 14 200 fr_FR 2 applet user 2 225 fr_CA 3 const user 1 255 pt_BR 4 int user 5 100 en_UK 5 11

Accessing a provider • An application accesses the data from a content provider with

Accessing a provider • An application accesses the data from a content provider with a Content. Resolver client object. • This object has methods that call identically-named methods in the provider object, an instance of one of the concrete subclasses of Content. Provider. • The Content. Resolver object in the client application's process and the Content. Provider object in the application that owns the provider automatically handle inter-process communication. • Content. Provider also acts as an abstraction layer between its repository of data and the external appearance of data as tables. • The Content. Resolver methods provide the basic "CRUD" (create, retrieve, update, and delete) functions of persistent storage. • To access a provider, your application usually has to request specific permissions in its manifest file 12

 • For example, to get a list of the words and their locales

• For example, to get a list of the words and their locales from the User Dictionary Provider, you call Content. Resolver. query(). • The query() method calls the Content. Provider. query() method defined by the User Dictionary Provider. • The following lines of code show a Content. Resolver. query() call: // Queries the user dictionary and returns results m. Cursor = get. Content. Resolver(). query( User. Dictionary. Words. CONTENT_URI, // The content URI of the words table m. Projection, // The columns to return for each row m. Selection. Clause // Selection criteria m. Selection. Args, // Selection criteria m. Sort. Order); // The sort order for the returned rows 13

Query() compared to SQL Select query(Uri, projection, selection. Args, sort. Order) query() argument SELECT

Query() compared to SQL Select query(Uri, projection, selection. Args, sort. Order) query() argument SELECT keyword/parameter Uri FROM table_name projection col, . . . selection WHERE col = value selection. Args (No exact equivalent. Selection arguments replace ? placeholders in the selection clause. ) sort. Order ORDER BY col, . . . Notes Uri maps to the table in the provider named table_name. projection is an array of columns that should be included for each row retrieved. selection specifies the criteria for selecting rows. sort. Order specifies the order in which rows appear in the returned Cursor. 14

Content URIs • A content URI is a URI that identifies data in a

Content URIs • A content URI is a URI that identifies data in a provider. • Content URIs include the symbolic name of the entire provider (its authority) and a name that points to a table (a path). • When you call a client method to access a table in a provider, the content URI for the table is one of the arguments. • In the preceding lines of code, the constant CONTENT_URI contains the content URI of the user dictionary's "words" table. • The Content. Resolver object parses out the URI's authority, and uses it to "resolve" the provider by comparing the authority to a system table of known providers. • The Content. Resolver can then dispatch the query arguments to the correct provider. 15

 • The Content. Provider uses the path part of the content URI to

• The Content. Provider uses the path part of the content URI to choose the table to access. • A provider usually has a path for each table it exposes. • the full URI for the "words" table is: • content: //user_dictionary/words • where the user_dictionary string is the provider's authority, and words string is the table's path. • The string content: // (the scheme) is always present, and identifies this as a content URI. 16

 • Many providers allow you to access a single row in a table

• Many providers allow you to access a single row in a table by appending an ID value to the end of the URI. • To retrieve a row whose _ID is 4 from user dictionary, you can use this content URI: • Uri single. Uri = Content. Uris. with. Appended. Id(User. Dictionary. Words. CONTENT_URI, 4); • You often use id values when you've retrieved a set of rows and then want to update or delete one of them. • Note: The Uri and Uri. Builder classes contain convenience methods for constructing well-formed Uri objects from strings. • The Content. Uris contains convenience methods for appending id values to a URI. 17

Retrieving Data from the Provider • Content. Resolver. query() 1. Request the read access

Retrieving Data from the Provider • Content. Resolver. query() 1. Request the read access permission for the provider. 2. Define the code that sends a query to the provider. 18

Requesting read access permission • To retrieve data from a provider, your application needs

Requesting read access permission • To retrieve data from a provider, your application needs "read access permission" for the provider rather than run time. • instead, you have to specify that you need this permission in your manifest, using the <uses-permission> element and the exact permission name defined by the provider. • When you specify this element in your manifest, you are in effect "requesting" this permission for your application. • When users install your application, they implicitly grant this request. • The User Dictionary Provider defines the permission android. permission. READ_USER_DICTIONARY in its manifest file, so an application that wants to read from the provider must request this permission 19

Constructing the query • The next step in retrieving data a provider is to

Constructing the query • The next step in retrieving data a provider is to construct a query. // A "projection" defines the columns that will be returned for each row String[] m. Projection = { User. Dictionary. Words. _ID, // Contract class constant for the _ID column name User. Dictionary. Words. WORD, // Contract class constant for the word column name User. Dictionary. Words. LOCALE // Contract class constant for the locale column name }; // Defines a string to contain the selection clause String m. Selection. Clause = null; // Initializes an array to contain selection arguments String[] m. Selection. Args = {""}; 20

Content. Resolver. query() using the User Dictionary Provider • A provider client query is

Content. Resolver. query() using the User Dictionary Provider • A provider client query is similar to an SQL query, and it contains a set of columns to return, a set of selection criteria, and a sort order. • The set of columns that the query should return is called a projection (the variable m. Projection). 21

 • The expression that specifies the rows to retrieve is split into a

• The expression that specifies the rows to retrieve is split into a selection clause and selection arguments. • The selection clause is a combination of logical and Boolean expressions, column names, and values (the variable m. Selection. Clause). • If you specify the replaceable parameter ? instead of a value, the query method retrieves the value from the selection arguments array (the variable m. Selection. Args). • if the user doesn't enter a word, the selection clause is set to null, and the query returns all the words in the provider. • If the user enters a word, the selection clause is set to User. Dictionary. Words. WORD + " = ? " and the first element of selection arguments array is set to the word the user enters. 22

/* This defines a one-element String array to contain the selection argument. */ String[]

/* This defines a one-element String array to contain the selection argument. */ String[] m. Selection. Args = {""}; // Gets a word from the UI m. Search. String = m. Search. Word. get. Text(). to. String(); // Remember to insert code here to check for invalid or malicious input. // If the word is the empty string, gets everything if (Text. Utils. is. Empty(m. Search. String)) { // Setting the selection clause to null will return all words m. Selection. Clause = null; m. Selection. Args[0] = ""; } else { // Constructs a selection clause that matches the word that //the user entered. m. Selection. Clause = User. Dictionary. Words. WORD + " = ? "; // Moves the user's input string to the selection arguments. m. Selection. Args[0] = m. Search. String; } 23

// Does a query against the table and returns a Cursor object m. Cursor

// Does a query against the table and returns a Cursor object m. Cursor = get. Content. Resolver(). query( User. Dictionary. Words. CONTENT_URI, // The content URI of the words table m. Projection, // The columns to return for each row m. Selection. Clause // Either null, or the word the user entered m. Selection. Args, // Either empty, or the string the user entered m. Sort. Order); // The sort order for the returned rows // Some providers return null if an error occurs, others throw an exception if (null == m. Cursor) { /* * Insert code here to handle the error. Be sure not to use the cursor! You may want to * call android. util. Log. e() to log this error. * */ // If the Cursor is empty, the provider found no matches } else if (m. Cursor. get. Count() < 1) { /* * Insert code here to notify the user that the search was unsuccessful. This isn't necessarily * an error. You may want to offer the user the option to insert a new row, or re-type the * search term. */ } else { // Insert code here to do something with the results } 24

 • This query is analogous to the SQL statement: • • SELECT _ID,

• This query is analogous to the SQL statement: • • SELECT _ID, word, locale FROM words WHERE word = <userinput> ORDER BY word ASC; 25

Selection arguments • Set up the array of like this: // Defines an array

Selection arguments • Set up the array of like this: // Defines an array to contain the selection arguments String[] selection. Args = {""}; • Put a value in the selection arguments array like this: // Sets the selection argument to the user's input selection. Args[0] = m. User. Input; 26

 • A selection clause that uses ? as a replaceable parameter and an

• A selection clause that uses ? as a replaceable parameter and an array of selection arguments array are preferred way to specify a selection, even if the provider isn't based on an SQL database. 27

Displaying query results • The Content. Resolver. query() client method always returns a Cursor

Displaying query results • The Content. Resolver. query() client method always returns a Cursor containing the columns specified by the query's projection for the rows that match the query's selection criteria. • A Cursor object provides random read access to the rows and columns it contains. • Using Cursor methods, you can iterate over the rows in the results, determine the data type of each column, get the data out of a column, and examine other properties of the results. • Some Cursor implementations automatically update the object when the provider's data changes, or trigger methods in an observer object when the Cursor changes, or both. 28

Query Result • If no rows match the selection criteria, the provider returns a

Query Result • If no rows match the selection criteria, the provider returns a Cursor object for which Cursor. get. Count() is 0 (an empty cursor). • If an internal error occurs, the results of the query depend on the particular provider. It may choose to return null, or it may throw an Exception. • Since a Cursor is a "list" of rows, a good way to display the contents of a Cursor is to link it to a List. View via a Simple. Cursor. Adapter. • It creates a Simple. Cursor. Adapter object containing the Cursor retrieved by the query, and sets this object to be the adapter for a List. View: 29

// Defines a list of columns to retrieve from the Cursor and load into

// Defines a list of columns to retrieve from the Cursor and load into an output row String[] m. Word. List. Columns = { User. Dictionary. Words. WORD, User. Dictionary. Words. LOCALE }; // Contract class constant for the word column name // Contract class constant for the locale column name // Defines a list of View IDs that will receive the Cursor columns for each row int[] m. Word. List. Items = { R. id. dict. Word, R. id. locale}; // Creates a new Simple. Cursor. Adapter m. Cursor. Adapter = new Simple. Cursor. Adapter( get. Application. Context(), // The application's Context object R. layout. wordlistrow, // A layout in XML for one row in the List. View m. Cursor, // The result from the query m. Word. List. Columns, // A string array of column names in the cursor m. Word. List. Items, // An integer array of view IDs in the row layout 0); // Flags (usually none are needed) // Sets the adapter for the List. View m. Word. List. set. Adapter(m. Cursor. Adapter); 30

List. View with a Cursor • the cursor must contain a column named _ID.

List. View with a Cursor • the cursor must contain a column named _ID. • Because of this, the query shown previously retrieves the _ID column for the "words" table, even though the List. View doesn't display it. • This restriction also explains why most providers have a _ID column for each of their tables. • Cursor implementations contain several "get" methods for retrieving different types of data from the object such as get. String(), get. Type() methods 31

Iterate rows in Cursor • // Determine the column index of the column named

Iterate rows in Cursor • // Determine the column index of the column named "word“ int index = m. Cursor. get. Column. Index(User. Dictionary. Words. WORD); /* Only executes if the cursor is valid. The User Dictionary Provider returns null if an internal error occurs. Other providers may throw an Exception instead of returning null. */ if (m. Cursor != null) { /* * Moves to the next row in the cursor. Before the first movement in the cursor, the "row pointer" is -1, and if you try to retrieve data at that position you will get an exception. */ while (m. Cursor. move. To. Next()) { // Gets the value from the column. new. Word = m. Cursor. get. String(index); // Insert code here to process the retrieved word. . // end of while loop } } else { // Insert code here to report an error if the cursor is null or the provider //threw an exception. } 32

Permission • As noted previously, the User Dictionary Provider requires the android. permission. READ_USER_DICTIONARY

Permission • As noted previously, the User Dictionary Provider requires the android. permission. READ_USER_DICTIONARY permission to retrieve data from it. • The provider has the separate android. permission. WRITE_USER_DICTIONARY permission for inserting, updating, or deleting data. • To get the permissions needed to access a provider, an application requests them with a <uses-permission> element in its manifest file. • When the Android Package Manager installs the application, a user must approve all of the permissions the application requests. • If the user approves all of them, Package Manager continues the installation; if the user doesn't approve them, Package Manager aborts the installation. • The following <uses-permission> element requests read access to the User Dictionary Provider: <uses-permission android: name="android. permission. READ_USER_DICTIONARY"> 33

Content. Resolver. insert() method inserts a new row into the provider and returns a

Content. Resolver. insert() method inserts a new row into the provider and returns a content URI for that row. // Defines a new Uri object that receives the result of the insertion Uri m. New. Uri; . . . // Defines an object to contain the new values to insert Content. Values m. New. Values = new Content. Values(); /* * Sets the values of each column and inserts the word. The arguments to the "put" * method are "column name" and "value" */ m. New. Values. put(User. Dictionary. Words. APP_ID, "example. user"); m. New. Values. put(User. Dictionary. Words. LOCALE, "en_US"); m. New. Values. put(User. Dictionary. Words. WORD, "insert"); m. New. Values. put(User. Dictionary. Words. FREQUENCY, "100"); m. New. Uri = get. Content. Resolver(). insert( User. Dictionary. Word. CONTENT_URI, // the user dictionary content URI m. New. Values // the values to insert ); 34

 • The snippet doesn't add the _ID column, because this column is maintained

• The snippet doesn't add the _ID column, because this column is maintained automatically. • The provider assigns a unique value of _ID to every row that is added. • Providers usually use this value as the table's primary key. • The data for the new row goes into a single Content. Values object, which is similar in form to a onerow cursor. • The columns in this object don't need to have the same data type, and if you don't want to specify a value at all, you can set a column to null using Content. Values. put. Null(). 35

Content URI • The content URI returned in new. Uri identifies the newly-added row,

Content URI • The content URI returned in new. Uri identifies the newly-added row, with the following format: • content: //user_dictionary/words/<id_value> • The <id_value> is the contents of _ID for the new row. • Most providers can detect this form of content URI automatically and then perform the requested operation on that particular row. • To get the value of _ID from the returned Uri, call Content. Uris. parse. Id(). 36

Updating data • To update a row, you use a Content. Values object with

Updating data • To update a row, you use a Content. Values object with the updated values just as you do with an insertion, and selection criteria just as you do with a query. • The client method you use is Content. Resolver. update(). • You only need to add values to the Content. Values object for columns you're updating. • If you want to clear the contents of a column, set the value to null. • The return value is the number of rows that were updated: 37

Changes all the rows whose locale has the language "en" to a have a

Changes all the rows whose locale has the language "en" to a have a locale of null // Defines an object to contain the updated values Content. Values m. Update. Values = new Content. Values(); // Defines selection criteria for the rows you want to update String m. Selection. Clause = User. Dictionary. Words. LOCALE + "LIKE ? "; String[] m. Selection. Args = {"en_%"}; // Defines a variable to contain the number of updated rows int m. Rows. Updated = 0; . . . /* Sets the updated value and updates the selected words. */ m. Update. Values. put. Null(User. Dictionary. Words. LOCALE); m. Rows. Updated = get. Content. Resolver(). update( User. Dictionary. Words. CONTENT_URI, // the content URI m. Update. Values // the m. Selection. Clause // the m. Selection. Args // the ); user dictionary columns to update column to select on value to compare to 38

Deleting data • Deleting rows is similar to retrieving row data: you specify selection

Deleting data • Deleting rows is similar to retrieving row data: you specify selection criteria for the rows you want to delete and the client method returns the number of deleted rows. • The following snippet The method returns the number of deleted rows. 39

Deletes rows whose appid matches "user" // Defines selection criteria for the rows you

Deletes rows whose appid matches "user" // Defines selection criteria for the rows you want to delete String m. Selection. Clause = User. Dictionary. Words. APP_ID + " LIKE ? "; String[] m. Selection. Args = {"user"}; // Defines a variable to contain the number of rows deleted int m. Rows. Deleted = 0; . . . // Deletes the words that match the selection criteria m. Rows. Deleted = get. Content. Resolver(). delete( User. Dictionary. Words. CONTENT_URI, // the user dictionary content URI m. Selection. Clause // the column to select on m. Selection. Args // the value to compare to ); 40

Provider Data Types • Content providers can offer many different data types. • The

Provider Data Types • Content providers can offer many different data types. • The User Dictionary Provider offers only text, but providers can also offer the following formats: • integer • long integer (long) • floating point • long floating point (double) • Another data type that providers often use is Binary Large OBject (BLOB) implemented as a 64 KB byte array. • You can see the available data types by looking at the Cursor class "get" methods 41

 • The data type for each column in a provider is usually listed

• The data type for each column in a provider is usually listed in its documentation. • The data types for the User Dictionary Provider are listed in the reference documentation for its contract class User. Dictionary. Words (contract classes are described in the section Contract Classes). • You can also determine the data type by calling Cursor. get. Type(). 42

Example Reference http: //www. compiletimeerror. com/2013/12/co ntent-provider-in-android. html#. VN 3 j 2 fn. F

Example Reference http: //www. compiletimeerror. com/2013/12/co ntent-provider-in-android. html#. VN 3 j 2 fn. F 8 q. Q http: //www. grokkingandroid. com/androidtutorial-writing-your-own-content-provider/ http: //code. tutsplus. com/tutorials/androidfundamentals-working-with-content-providers-mobile-5549 43