Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> 關於Android編程 >> API翻譯 --- Content Provider Basics

API翻譯 --- Content Provider Basics

編輯:關於Android編程

IN THIS DOCUMENT

Overview 綜述
Accessing a provider 訪問一個提供者
Content URIs 內容URI
Retrieving Data from the Provider 檢索的數據提供者
Requesting read access permission 請求讀訪問權限
Constructing the query 構建查詢
Displaying query results 顯示查詢結果
Getting data from query results 從查詢結果中獲取數據
Content Provider Permissions 內容提供者權限
Inserting, Updating, and Deleting Data 插入、更新和刪除數據
Inserting data 添加數據
Updating data 更新數據
Deleting data 刪除數據
Provider Data Types 提供者的數據類型
Alternative Forms of Provider Access 替代形式的提供者訪問
Batch access 成批存取
Data access via intents 數據訪問通過意圖
Contract Classes 合同類
MIME Type Reference MIME類型引用

KEY CLASSES

  1. ContentProvider
  2. ContentResolver
  3. Cursor
  4. Uri

RELATED SAMPLES

  1. Cursor (People)
  2. Cursor (Phones)

SEE ALSO

  1. Creating a Content Provider
  2. Calendar Provider 日歷提供者

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.

一個內容提供者管理的中央存儲庫數據的訪問。提供者是Android應用程序的一部分,通常提供自己的UI處理數據。然而,內容提供商主要是打算使用的其他應用程序,訪問提供者使用提供者端對象。客戶,供應商和供應商提供一個一致的,數據標准接口,還處理進程間通信和安全的數據訪問。

This topic describes the basics of the following:本主題描述的基本知識:

  • How content providers work.內容提供者是如何工作的。
  • The API you use retrieve data from a content provider.您所使用的API檢索數據從一個內容提供者。
  • The API you use to insert, update, or delete data in a content provider.API用於插入、更新或刪除數據在一個內容提供者
  • Other API features that facilitate working with providers.其他API功能,促進與供應商合作。

Overview


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. Table 1 illustrates what the data might look like in this provider's table:

例如,Android平台內置的提供者之一是用戶詞典,商店標准單詞的拼寫,用戶希望保持。表1顯示了數據可能看起來像這個提供者的表:

Table 1:Sample user dictionary table.

word app id frequency locale _ID mapreduce user1 100 en_US 1 precompiler user14 200 fr_FR 2 applet user2 225 fr_CA 3 const user1 255 pt_BR 4 int user5 100 en_UK 5

In table 1, 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. The column headers are column names that are stored in the provider. To refer to a row's locale, you refer to itslocalecolumn. For this provider, the_IDcolumn serves as a "primary key" column that the provider automatically maintains.

在表1中,每一行表示一個單詞的實例可能不會發現在標准字典。每一列表示一些詞的數據,如語言環境中,這是第一次遇到。列標題的列名稱存儲在提供者。指連續的區域,你參考它的地區列。對於這個提供者,_ID列作為“主鍵”專欄,提供者自動維護。

Note:A provider isn't required to have a primary key, and it isn't required to use_IDas the column name of a primary key if one is present. However, if you want to bind data from a provider to aListView, one of the column names has to be_ID. This requirement is explained in more detail in the sectionDisplaying query results.

注意:提供者不需要有一個主鍵,並且不需要使用_ID作為一個主鍵的列名稱如果有的話)。然而,如果你想要綁定的數據提供者列表視圖,列名必須_ID之一。這個需求更詳細地解釋中顯示查詢結果。

Accessing a provider 訪問一個提供者

An application accesses the data from a content provider with aContentResolverclient object. This object has methods that call identically-named methods in the provider object, an instance of one of the concrete subclasses ofContentProvider. TheContentResolvermethods provide the basic "CRUD" (create, retrieve, update, and delete) functions of persistent storage.

應用程序訪問數據從一個內容提供者ContentResolver客戶端對象。這個對象方法調用提供者對象名稱相同的方法,具體的子類的一個實例ContentProvider。ContentResolver方法提供了基本的CRUD(創建、檢索、更新和刪除)的持久性存儲功能。

TheContentResolverobject in the client application's process and theContentProviderobject in the application that owns the provider automatically handle inter-process communication.ContentProvideralso acts as an abstraction layer between its repository of data and the external appearance of data as tables.

ContentResolver對象在客戶端應用程序的過程和ContentProvider對象在應用程序擁有提供者自動處理進程間通信。ContentProvideralso之間充當一個抽象層的存儲庫數據和數據表的外觀。

Note:To access a provider, your application usually has to request specific permissions in its manifest file. This is described in more detail in the sectionContent Provider Permissions

For example, to get a list of the words and their locales from the User Dictionary Provider, you callContentResolver.query(). Thequery()method calls theContentProvider.query()method defined by the User Dictionary Provider. The following lines of code show aContentResolver.query()call:

注意:訪問提供者,您的應用程序通常有請求特定的權限清單文件。這是更詳細地描述部分內容提供者權限
例如,要獲取的單詞列表和他們的地區從用戶詞典提供程序,你叫ContentResolver.query()。查詢()方法調用ContentProvider.query()方法定義的用戶詞典提供程序。下面的代碼行顯示ContentResolver.query()調用:

