Android content providers'-content providers' BASICS (getting data from the providers)

Source: Internet
Author: User

This section uses the user dictionary provider as an example to describe how to obtain data from the provider.

For clarity, the code snippets in this section call the contentresolver () method on the UI thread. However, in actual code, asynchronous queries should be executed in an independent thread. One of the methods for executing asynchronous queries is to use the cursorloader class, which has been described in detail in the loader guide. In addition, the Code here is only a code snippet, which is not a full application demonstration.

Follow these steps to obtain data from the provider:

1. Apply for read access permissions for the provisioner;

2. Define the query code sent to the provider.

Apply for read permission

To obtain data from a provider, the application requires "Read access" for the corresponding provider ". You cannot apply for this permission at runtime. Instead, you must use the <uses-Permission> element and the exact license name defined by the provider in the configuration file to specify the required permissions. When this element is specified in the list file, your application will be affected by the permission you applied. When you install the application, the system will implicitly approve the application.

To find the exact name of the reader's read access permission you want to use, and the name of other access permissions used by the provider, please refer to the documentation of the corresponding provider.

Roles that are allowed to access the providers' permissions will be described in more detail in the content providers' permissions section.

The user dictionary provider defines the Android. Permission. read_user_dictionary license in its list file. Therefore, if the application wants to read data from this provider, it must apply for this permission.

Build Query

The next step is to construct a query to obtain the data in the provider. First, some variables are defined to access the user dictionary provider:

// A "projection" defines the columns that will be returned for each row
String [] mprojection =
{
Userdictionary. Words. _ id, // Contract class constant for the _ ID column name
Userdictionary. Words. Word, // Contract class constant for the word column name
Userdictionary. Words. locale // Contract class constant for the locale column name
};

// Defines a string to contain the selection clause
String mselectionclause = NULL;

// Initializes an array to contain selection arguments
String [] mselectionargs = {""};

The following code snippet uses the user dictionary provider as an example to demonstrate how to use the contentresolver. Query () method. The client query of the provisioner is similar to an SQL query. It contains the set of columns to be returned, the set of selection conditions, and the sorting standard.

The set of columns to be returned for a query is called projection (defined in the variable mprojection ).

