android.provider
package. You can query these providers for the data they contain (although, for some, you must acquire the proper permission to read the data).
android.provider
包中看到.你能夠內容提供者所包含的數據(可是,對於某些數據,你須要取得相應的數據讀取權限)
ContentProvider
subclass) or you can add the data to an existing provider — if there's one that controls the same type of data and you have permission to write to it.
ContentProvider
子類),或者把數據加入到已存在的內空提供者— (若是有一個)控制數據的一樣的類型並你有權限寫入它.(很差翻譯)
ContentResolver
objects. You get a ContentResolver by calling
getContentResolver()
from within the implementation of an Activity or other application component:
ContentResolver
對象.
你能夠在活動的實現或者其餘應用組件,
調用getContentResolver()
方法,
獲得一個內容解釋者.
ContentResolver cr = getContentResolver();
_ID
|
NUMBER
|
NUMBER_KEY
|
LABEL
|
NAME
|
TYPE
|
13
|
(425) 555 6677
|
425 555 6677
|
Kirkland office
|
Bully Pulpit
|
TYPE_WORK
|
44
|
(212) 555-1234
|
212 555 1234
|
NY apartment
|
Alan Vain
|
TYPE_HOME
|
45
|
(212) 555-6657
|
212 555 6657
|
Downtown office
|
Alan Vain
|
TYPE_MOBILE
|
53
|
201.555.4433
|
201 555 4433
|
Love Nest
|
Rex Cars
|
TYPE_HOME
|
_ID
field that uniquely identifies the record within the table. IDs can be used to match records in related tables — for example, to find a person's phone number in one table and pictures of that person in another.
Cursor
object that can move from record to record and column to column to read the contents of each field. It has specialized methods for reading each type of data. So, to read a field, you must know what type of data the field contains. (There's more on query results and Cursor objects later.)
Cursor
對象,
該對象能夠從一個記錄移動到另外一個記錄,
而且能夠列的形式讀取每一個域的內容.
它有讀取每種數據類型的特殊方法.
因此,
要讀取一個域,
你必須知道該域包括的數據是什麼類型.(
後面有更多關於Cursor
對象和查詢結果的討論)
Uri
object) that uniquely identifies its data set. A content provider that controls multiple data sets (multiple tables) exposes a separate URI for each one. All URIs for providers begin with the string "
content://
". The
content:
scheme identifies the data as being controlled by a content provider.
Uri
對象包裹起來
),它是數據集的標識.一個內容提供者控制多個數據集合(多個表格),並把每個解釋成一個獨立的URI.內容提供者的全部的URIs都以字串"
content://
"開始。內容:cheme identifies the data as being controlled by a content provider.
CONTENT_URI
constants for all the providers that come with the platform. For example, the URI for the table that matches phone numbers to people and the URI for the table that holds pictures of people (both controlled by the Contacts content provider) are:
CONTENT_URI
常量.好比,匹配某人電話的表格的URI,匹配某人所捅有的圖片的URI(它們都由內通訊錄內容提供者所控制)
android.provider.Contacts.Phones.CONTENT_URI
android.provider.Contacts.Photos.CONTENT_URI
ContentResolver
method takes the URI as its first argument. It's what identifies which provider the ContentResolver should talk to and which table of the provider is being targeted.
ContentResolver
方法,都把它當成第一個參數。它指定了內容解釋者與那個內容提供者對話,內容提供者定位到那個表格。
ContentResolver.query()
method or the
Activity.managedQuery()
method. Both methods take the same set of arguments, and both return a Cursor object. However,
managedQuery()
causes the activity to manage the life cycle of the Cursor. A managed Cursor handles all of the niceties, such as unloading itself when the activity pauses, and requerying itself when the activity restarts. You can ask an Activity to begin managing an unmanaged Cursor object for you by calling
Activity.startManagingCursor()
.
ContentResolver.query()
方法,或者
Activity.managedQuery()
方法。它們都採用同相樣的參數集,並都返回一個Cursor對象。可是,方法致使活動管理Cursor的生命週期。一個管理的Cursor處理全部的細節,好比當活動暫停時不加載它本身,當活動從新啓動時,從新查詢它本身。你能夠調用
Activity.startManagingCursor()
方法,要求活動管理沒有管理的Cursor對象。
query()
or
managedQuery()
is the provider URI — the
CONTENT_URI
constant that identifies a particular ContentProvider and data set (see
URIs earlier).
_ID
value for that record to the URI — that is, place a string matching the ID as the last segment of the path part of the URI. For example, if the ID is 23, the URI would be:
content://. . . ./23
ContentUris.withAppendedId()
and
Uri.withAppendedPath()
, that make it easy to append an ID to a URI. Both are static methods that return a Uri object with the ID added. So, for example, if you were looking for record 23 in the database of people contacts, you might construct a query as follows:
ContentUris.withAppendedId()
方法和
Uri.withAppendedPath()
方法,它們使得追加ID到URI更加容易。它們都是靜態方法,而且返回一個帶追加ID的Uri對象。因此若是,你要在通訊錄數據庫中查詢記錄23,你可能會這樣構建一個查詢:
import android.provider.Contacts.People;
import android.content.ContentUris;
import android.net.Uri;
import android.database.Cursor;
// Use the ContentUris method to produce the base URI for the contact with _ID == 23.
//使用方法,產生一個基於Uri且通訊錄_ID等於23的。
Uri myPerson = ContentUris.withAppendedId(People.CONTENT_URI, 23);
// Alternatively, use the Uri method to produce the base URI.
// It takes a string rather than an integer.
// 一個可選方法,用Uri方法,產生一個基於URI的,它採用字串,而不是一個整型值
Uri myPerson = Uri.withAppendedPath(People.CONTENT_URI, "23");
// Then query for this specific record:查詢這個指定的記錄:
Cursor cur = managedQuery(myPerson, null, null, null, null);
query()
and
managedQuery()
methods delimit the query in more detail. They are:
null
value returns all columns. Otherwise, only columns that are listed by name are returned. All the content providers that come with the platform define constants for their columns. For example, the
android.provider.Contacts.Phones
class defines constants for the names of the columns in the phone table illustrated earlier —
_ID
,
NUMBER
,
NUMBER_KEY
,
NAME
, and so on.
android.provider.Contacts.Phones
定義了上電話面圖表中的列名的常量
—ID, NUMBER, NUMBER_KEY, NAME,
等等。
WHERE
clause (excluding the
WHERE
itself). A
null
value returns all rows (unless the URI limits the query to a single record).
ORDER BY
clause (excluding the
ORDER BY
itself). A
null
value returns the records in the default order for the table, which may be unordered.
ORDER BY
它本身),一個空值返回表格中記錄的默認順序,多是無序的。
import android.provider.Contacts.People;
import android.database.Cursor;
// Form an array specifying which columns to return. 經過一個數組指定要返回的列
String[] projection = new String[] {
People._ID,
People._COUNT,
People.NAME,
People.NUMBER
};
// Get the base URI for the People table in the Contacts content provider.
Uri contacts = People.CONTENT_URI;
// Make the query.
Cursor managedCursor = managedQuery(contacts,
projection, // Which columns to return 要返回那些列
null, // Which rows to return (all rows)返回的行(全部行)
null, // Selection arguments (none)(可選參數,無)
// Put the results in ascending order by name(以名字降序排列)
People.NAME + " ASC");
_COUNT
field of each record.
_COUNT
域的,記錄值。
_ID
and
_COUNT
in
BaseColumns
,
NAME
in
PeopleColumns
, and
NUMBER
in
PhoneColumns
. The
Contacts.People
class implements each of these interfaces, which is why the code example above could refer to them using just the class name.
_ID
和
_COUNT
基於
BaseColumns
,
NAME
在
PeopleColumns, NUMBER
在
PhoneColumns.
類Contacts.People
實現了這些接口,這也是爲何上面例子代碼中只使用一個類名就能夠引用它們的緣由。
_ID
column, which holds a unique numeric ID for each record. Every provider can also report the number of records returned as the
_COUNT
column; its value is the same for all rows.
_COUNT
列,它的值對全部的行都是同樣的。
_ID
|
_COUNT
|
NAME
|
NUMBER
|
44
|
3
|
Alan Vain
|
212 555 1234
|
13
|
3
|
Bully Pulpit
|
425 555 6677
|
53
|
3
|
Rex Cars
|
201 555 4433
|
Cursor
object that can be used to iterate backward or forward through the result set. You can use this object only to read the data. To add, modify, or delete data, you must use a ContentResolver object.
Cursor
對象解釋,它能夠向後或向前迭代記錄集。你只能用這個對象讀取數據,要添加,修改,或者刪除數據,你必需要用一個ContentResolver 內容解釋對象。
getString()
,
getInt()
, and
getFloat()
. (However, for most types, if you call the method for reading strings, the Cursor object will give you the String representation of the data.) The Cursor lets you request the column name from the index of the column, or the index number from the column name.
getString()
,
getInt()
, 和
getFloat().(
然而,大多數類型,若是你調用讀字串方法,Cursor
對象將給一個該數據所表示的字串值)
,Cursor
對象可以讓你從列索引讀取列名,或者從列名讀取列索引
import android.provider.Contacts.People;
private void getColumnData(Cursor cur){
if (cur.moveToFirst()) {
String name;
String phoneNumber;
int nameColumn = cur.getColumnIndex(People.NAME);
int phoneColumn = cur.getColumnIndex(People.NUMBER);
String p_w_picpathPath;
do {
// Get the field values
name = cur.getString(nameColumn);
phoneNumber = cur.getString(phoneColumn);
// Do something with the values.
...
} while (cur.moveToNext());
}
}
content:
URI that you can use to get the data. In general, smaller amounts of data (say, from 20 to 50K or less) are most often directly entered in the table and can be read by calling
Cursor.getBlob()
. It returns a byte array.
Cursor.getBlob()
讀取。它返回一個字節數組。
content:
URI, you should never try to open and read the file directly (for one thing, permissions problems can make this fail). Instead, you should call
ContentResolver.openInputStream()
to get an
InputStream
object that you can use to read the data.
ContentResolver.openInputStream()
方法,獲取一個輸入流
InputStream
對象,來讀取數據。
ContentResolver
methods. Some content providers require a more restrictive permission for writing data than they do for reading it. If you don't have permission to write to a content provider, the ContentResolver methods will fail.
ContentResolver
方法完成。一些內容提供者寫入數據比讀取數據要求更多的權限。若是你沒有寫某個內容提供者的權限,ContentResolver 內容解釋方法將失敗。
ContentValues
object, where each key matches the name of a column in the content provider and the value is the desired value for the new record in that column. Then call
ContentResolver.insert()
and pass it the URI of the provider and the ContentValues map. This method returns the full URI of the new record — that is, the provider's URI with the appended ID for the new record. You can then use this URI to query and get a Cursor over the new record, and to further modify the record. Here's an example:
import android.provider.Contacts.People;
import android.content.ContentResolver;
import android.content.ContentValues;
ContentValues values = new ContentValues();
// Add Abraham Lincoln to contacts and make him a favorite.
values.put(People.NAME, "Abraham Lincoln");
// 1 = the new contact is added to favorites
// 0 = the new contact is not added to favorites
values.put(People.STARRED, 1);
Uri uri = getContentResolver().insert(People.CONTENT_URI, values);
CONTENT_DIRECTORY
constant. The following code continues the previous example by adding a phone number and e-mail address for the record just created:
CONTENT_DIRECTORY
常量。下面的例子,爲一新建立的記錄添加一個電話號和郵件地址。
Uri phoneUri = null;
Uri emailUri = null;
// Add a phone number for Abraham Lincoln. Begin with the URI for
// the new record just returned by insert(); it ends with the _ID
// of the new record, so we don't have to add the ID ourselves.
// Then append the designation for the phone table to this URI,
// and use the resulting URI to insert the phone number.
phoneUri = Uri.withAppendedPath(uri, People.Phones.CONTENT_DIRECTORY);
values.clear();
values.put(People.Phones.TYPE, People.Phones.TYPE_MOBILE);
values.put(People.Phones.NUMBER, "1233214567");
getContentResolver().insert(phoneUri, values);
// Now add an email address in the same way.
emailUri = Uri.withAppendedPath(uri, People.ContactMethods.CONTENT_DIRECTORY);
values.clear();
// ContactMethods.KIND is used to distinguish different kinds of
// contact methods, such as email, IM, etc.
values.put(People.ContactMethods.KIND, Contacts.KIND_EMAIL);
values.put(People.ContactMethods.DATA, "test@example.com");
values.put(People.ContactMethods.TYPE, People.ContactMethods.TYPE_HOME);
getContentResolver().insert(emailUri, values);
ContentValues.put()
that takes a byte array. That would work for a small icon-like p_w_picpath or a short audio clip, for example. However, if you have a large amount of binary data to add, such as a photograph or a complete song, put a
content:
URI for the data in the table and call
ContentResolver.openOutputStream()
with the file's URI. (That causes the content provider to store the data in a file and record the file path in a hidden field of the record.)
ContentValues.put()
方法帶字節數組的版本放置少許2
進制數據。好比,多是圖像的小icon,
或者簡短的音樂剪輯。可是,你若加大量的二進制數據,好比圖形或者完整的歌曲,放入一個內容:放數據的URI
在表格中,
調用使用文件的URI
的ContentResolver.openOutputStream()
方法,(這將致使內容提供者將數據存在一個文件中,而且在記錄的隱藏域記錄文件的路徑)
MediaStore
content provider, the main provider that dispenses p_w_picpath, audio, and video data, employs a special convention: The same URI that is used with
query()
or
managedQuery()
to get meta-information about the binary data (such as, the caption of a photograph or the date it was taken) is used with
openInputStream()
to get the data itself. Similarly, the same URI that is used with
insert()
to put meta-information into a MediaStore record is used with
openOutputStream()
to place the binary data there. The following code snippet illustrates this convention:
MediaStore內容提供者,分發圖像,音頻和視頻數據的主要內容提供者,使用一個特別的慣例: query()方法或者managedQuery()方法使用同一個URI來獲取關於二進制數據的信息(好比:圖片標題,或者它的產生日期),它經常使用openInputStream()方法獲取數據的.一樣,該同一個URI也用於insert()插入信息到MediaStore記錄,而它一般用於openOutputStream()方法把數據放到那裏。
import android.provider.MediaStore.Images.Media;
import android.content.ContentValues;
import java.io.OutputStream;
// Save the name and description of an p_w_picpath in a ContentValues map.
ContentValues values = new ContentValues(3);
values.put(Media.DISPLAY_NAME, "road_trip_1");
values.put(Media.DESCRIPTION, "Day 1, trip to Los Angeles");
values.put(Media.MIME_TYPE, "p_w_picpath/jpeg");
// Add a new record without the bitmap, but with the values just set.
// insert() returns the URI of the new record.
Uri uri = getContentResolver().insert(Media.EXTERNAL_CONTENT_URI, values);
// Now get a handle to the file for that record, and save the data into it.
// Here, sourceBitmap is a Bitmap object representing the file to save to the database.
try {
OutputStream outStream = getContentResolver().openOutputStream(uri);
sourceBitmap.compress(Bitmap.CompressFormat.JPEG, 50, outStream);
outStream.close();
} catch (Exception e) {
Log.e(TAG, "exception while writing p_w_picpath", e);
}
ContentResolver.update()
method with the columns and values to change. 經批處理一組記錄(好比,將」NY」改爲」New York」到全部的域),調用
ContentResolver.update()
方法,帶上列及要改變的值。
ContentResolver.delete()
with the URI of a specific row. 刪除一行,用
ContentResolver.delete()
方法,帶上一個包括指定行的URI
ContentResolver.delete()
with the URI of the type of record to delete (for example,
android.provider.Contacts.People.CONTENT_URI
) and an SQL
WHERE
clause defining which rows to delete. (
Caution
: Be sure to include a valid
WHERE
clause if you're deleting a general type, or you risk deleting more records than you intended!).
ContentResolver.delete()
方法,帶上一個要刪除的記錄的類型,和定義那些行的SQL
WHERE簇
URI(注意:若是你要刪除一個通用的類型,確保包括了一個正確的WHERE簇,不然,你可能刪除的記錄,比你想要刪除的記錄多)
SQLiteOpenHelper
class to help you create a database and
SQLiteDatabase
to manage it. 設置存儲數據的一個系統,大多數內容提供者使用Android的文件存儲數據, 或者SQLite數據庫系統.可是你能夠以你想要的任何方法存儲數據。Android提供了一個
SQLiteOpenHelper
類,幫助你建立一個數據庫,而且用
SQLiteDatabase
管理它.
ContentProvider
subclass to expose your data to others using the conventions expected by ContentResolver and Cursor objects. Principally, this means implementing six abstract methods declared in the ContentProvider class:
query()
insert()
update()
delete()
getType()
onCreate()
query()
method must return a
Cursor
object that can iterate over the requested data. Cursor itself is an interface, but Android provides some ready-made Cursor objects that you can use. For example,
SQLiteCursor
can iterate over data stored in an SQLite database. You get the Cursor object by calling any of the
SQLiteDatabase
class's
query()
methods. There are other Cursor implementations — such as
MatrixCursor
— for data not stored in a database.
query()方法,必須返回一個Cursor對象,而且它能夠迭代請求的數據。
Cursor自己是一個接口.可是Android系統提供一些準備好的 Cursor對象給你使用.好比,
SQLiteCursor能夠迭代存在於SQLite數據庫中的數據。你能夠調用任何一個SQLiteDatabase類的query()方法,獲得一個Cursor對象。還有一些其餘的Cursor實現,
—好比
MatrixCursor
—用於非數據庫存儲的數據。
ContentResolver.notifyChange()
to notify listeners when there are modifications to the data. 出於好意,你可能也想調用
ContentResolver.notifyChange()
方法,通知監聽器數據何時被改變了。
public static final
Uri
named
CONTENT_URI
. This is the string that represents the full
content:
URI that your content provider handles. You must define a unique string for this value. The best solution is to use the fully-qualified class name of the content provider (made lowercase). So, for example, the URI for a TransportationProvider class could be defined as follows:
CONTENT_URI的公共靜態的最終的Uri.這個字串表示你的內容提供者所能處理的全部content:URI.你必須爲這個值指定一個惟一的字串,最好的解決方法是用內容提供者的全類名(由小寫構成),全部,好比,TransportationProvider的URI定義成下面的樣子:
· public static final Uri CONTENT_URI =
Uri.parse("content://com.example.codelab.transportationprovider");
CONTENT_URI
constants for each of the subtables. These URIs should all have the same authority (since that identifies the content provider), and be distinguished only by their paths. For example:
CONTENT_URI常量.這些URIs應都有一樣的認證(由於它標識內容提供者),而且只根據它們的路徑區分,好比:
content://com.example.codelab.transportationprovider/train
content://com.example.codelab.transportationprovider/air/domestic
content://com.example.codelab.transportationprovider/air/international
content:
URIs, see the
Content URI Summary at the end of this document. 想要概覽content:URIs,請看本文檔後面的
Content URI Summary.
public static
String constants that clients can use to specify the columns in queries and other instructions.
_id
" (with the constant
_ID
) for the IDs of the records. You should have this field whether or not you have another field (such as a URL) that is also unique among all records. If you're using the SQLite database, the
_ID
field should be the following type:
INTEGER PRIMARY KEY AUTOINCREMENT [整型,主健,自動增長]
AUTOINCREMENT
descriptor is optional. But without it, SQLite increments an ID counter field to the next number above the largest existing number in the column. If you delete the last row, the next row added will have the same ID as the deleted row.
AUTOINCREMENT
avoids this by having SQLite increment to the next largest value whether deleted or not.
AUTOINCREMENT的描述是可選的。可是若是不帶上該描述,SQLite將在該列存在的最大數值之上,增長一個ID計數。若是我刪除最後一行,下一個增長的行將與刪除的行ID是相同的。AUTOINCREMENT是爲避免這種狀況,不管是否刪除,都在下一個最大值上增長.
ContentProvider.getType()
. The type depends in part on whether or not the
content:
URI submitted to
getType()
limits the request to a specific record. There's one form of the MIME type for a single record and another for multiple records. Use the
Uri
methods to help determine what is being requested. Here is the general format for each type:
ContentProvider.getType()
實現中,返回定義的新MIME類型 。
vnd.android.cursor.item/vnd.
yourcompanyname.contenttype
content://com.example.transportationprovider/trains/122
vnd.android.cursor.item/vnd.example.rail
vnd.android.cursor.dir/vnd.
yourcompanyname.contenttype
content://com.example.transportationprovider/trains
vnd.android.cursor.dir/vnd.example.rail
content:
URI string. This is the field that gives clients access to the data file. The record should also have another field, named "
_data
" that lists the exact file path on the device for that file. This field is not intended to be read by the client, but by the ContentResolver. The client will call
ContentResolver.openInputStream()
on the user-facing field holding the URI for the item. The ContentResolver will request the "
_data
" field for that record, and because it has higher permissions than a client, it should be able to access that file directly and return a read wrapper for the file to the client.
content:
URI字串,這個域給客戶訪問數據文件。這個記錄也應有另外一個域,叫作」_data」,它列出了數據文件在設備上的確切路徑。這個域不是給客戶端讀取的,而是爲內容解釋者提供的。客戶端將調用持有該項URI的面向用戶的
ContentResolver.openInputStream()
方法。ContentResolver將請求「_data」域。因爲它的權限比客戶端高,它應能直接訪問文件,而且返回一個文件的包裹給客戶端.
<provider>
element in the application's AndroidManifest.xml file. Content providers that are not declared in the manifest are not visible to the Android system
<provider>
元素聲明它。沒有在manifest文件中聲明的內容提供者,對Android系統不可見。
name
attribute is the fully qualified name of the ContentProvider subclass. The
authorities
attribute is the authority part of the
content:
URI that identifies the provider. For example if the ContentProvider subclass is AutoInfoProvider, the
<provider>
element might look like this:
Authorities屬性,是指定內容提供者的content:URI的部分認證。好比,如查ContentProvider子類是AutoInfoProvider,它的<provider>元素,多是這樣的:
<provider android:name="com.example.autos.AutoInfoProvider"
android:authorities="com.example.autos.autoinfoprovider"
. . . />
</provider>
authorities
attribute omits the path part of a
content:
URI. For example, if AutoInfoProvider controlled subtables for different types of autos or different manufacturers,
authorities屬性省略了content:
URI的部分路徑。好比,AutoInfoProvider控制不一樣汽車類型和不一樣廠商的子表
content://com.example.autos.autoinfoprovider/honda
content://com.example.autos.autoinfoprovider/gm/compact
content://com.example.autos.autoinfoprovider/gm/suv
<provider>
attributes can set permissions to read and write data, provide for an icon and text that can be displayed to users, enable and disable the provider, and so on. Set the
multiprocess
attribute to "
true
" if data does not need to be synchronized between multiple running versions of the content provider. This permits an instance of the provider to be created in each client process, eliminating the need to perform IPC.
<provider>屬性,能夠設置讀取和寫入數據的權限,給用戶提供一個圖標及文本用來顯示,容許及禁止內容提供者等。若是數據不須要在多個運行的內容提供者之間同步,將multiprocess屬性設爲true.它容許在每一個客戶端進程中建立一個內容提供者的實例,消除了執行IPC的須要.
<provider>
element's
authorities
attribute:
<provider>
元素的
authorities
屬性中。
C. <provider android:name=".TransportationProvider"
D. android:authorities="com.example.transportationprovider"
. . . >
land/bus
", "
land/train
", "
sea/ship
", and "
sea/submarine
" to give four possibilities.
land/bus
", "
land/train
", "
sea/ship
", and "
sea/submarine
"提供了4種可能的值。
_ID
value of the requested record. If the request is not limited to a single record, this segment and the trailing slash are omitted:
content://com.example.transportationprovider/trains