// Queries the user dictionary and returns results
mCursor = getContentResolver().query(
  UserDictionary.Words.CONTENT_URI,  // The content URI of the words table
  mProjection,            // The columns to return for each row
  mSelectionClause          // Selection criteria
  mSelectionArgs,           // Selection criteria
  mSortOrder);            // The sort order for the returned rows

Table 2 shows how the arguments toquery(Uri,projection,selection,selectionArgs,sortOrder)match an SQL SELECT statement:

Table 2:Query() compared to SQL query.

query() argument SELECT keyword/parameter Notes Uri FROMtable_name Urimaps to the table in the provider namedtable_name. projection col,col,col,... projectionis an array of columns that should be included for each row retrieved. selection WHEREcol=value selectionspecifies the criteria for selecting rows. selectionArgs (No exact equivalent. Selection arguments replace?placeholders in the selection clause.) sortOrder ORDER BYcol,col,... sortOrderspecifies the order in which rows appear in the returnedCursor.

Content URIs

Acontent URIis a URI that identifies data in a provider. Content URIs include the symbolic name of the entire provider (itsauthority) and a name that points to a table (apath). 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 constantCONTENT_URIcontains the content URI of the user dictionary's "words" table. TheContentResolverobject parses out the URI's authority, and uses it to "resolve" the provider by comparing the authority to a system table of known providers. TheContentResolvercan then dispatch the query arguments to the correct provider.

TheContentProvideruses the path part of the content URI to choose the table to access. A provider usually has apathfor each table it exposes.

內容的URI是一個URI標識數據提供者。內容uri包括整個提供者的符號名(權力)和一個名字指向一個表(路徑)。當你調用客戶方法訪問一個表在一個提供者,內容的表是一個URI參數。
在前面的代碼行,不斷CONTENT_URI包含內容的URI用戶詞典的“單詞”表。ContentResolver對象解析URI的權威,並使用它來“解決”提供者通過比較系統的權限表的提供者。TheContentResolver可以調度查詢參數正確的供應商。

In the previous lines of code, the full URI for the "words" table is:

在前一行代碼,完整的URI的“單詞”表:

content://user_dictionary/words

where theuser_dictionarystring is the provider's authority, andwordsstring is the table's path. The stringcontent://(thescheme) is always present, and identifies this as a content URI.

user_dictionary字符串的提供者的權威,和文字字符串表的路徑。字符串內容:/ /(計劃)總是存在,並確定這是一個URI的內容。

Many providers allow you to access a single row in a table by appending an ID value to the end of the URI. For example, to retrieve a row whose_IDis4from user dictionary, you can use this content URI:

許多供應商允許您訪問表中的一行通過附加一個ID值的URI。例如,檢索一行的_ID 4從用戶詞典,你可以使用這個URI的內容:

Uri singleUri =ContentUris.withAppendedId(UserDictionary.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.

你經常使用id值,當檢索一組行,然後想要更新或刪除其中之一。

Note:TheUriandUri.Builderclasses contain convenience methods for constructing well-formed Uri objects from strings. TheContentUriscontains convenience methods for appending id values to a URI. The previous snippet useswithAppendedId()to append an id to the UserDictionary content URI.

注意:Uri和Uri。構建器類包含便利方法構造格式良好的Uri對象從字符串。ContentUris包含便利的方法將id值附加到一個URI。前面的代碼片段使用withAppendedId()添加一個id UserDictionary內容URI。

Retrieving Data from the Provider


This section describes how to retrieve data from a provider, using the User Dictionary Provider as an example.本節描述如何從提供者檢索數據,使用用戶詞典提供程序作為示例。

For the sake of clarity, the code snippets in this section callContentResolver.query()on the "UI thread"". In actual code, however, you should do queries asynchronously on a separate thread. One way to do this is to use theCursorLoaderclass, which is described in more detail in theLoadersguide. Also, the lines of code are snippets only; they don't show a complete application.

為了清晰,本節中的代碼段調用ContentResolver.query“UI線程上的()。然而,在實際的代碼,你應該做一個獨立的線程上異步查詢。一種方法是使用CursorLoader類,這是Loadersguide更詳細地描述。也,行代碼片段;他們不顯示一個完整的應用程序。

To retrieve data from a provider, follow these basic steps:

檢索的數據提供者,遵循這些基本步驟:

  1. Request the read access permission for the provider.供應商請求讀訪問權限。
  2. Define the code that sends a query to the provider.定義的代碼將查詢發送到提供者。

Requesting read access permission請求讀訪問權限

To retrieve data from a provider, your application needs "read access permission" for the provider. You can't request this permission at run-time; instead, you have to specify that you need this permission in your manifest, using theelement 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.

檢索的數據提供者,您的應用程序需要“讀訪問權限”提供者。你不能請求允許在運行時;相反,您必須指定你需要這個權限清單,使用< uses-permission >元素和確切的權限名稱定義的提供者。當你在清單中指定這個元素時,你實際上是“請求”這允許您的應用程序。當用戶安裝應用程序時,他們隱式授予此請求。

To find the exact name of the read access permission for the provider you're using, as well as the names for other access permissions used by the provider, look in the provider's documentation.找到准確的讀訪問權限的名稱您所使用的提供者,以及其他訪問權限的名稱使用的供應商,看看提供者的文檔。

The role of permissions in accessing providers is described in more detail in the sectionContent Provider Permissions.

權限訪問提供商的角色是更詳細地描述部分內容提供者權限。

The User Dictionary Provider defines the permissionandroid.permission.READ_USER_DICTIONARYin its manifest file, so an application that wants to read from the provider must request this permission.用戶詞典提供程序定義了android.permission許可。READ_USER_DICTIONARY清單文件,所以想讀的應用程序從提供者必須請求許可。

Constructing the query構建查詢

The next step in retrieving data a provider is to construct a query. This first snippet defines some variables for accessing 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 next snippet shows how to useContentResolver.query(), using the User Dictionary Provider as an example. 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.

下一個代碼片段展示了如何使用ContentResolver.query(),使用用戶詞典提供程序作為示例。提供客戶端查詢類似於SQL查詢,它包含一組列返回,一組選擇標准,和排序順序。

The set of columns that the query should return is called aprojection(the variablemProjection).查詢的列集應該返回稱為投影(變量mProjection)。

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 variablemSelectionClause). If you specify the replaceable parameter?instead of a value, the query method retrieves the value from the selection arguments array (the variablemSelectionArgs).