The expression of the row to be obtained is divided into two parts: Select clause and select parameter. The Select clause is a combination of logical and boolean expressions (including column names and values, which are defined in the mselection variable in the previous example ). If you specify a parameter that can be replaced by a value in the selection clause "?", The query method then obtains the data that matches the value specified in the selected parameter array (variable mselectionargs.

In the following code snippet, if the user does not input content in the input field, the selection clause is set to null, and the query returns all rows in the provider. If you enter some content, the selection clause is set to userdictionary. Words. Word + "= ?", Select the first element in the parameter array to be set as user input.

/*
* This defines a one-element string array to contain the selection argument.
*/
String [] mselectionargs = {""};

// Gets a word from the UI
Msearchstring = msearchword. gettext (). tostring ();

// Remember to insert code here to check for invalid or malicious input.

// If the word is the empty string, gets everything
If (textutils. isempty (msearchstring )){
// Setting the selection clause to null will return all words
Mselectionclause = NULL;
Mselectionargs [0] = "";

} Else {
// Constructs a selection clause that matches the word that the user entered.
Mselectionclause = "=? ";

// Moves the user's input string to the selection arguments.
Mselectionargs [0] = msearchstring;

}

// Does a query against the table and returns a cursor object
Mcursor = getcontentresolver (). Query (
Userdictionary. Words. content_uri, // The content URI of the words table
Mprojection, // The columns to return for each row
Mselectionclause // either null, or the word the user entered
Mselectionargs, // either empty, or the string the user entered
Msortorder); // The sort order for the returned rows

// Some providers return NULL if an error occurs, others throw an exception
If (null = mcursor ){
/*
* Insert code here to handle the error. Be sure not to use the cursor! You may want
* Call Android. util. log. E () to log this error.
*
*/
// If the cursor is empty, the provider found no matches
} Else if (mcursor. getcount () <1 ){

/*
* Insert code here to modify y 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
* Search term.
*/

} Else {
// Insert code here to do something with the results

}

This query is similar to the following SQL statement

Select _ id, word, frequency, locale from words where WORD = <userinput> order by word ASC;

In this SQL statement, the constant of the agreed class is replaced by the actual column name.

Prevent malicious input

If the data of the content provider is managed by a SQL database, illegal external data can be included in SQL statements, resulting in SQL injection (A Method of inserting malicious code into strings to attack relational databases).

Study the following selection clause:

// Constructs a selection clause by concatenating the user's input to the column name
String mselectionclause = "Var =" + muserinput;

If you do this, you can assemble malicious SQL statements into your SQL statements. For example, you can input "nothing; drop table *" to the variable muserinput, which causes Var = nothing; drop table * "to appear in the selection clause. Therefore, the selection clause is treated as an SQL statement, which may cause the provider to delete all the tables in the SQLite database (unless the provider attempts to capture SQL injection ).

To avoid this problem, use "?" As a selection clause of replaceable parameters and an independent array of selection parameters, user input is directly bound to the query instead of being interpreted as part of an SQL statement. Because it is not regarded as an SQL statement, user input cannot inject malicious SQL statements. The following example uses the string assembly method that includes user input instead of the select clause method:

// Constructs a selection clause with a replaceable Parameter
String mselectionclause = "Var =? ";

The following describes how to create a selection parameter array:

// Defines an array to contain the selection arguments
String [] selectionargs = {""};

The following describes how to add user input to the selection parameter array:

// Sets the selection argument to the user's input
Selectionargs [0] = muserinput;

Use "?" As the selection clause of replaceable parameters and the selection of parameter data, it is the first choice to specify a selection condition, even if the provider is not the machine SQL data.

 Display query data

The contentresolver. Query () Client method always returns a cursor object that contains the rows matching the query conditions and the columns specified by the query projection. The cursor object provides Random Access to the rows and columns it contains. Using the cursor object method, you can traverse all rows in the result, determine the Data Type of each column, obtain a column of data, and check other attributes of the result. Some cursor objects also automatically update objects when the provider's data changes, or trigger methods in an observer object when the cursor object changes, or both.

Note:Based on the query object construction feature, the provider can restrict access to certain columns. For example, the communication recorder restricts access to certain columns for the asynchronous adapter, so these columns cannot be returned to activity or service.

If no data row matches the selection condition, the provider will call the getcount () method of the cursor object and the result will be 0 (an empty cursor object ).

If an internal error occurs, the query result depends on a specific provider. It can return null or throw an exception.

Because the cursor object is a list of rows, it is a good way to associate the cursor object with a listview object through simplecursoradapter object to display the content.

The following code snippet is the continuation of the previous code snippet. It creates a simplecursoradapter object that contains the returned cursor object and sets this as the adapter of the listview object.

// Defines a list of columns to retrieve from the cursor and load into an output row
String [] mwordlistcolumns =
{
Userdictionary. Words. Word, // Contract class constant containing the word column name
Userdictionary. Words. locale // Contract class constant containing the locale column name
};

// Defines a list of view IDs that will receive the cursor columns for each row
Int [] mwordlistitems = {R. Id. dictword, R. Id. locale };

// Creates a new simplecursoradapter
Mcursoradapter = new simplecursoradapter (
Getapplicationcontext (), // The application's context object
R. layout. wordlistrow, // a layout in XML for one row in the listview
Mcursor, // The result from the query
Mwordlistcolumns, // a string array of column names in the cursor
Mwordlistitems, // an integer array of view IDs in the row Layout
0); // flags (usually none are needed)

// Sets the adapter for the listview
Mwordlist. setadapter (mcursoradapter );

Note:To complete the one-to-one correspondence between listview and cursor, the cursor object must contain a column named _ id. Because of this, you need to obtain the _ ID column of the "Words" table in the preceding query, even if the listview object does not display this column. This restriction explains why each table in most providers has a _ ID column.

Obtain data from query results

You can not only display query results, but also use them in other tasks. For example, you can get the spelling from the user dictionary and view it in other providers. You can iterate all rows in cursor to do this.

// Determine the column index of the column named "word"
Int Index = mcursor. getcolumnindex (userdictionary. 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 (mcursor! = NULL ){
/*
* Moves to the next row in the cursor. Before the first movement in the cursor,
* "Row Pointer" is-1, and if you try to retrieve data at that position you will get
* Exception.
*/
While (mcursor. movetonext ()){

// Gets the value from the column.
Newword = mcursor. getstring (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.
}

The cursor class provides several "get" methods to obtain different types of data from objects. For example, the getstring () method in the preceding code snippet. The GetType () method returns the Data Type of the specified column.

 

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.