檢索表達式,指定行分為選擇條款和選擇參數。選擇子句的組合邏輯、布爾表達式列名稱和值(變量mSelectionClause)。如果你指定可替換的參數?而不是一個值,查詢方法檢索的值選擇參數數組(variablemSelectionArgs)。

In the next snippet, if the user doesn't enter a word, the selection clause is set tonull, and the query returns all the words in the provider. If the user enters a word, the selection clause is set toUserDictionary.Words.WORD + " = ?"and the first element of selection arguments array is set to the word the user enters.

在下一個代碼片段,如果用戶不輸入一個單詞,選擇條款設置為空,查詢返回所有單詞的提供者。如果用戶輸入一個單詞,設置選擇條件是UserDictionary.Words.WORD + " = ?"和選擇參數數組的第一個元素設置為用戶輸入這個詞。

/*
* 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 =UserDictionary.Words.WORD +" = ?";

  // 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 to
  * call android.util.Log.e() to log this error.
  *
  */
// If the Cursor is empty, the provider found no matches
}elseif(mCursor.getCount()<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

}

This query is analogous to the SQL statement:這個查詢的方法是類似於SQL語句

SELECT _ID, word, locale FROM words WHERE word = ORDER BY word ASC;

In this SQL statement, the actual column names are used instead of contract class constants.在這個SQL語句,使用實際的列名而不是合同類的常量。

Protecting against malicious input防止惡意輸入

If the data managed by the content provider is in an SQL database, including external untrusted data into raw SQL statements can lead to SQL injection.如果由內容提供者的數據是在一個SQL數據庫,包括外部不可信數據為原始SQL語句會導致SQL注入。

Consider this 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're allowing the user to concatenate malicious SQL onto your SQL statement. For example, the user could enter "nothing; DROP TABLE *;" formUserInput, which would result in the selection clausevar = nothing; DROP TABLE *;. Since the selection clause is treated as an SQL statement, this might cause the provider to erase all of the tables in the underlying SQLite database (unless the provider is set up to catchSQL injectionattempts).

如果你這樣做,你惡意SQL允許用戶連接到您的SQL語句。例如,用戶可以輸入“什麼;刪除表*”mUserInput,這將導致選擇條款var =什麼;表*;下降。自從選擇條款被視為一個SQL語句,這可能導致供應商消除底層SQLite數據庫中所有的表(除非提供者設置捕獲SQL注入的嘗試)。

To avoid this problem, use a selection clause that uses?as a replaceable parameter and a separate array of selection arguments. When you do this, the user input is bound directly to the query rather than being interpreted as part of an SQL statement. Because it's not treated as SQL, the user input can't inject malicious SQL. Instead of using concatenation to include the user input, use this selection clause:

為了避免這個問題,使用選擇條款,使用?作為一個可替換的參數選擇和一個單獨的數組參數。當你這樣做時,用戶輸入直接綁定到查詢而不是被解釋為一個SQL語句的一部分。因為它不是作為SQL,用戶輸入不能注入惡意SQL。而不是使用連接包括用戶輸入,選擇使用這個條款:

// Constructs a selection clause with a replaceable parameter
String mSelectionClause = "var = ?";

Set up the array of selection arguments like this:建立了一系列的選擇參數如下:

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

Put a value in the selection arguments array like this:把選擇的參數數組中的值如下:

// Sets the selection argument to the user's input
selectionArgs[0]= mUserInput;

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.選擇使用條款?作為一個可替換的參數和選擇參數數組的數組是首選方法指定一個選擇,即使提供者不是基於SQL數據庫。

Displaying query results顯示查詢結果

TheContentResolver.query()client method always returns aCursorcontaining the columns specified by the query's projection for the rows that match the query's selection criteria. ACursorobject provides random read access to the rows and columns it contains. UsingCursormethods, 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. SomeCursorimplementations automatically update the object when the provider's data changes, or trigger methods in an observer object when theCursorchanges, or both.

ContentResolver.query()客戶機方法總是返回包含指定的列的游標查詢的行投影匹配查詢的選擇標准。一個游標對象提供了隨機讀取訪問它所包含的行和列。使用光標的方法,可以遍歷行結果,確定每一列的數據類型,獲取數據的列,並檢查其他屬性的結果。一些指針實現自動更新對象當提供者的數據發生變化時,或觸發方法在一個觀察者對象當光標變化時,或兩者兼而有之。

Note:A provider may restrict access to columns based on the nature of the object making the query. For example, the Contacts Provider restricts access for some columns to sync adapters, so it won't return them to an activity or service.

注意:提供者可能限制列基於對象的性質進行查詢。例如,聯系供應商限制訪問一些列同步適配器,所以它不會返回一個活動或服務。

If no rows match the selection criteria, the provider returns aCursorobject for whichCursor.getCount()is 0 (an empty cursor).

如果沒有行匹配選擇條件,提供程序返回一個游標對象whichCursor.getCount()0(空指針)。

If an internal error occurs, the results of the query depend on the particular provider. It may choose to returnnull, or it may throw anException.如果發生內部錯誤,查詢的結果依賴於特定的提供者。它可以選擇返回null,或者它可能拋出異常。

Since aCursoris a "list" of rows, a good way to display the contents of aCursoris to link it to aListViewvia aSimpleCursorAdapter.

The following snippet continues the code from the previous snippet. It creates aSimpleCursorAdapterobject containing theCursorretrieved by the query, and sets this object to be the adapter for aListView:由於一個游標是一個“列表”的行,顯示游標的內容的一個好方法是通過SimpleCursorAdapter鏈接到列表視圖。
以下代碼片段繼續前面的代碼片段。它創建一個包含光標SimpleCursorAdapterobject檢索查詢,並設置該對象為aListView適配器:

// 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 =newSimpleCursorAdapter(
  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 back aListViewwith aCursor, the cursor must contain a column named_ID. Because of this, the query shown previously retrieves the_IDcolumn for the "words" table, even though theListViewdoesn't display it. This restriction also explains why most providers have a_IDcolumn for each of their tables.

注:支持列表視圖與光標,光標必須包含一個列名叫_ID。正因為如此,先前的查詢檢索_ID列“單詞”表,即使theListView不會顯示它。這種限制也解釋了為什麼大多數供應商都有_ID為每個表的列。

Getting data from query results 獲取數據的查詢結果

Rather than simply displaying query results, you can use them for other tasks. For example, you can retrieve spellings from the user dictionary and then look them up in other providers. To do this, you iterate over the rows in theCursor:

而不是簡單地顯示查詢結果,您可以使用它們為其他任務。例如,您可以從用戶檢索拼寫字典,然後看他們在其他供應商。要做到這一點,您遍歷游標的行:

// 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, the
  * "row pointer" is -1, and if you try to retrieve data at that position you will get an
  * 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.
}

Cursorimplementations contain several "get" methods for retrieving different types of data from the object. For example, the previous snippet usesgetString(). They also have agetType()method that returns a value indicating the data type of the column.

游標實現包含多個“獲得”的方法獲取不同類型的數據對象。例如,前面的代碼片段使用getString()。他們也有一個方法()方法,它返回一個值指示該列的數據類型。

Content Provider Permissions


A provider's application can specify permissions that other applications must have in order to access the provider's data. These permissions ensure that the user knows what data an application will try to access. Based on the provider's requirements, other applications request the permissions they need in order to access the provider. End users see the requested permissions when they install the application.

提供商的應用程序可以指定權限,其他應用程序必須以訪問提供者的數據。這些權限,確保用戶知道數據應用程序將嘗試訪問。根據供應商的要求,其他應用程序請求所需的權限來訪問提供者。最終用戶安裝應用程序時看到請求的權限。

If a provider's application doesn't specify any permissions, then other applications have no access to the provider's data. However, components in the provider's application always have full read and write access, regardless of the specified permissions.

As noted previously, the User Dictionary Provider requires theandroid.permission.READ_USER_DICTIONARYpermission to retrieve data from it. The provider has the separateandroid.permission.WRITE_USER_DICTIONARYpermission for inserting, updating, or deleting data.

如果一個供應商的應用程序不指定任何權限,然後其他應用程序沒有對提供者的數據的訪問。然而,組件提供商的應用程序總是完整的讀和寫訪問,無論指定的權限。
如前所述,用戶詞典提供程序需要android.permission。READ_USER_DICTIONARY許可從中檢索數據。供應商有android.permission分開。WRITE_USER_DICTIONARY允許插入、更新或刪除數據。

To get the permissions needed to access a provider, an application requests them with aelement 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.

獲得所需的權限訪問提供者,一個應用程序請求他們< uses-permission >元素的清單文件。Android包管理器安裝應用程序時,用戶必須批准所有的應用程序請求的權限。如果用戶批准所有的包管理器繼續安裝;如果用戶不批准,包管理器中止安裝。

The followingelement requests read access to the User Dictionary Provider:

以下< uses-permission >元素請求讀訪問權的用戶詞典提供程序:

  

The impact of permissions on provider access is explained in more detail in theSecurity and Permissionsguide.

提供者訪問權限的影響將更加詳細地解釋安全和權限指南。

Inserting, Updating, and Deleting Data


In the same way that you retrieve data from a provider, you also use the interaction between a provider client and the provider'sContentProviderto modify data. You call a method ofContentResolverwith arguments that are passed to the corresponding method ofContentProvider. The provider and provider client automatically handle security and inter-process communication.

以同樣的方式,你從提供者檢索數據,您還可以使用提供者之間的交互的客戶端和提供者的ContentProvider修改數據。您調用ContentResolver方法參數傳遞到相應的方法的內容提供者。提供者和提供者端自動處理安全與進程間通信。

Inserting data

To insert data into a provider, you call theContentResolver.insert()method. This method inserts a new row into the provider and returns a content URI for that row. This snippet shows how to insert a new word into the User Dictionary Provider:

將數據插入一個提供者,你叫ContentResolver.insert()方法。這種方法將一個新行插入該行的內容提供者和返回一個URI。這個代碼片段展示了如何將一個新單詞插入到用戶詞典提供程序:

// Defines a new Uri object that receives the result of the insertion
Uri mNewUri;

...

// Defines an object to contain the new values to insert
ContentValues mNewValues = new ContentValues();

/*
* Sets the values of each column and inserts the word. The arguments to the "put"
* method are "column name" and "value"
*/
mNewValues.put(UserDictionary.Words.APP_ID, "example.user");
mNewValues.put(UserDictionary.Words.LOCALE, "en_US");
mNewValues.put(UserDictionary.Words.WORD, "insert");
mNewValues.put(UserDictionary.Words.FREQUENCY, "100");

mNewUri = getContentResolver().insert(
  UserDictionary.Word.CONTENT_URI,  // the user dictionary content URI
  mNewValues             // the values to insert
);

The data for the new row goes into a singleContentValuesobject, which is similar in form to a one-row 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 tonullusingContentValues.putNull().

的數據進入一個新行ContentValues對象,在形式上類似於一行光標。這個對象不需要的列有相同的數據類型,如果你不想指定一個值,您可以使用ContentValues.putNull列設置為null()。

The snippet doesn't add the_IDcolumn, because this column is maintained automatically. The provider assigns a unique value of_IDto every row that is added. Providers usually use this value as the table's primary key.

代碼片段不添加_ID列,因為這列是自動維護。_ID的提供者分配一個獨特的價值,每一行添加。供應商通常使用該值作為表的主鍵。

The content URI returned innewUriidentifies the newly-added row, with the following format:

內容的URI中返回(newUri識別新添加的行,使用以下格式:

content://user_dictionary/words/

Theis the contents of_IDfor the new row. Most providers can detect this form of content URI automatically and then perform the requested operation on that particular row.

< id_value >的內容是_ID新行。大多數提供者可以探測到這種形式的內容自動URI,然後執行所請求的操作,特定的行。

To get the value of_IDfrom the returnedUri, callContentUris.parseId().

獲得的價值_ID從返回的Uri,叫ContentUris.parseId()。

Updating data

To update a row, you use aContentValuesobject 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 isContentResolver.update(). You only need to add values to theContentValuesobject for columns you're updating. If you want to clear the contents of a column, set the value tonull.

更新一行,您使用一個ContentValues對象與更新的值就像你插入,和選擇標准,正如你查詢。客戶端使用方法ContentResolver.update()。你只需要將值添加到ContentValues對象列你更新。如果你想清楚的列的內容,將值設置為null。

The following snippet changes all the rows whose locale has the language "en" to a have a locale ofnull. The return value is the number of rows that were updated:

以下代碼片段變化的地區語言的所有行“en”有一個空的區域。返回值是被更新的行數:

// Defines an object to contain the updated values
ContentValues mUpdateValues = new ContentValues();

// Defines selection criteria for the rows you want to update
String mSelectionClause = UserDictionary.Words.LOCALE + "LIKE ?";
String[] mSelectionArgs = {"en_%"};

// Defines a variable to contain the number of updated rows
int mRowsUpdated = 0;

...

/*
* Sets the updated value and updates the selected words.
*/
mUpdateValues.putNull(UserDictionary.Words.LOCALE);

mRowsUpdated = getContentResolver().update(
  UserDictionary.Words.CONTENT_URI,  // the user dictionary content URI
  mUpdateValues            // the columns to update
  mSelectionClause          // the column to select on
  mSelectionArgs           // the value to compare to
);

You should also sanitize user input when you callContentResolver.update(). To learn more about this, read the sectionProtecting against malicious input.

你也應該當你叫ContentResolver.update清潔用戶輸入()。要了解更多,請閱讀部分防止惡意的輸入。

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 deletes rows whose appid matches "user". The method returns the number of deleted rows.

刪除行類似於檢索行數據:你指定行你想刪除的選擇標准和客戶方法返回刪除的行數。以下代碼片段刪除行appid匹配的“用戶”。該方法返回刪除的行數。
// Defines selection criteria for the rows you want to delete
String mSelectionClause = UserDictionary.Words.APP_ID + " LIKE ?";
String[] mSelectionArgs = {"user"};

// Defines a variable to contain the number of rows deleted
int mRowsDeleted = 0;

...

// Deletes the words that match the selection criteria
mRowsDeleted = getContentResolver().delete(
  UserDictionary.Words.CONTENT_URI,  // the user dictionary content URI
  mSelectionClause          // the column to select on
  mSelectionArgs           // the value to compare to
);

You should also sanitize user input when you callContentResolver.delete(). To learn more about this, read the sectionProtecting against malicious input.

你也應該當你叫ContentResolver.delete清潔用戶輸入()。要了解更多,請閱讀部分防止惡意的輸入。

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 64KB byte array. You can see the available data types by looking at theCursorclass "get" methods.

另一個供應商經常使用的數據類型是二進制大對象(BLOB)實現為一個64 kb的字節數組。你可以看到可用的數據類型通過查看光標類“獲得”方法。

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 classUserDictionary.Words(contract classes are described in the sectionContract Classes). You can also determine the data type by callingCursor.getType().

每一列的數據類型提供者通常列在其文檔。數據類型為用戶詞典提供程序中列出UserDictionary合同類的參考文檔。單詞(合同類所描述的部分合同類)。您也可以通過調用Cursor.getType確定數據類型()。

Providers also maintain MIME data type information for each content URI they define. You can use the MIME type information to find out if your application can handle data that the provider offers, or to choose a type of handling based on the MIME type. You usually need the MIME type when you are working with a provider that contains complex data structures or files. For example, theContactsContract.Datatable in the Contacts Provider uses MIME types to label the type of contact data stored in each row. To get the MIME type corresponding to a content URI, callContentResolver.getType().

提供者也維護MIME數據類型信息為每個URI定義內容。您可以使用MIME類型信息找出如果您的應用程序可以處理的數據提供者提供,或選擇一個類型的處理基於MIME類型。你通常需要MIME類型正在與一個提供者,其中包含復雜的數據結構或文件。例如,ContactsContract。數據表中的聯系人提供程序使用MIME類型標簽接觸每一行中存儲的數據的類型。MIME類型的對應內容URI,叫ContentResolver.getType()。

The sectionMIME Type Referencedescribes the syntax of both standard and custom MIME types.

MIME類型引用部分描述的語法標准和定制的MIME類型。

Alternative Forms of Provider Access


Three alternative forms of provider access are important in application development:

三個可選形式的提供者訪問是重要的在應用程序開發:

  • Batch access: You can create a batch of access calls with methods in theContentProviderOperationclass, and then apply them withContentResolver.applyBatch().
  • 批量訪問:您可以創建一個批處理ContentProviderOperation訪問調用方法的類,然後將它們應用ContentResolver.applyBatch()。
  • Asynchronous queries: You should do queries in a separate thread. One way to do this is to use aCursorLoaderobject. The examples in theLoadersguide demonstrate how to do this.
  • 你要做異步查詢:查詢在一個單獨的線程。一種方法是使用一個CursorLoader對象。加載器指南中的示例演示如何做到這一點。
  • Data access via intents: Although you can't send an intent directly to a provider, you can send an intent to the provider's application, which is usually the best-equipped to modify the provider's data.
  • 數據訪問通過意圖:雖然你不能發送一個意圖直接提供者,您可以發送一個意圖提供者的應用程序中,這通常是裝備修改提供者的數據。

Batch access and modification via intents are described in the following sections.

批通過意圖訪問和修改以下部分中描述。

Batch access

Batch access to a provider is useful for inserting a large number of rows, or for inserting rows in multiple tables in the same method call, or in general for performing a set of operations across process boundaries as a transaction (an atomic operation).

批量訪問提供者用於插入大量的行,或者在多個表中插入行相同的方法調用,或一般跨進程執行的一組操作作為一個事務(一個原子操作)。

To access a provider in "batch mode", you create an array ofContentProviderOperationobjects and then dispatch them to a content provider withContentResolver.applyBatch(). You pass the content provider'sauthorityto this method, rather than a particular content URI. This allows eachContentProviderOperationobject in the array to work against a different table. A call toContentResolver.applyBatch()returns an array of results.

訪問供應商在“批處理模式”,你創建ContentProviderOperation對象數組,然後分派到內容提供商與ContentResolver.applyBatch()。您通過此方法的內容提供者的權威,而不是一個特定的內容URI。這允許每個ContentProviderOperation對象數組中針對不同的工作表。調用ContentResolver.applyBatch()返回一個數組的結果。

The description of theContactsContract.RawContactscontract class includes a code snippet that demonstrates batch insertion. TheContact Managersample application contains an example of batch access in itsContactAdder.javasource file.

ContactsContract的描述。RawContacts合同類包含一個代碼片段,展示了批量插入。聯系人管理器的示例應用程序包含一個例子ContactAdder批訪問。java源文件。

Displaying data using a helper app

If your applicationdoeshave access permissions, you still may want to use an intent to display data in another application. For example, the Calendar application accepts anACTION_VIEWintent, which displays a particular date or event. This allows you to display calendar information without having to create your own UI. To learn more about this feature, see theCalendar Providerguide.

如果您的應用程序有訪問權限,你仍然可能想要使用一個意圖在另一個應用程序來顯示數據。例如,日歷應用程序接受一個ACTION_VIEW意圖,它顯示一個特定的日期或事件。這允許您顯示日歷信息,而不必創建您自己的用戶界面。更多地了解這一特性,看到日歷提供指南。

The application to which you send the intent doesn't have to be the application associated with the provider. For example, you can retrieve a contact from the Contact Provider, then send anACTION_VIEWintent containing the content URI for the contact's image to an image viewer.

您的應用程序發送目的不一定要與提供者相關聯的應用程序。例如,您可以檢索一個聯系人的聯系供應商,然後發送一個ACTION_VIEW意圖包含URI的內容聯系到一個圖像查看器的形象。

Data access via intents

Intents can provide indirect access to a content provider. You allow the user to access data in a provider even if your application doesn't have access permissions, either by getting a result intent back from an application that has permissions, or by activating an application that has permissions and letting the user do work in it.

意圖可以提供間接訪問內容提供者。你允許用戶訪問數據的應用程序提供者即使沒有訪問權限,通過獲得一個結果意圖從一個應用程序,該應用程序權限,或通過激活的應用程序的權限,讓用戶完成工作。

Getting access with temporary permissions

You can access data in a content provider, even if you don't have the proper access permissions, by sending an intent to an application that does have the permissions and receiving back a result intent containing "URI" permissions. These are permissions for a specific content URI that last until the activity that receives them is finished. The application that has permanent permissions grants temporary permissions by setting a flag in the result intent:

您可以訪問的數據在一個內容提供者,即使你沒有適當的訪問權限,通過發送一個意圖有權限的應用程序和接收返回結果的意圖包含“URI”權限。這些權限具體內容URI持續到接收完成他們的活動。永久權限授予臨時權限的應用程序通過設置一個標記在結果的意圖:

  • Read permission:FLAG_GRANT_READ_URI_PERMISSION
  • Write permission:FLAG_GRANT_WRITE_URI_PERMISSION

Note:These flags don't give general read or write access to the provider whose authority is contained in the content URI. The access is only for the URI itself.

注意:這些旗幟不給一般讀或寫訪問提供者的權威是URI中包含的內容。的訪問只是URI本身。

A provider defines URI permissions for content URIs in its manifest, using theandroid:grantUriPermissionattribute of theelement, as well as thechild element of theelement. The URI permissions mechanism is explained in more detail in theSecurity and Permissionsguide, in the section "URI Permissions".

提供者定義URI URI的權限內容清單,使用android:grantUriPermission <供應商>元素的屬性,以及< grant-uri-permission > <供應商>元素的子元素。URI的權限機制更詳細地解釋在安全性和權限指引,在部分“URI權限”。

For example, you can retrieve data for a contact in the Contacts Provider, even if you don't have theREAD_CONTACTSpermission. You might want to do this in an application that sends e-greetings to a contact on his or her birthday. Instead of requestingREAD_CONTACTS, which gives you access to all of the user's contacts and all of their information, you prefer to let the user control which contacts are used by your application. To do this, you use the following process:

例如,您可以檢索數據的接觸聯系供應商,即使你沒有READ_CONTACTS許可。你可能想這樣做在一個應用程序,該應用程序發送e-greetings聯系在他或她的生日。而不是請求READ_CONTACTS,它給你訪問所有用戶的接觸和他們所有的信息,你喜歡讓用戶控制哪些聯系人使用您的應用程序。要做到這一點,您使用以下過程:

  1. Your application sends an intent containing the actionACTION_PICKand the "contacts" MIME typeCONTENT_ITEM_TYPE, using the methodstartActivityForResult().
  2. 您的應用程序發送一個包含動作的意圖ACTION_PICK CONTENT_ITEM_TYPE“聯系人”MIME類型,使用方法startActivityForResult()。
  3. Because this intent matches the intent filter for the People app's "selection" activity, the activity will come to the foreground.
  4. 因為這個目的與意圖過濾器匹配的人應用的“選擇”的活動,活動將出現在前台。
  5. In the selection activity, the user selects a contact to update. When this happens, the selection activity callssetResult(resultcode, intent)to set up a intent to give back to your application. The intent contains the content URI of the contact the user selected, and the "extras" flagsFLAG_GRANT_READ_URI_PERMISSION. These flags grant URI permission to your app to read data for the contact pointed to by the content URI. The selection activity then callsfinish()to return control to your application.
  6. 在選擇活動,用戶選擇一個聯系人更新。當這一切發生的時候,選擇活動callssetResult(resultcode意圖)建立一個意圖回饋您的應用程序。目的包含的內容URI聯系用戶選中,和“臨時演員”旗幟FLAG_GRANT_READ_URI_PERMISSION。這些旗幟格蘭特URI允許應用程序讀取數據的接觸URI指向的內容。選擇活動然後調用完成()返回控制您的應用程序。
  7. Your activity returns to the foreground, and the system calls your activity'sonActivityResult()method. This method receives the result intent created by the selection activity in the People app.
  8. 活動回到前台,和系統調用活動的onActivityResult()方法。這個方法接收結果的意圖由人民選擇活動應用程序。
  9. With the content URI from the result intent, you can read the contact's data from the Contacts Provider, even though you didn't request permanent read access permission to the provider in your manifest. You can then get the contact's birthday information or his or her email address and then send the e-greeting.
  10. 內容從結果URI的意圖,你可以閱讀從聯系人聯系的數據提供者,即使你沒有請求永久讀訪問權限清單中的供應商。然後您可以獲取聯系人的生日信息或他或她的電子郵件地址,然後發送e-greeting。

Using another application

A simple way to allow the user to modify data to which you don't have access permissions is to activate an application that has permissions and let the user do the work there.

一個簡單的方法,以允許用戶修改數據,你沒有訪問權限是激活的應用程序的權限,讓用戶做這項工作。

For example, the Calendar application accepts anACTION_INSERTintent, which allows you to activate the application's insert UI. You can pass "extras" data in this intent, which the application uses to pre-populate the UI. Because recurring events have a complex syntax, the preferred way of inserting events into the Calendar Provider is to activate the Calendar app with anACTION_INSERTand then let the user insert the event there.

例如,日歷應用程序接受一個ACTION_INSERT意圖,它允許您啟動應用程序的UI插入。你可以通過“臨時演員”數據在這個意圖,該應用程序使用預填充UI。因為重復事件有一個復雜的語法,將事件插入日歷提供者的首選方法是激活anACTION_INSERT的日歷應用程序,然後讓用戶插入事件。

Contract Classes


A contract class defines constants that help applications work with the content URIs, column names, intent actions, and other features of a content provider. Contract classes are not included automatically with a provider; the provider's developer has to define them and then make them available to other developers. Many of the providers included with the Android platform have corresponding contract classes in the packageandroid.provider.

合同類定義常量,幫助應用程序與內容uri,列名,意圖行動,內容提供商和其他特性。合同類不包括自動與提供者;提供者的開發人員定義他們,然後讓他們提供給其他開發人員。許多Android平台的提供者包括類的包android.provider相應合同。

For example, the User Dictionary Provider has a contract classUserDictionarycontaining content URI and column name constants. The content URI for the "words" table is defined in the constantUserDictionary.Words.CONTENT_URI. TheUserDictionary.Wordsclass also contains column name constants, which are used in the example snippets in this guide. For example, a query projection can be defined as:

例如,用戶詞典提供程序有一個合同類UserDictionary URI和列名稱常量包含內容。URI的內容“單詞”表中定義的常數UserDictionary.Words.CONTENT_URI。UserDictionary。文字類還包含列名常量,用於本指南中的示例代碼片段。例如,一個查詢投影可以定義為:

String[] mProjection =
{
  UserDictionary.Words._ID,
  UserDictionary.Words.WORD,
  UserDictionary.Words.LOCALE
};

Another contract class isContactsContractfor the Contacts Provider. The reference documentation for this class includes example code snippets. One of its subclasses,ContactsContract.Intents.Insert, is a contract class that contains constants for intents and intent data.

另一個合同類是接觸ContactsContract提供者。這個類的參考文檔包括示例代碼片段。它的一個子類,ContactsContract.Intents。插入、是一個合同類,包含意圖和目的的常量數據。

MIME Type Reference


Content providers can return standard MIME media types, or custom MIME type strings, or both.

MIME types have the format

內容提供者可以返回標准的MIME媒體類型,或自定義MIME類型字符串,或兩者兼而有之。
MIME類型的格式

type/subtype

For example, the well-known MIME typetext/htmlhas thetexttype and thehtmlsubtype. If the provider returns this type for a URI, it means that a query using that URI will return text containing HTML tags.

例如,著名的MIME類型text / html文本類型和子類型的html。如果提供者返回這種類型的URI,它意味著一個查詢使用這個URI將返回包含HTML標記文本。

Custom MIME type strings, also called "vendor-specific" MIME types, have more complextypeandsubtypevalues. Thetypevalue is always

定制的MIME類型字符串,也稱為“特定於供應商的”MIME類型,有更復雜的類型和子類型值。值類型總是

vnd.android.cursor.dir

for multiple rows, or

vnd.android.cursor.item

for a single row.

單個行。

Thesubtypeis provider-specific. The Android built-in providers usually have a simple subtype. For example, the when the Contacts application creates a row for a telephone number, it sets the following MIME type in the row:

特定於提供程序的子類型。Android內置提供者通常有一個簡單的亞型。例如,當聯系人應用程序創建一行電話號碼,它集以下行MIME類型:

vnd.android.cursor.item/phone_v2

Notice that the subtype value is simplyphone_v2.

注意,只是phone_v2子類型值。

Other provider developers may create their own pattern of subtypes based on the provider's authority and table names. For example, consider a provider that contains train timetables. The provider's authority iscom.example.trains, and it contains the tables Line1, Line2, and Line3. In response to the content URI

其他供應商開發人員可以創建自己的模式基於提供者的亞型的權威和表名。例如,考慮一個提供者包含列車時刻表。是com.example提供者的權威。火車,它包含表Line1期,Line3。為了應對內容URI

content://com.example.trains/Line1

for table Line1, the provider returns the MIME type

對於表Line1,提供者返回的MIME類型

vnd.android.cursor.dir/vnd.example.line1

In response to the content URI

為了應對內容URI

content://com.example.trains/Line2/5

for row 5 in table Line2, the provider returns the MIME type

表5為行Line2,提供者返回的MIME類型

vnd.android.cursor.item/vnd.example.line2

Most content providers define contract class constants for the MIME types they use. The Contacts Provider contract classContactsContract.RawContacts, for example, defines the constantCONTENT_ITEM_TYPEfor the MIME type of a single raw contact row.

大部分內容提供商為MIME類型定義合同類常量。聯系人ContactsContract提供者契約類。RawContacts,例如,定義了常數CONTENT_ITEM_TYPE MIME類型的單個原始行聯系。

Content URIs for single rows are described in the sectionContent URIs.

內容uri uri單一行部分所描述的內容。

Except as noted, this content is licensed underCreative Commons Attribution 2.5. For details and restrictions, see theContent License. 除了如上所述,這個內容是2.5使用Creative Commons許可的歸因。和限制的詳細信息,請參見內容許可證。

About Android|Legal|Support


  1. 上一頁:
  2. 下一頁:
熱門文章
閱讀排行版
Copyright © Android教程網 All Rights Reserved