Content Providerベース(一)


目的
l原理
l ContentProviderからのデータ取得
lデータの挿入、更新、削除
 
 
Content Providerの動作原理
l概要
Content Providerは、外部アプリケーションに対してデータ共有の表示形式を提供し、リレーショナル・データベースのテーブル構造と類似しています.たとえば、次のユーザー・辞書のテーブルなどです.各行に1つの単語を表す唯一の情報です.
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
 
l Providerへのアクセス
アプリケーションでContent Providerにアクセスする必要があるデータはContentResolverオブジェクトによって実現されます.Content Providerオブジェクトインスタンスのメソッドは、データの永続化操作のための基本的なCRUDメソッドを提供します.また、これらの操作の目的を達成するためには、manifast fileに対応する権限を提供する必要がある:Content Provider Permissions.
たとえば、Providerのすべてのユーザー単語とlocalesを問い合わせるには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

 
l  Content URIs
content URIは、providerのデータリソースを一意に識別します.各Content URLには、Providerのエントリとデータテーブルのパス(テーブルの列)が含まれています.Providerデータリソースにアクセスするとき、つまりContentResolverを呼び出す方法では、URIがパラメータとして渡されます.たとえば、辞書の単語にアクセスすると、URIは次のように記述されます.
content://user_dictionary/words

 
通常、ある指定行のデータを取得するには、URIに指定行のIDを追加する必要があります.例えば、取得_ID 4の行:
 
Uri singleUri = ContentUri.withAppendedId(UserDictionary.Words.CONTENT_URI,4);//withAppendedId   URI     ID。

providerのデータの取得
lクエリーの構築
1.次の処理を容易にします.次のコード・クリップは、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 = {""};

 
2次のセクションではContentResolverについて説明します.query()の詳細な使用.Providerのクエリーは実際にはSQLと同じ構文を持っています.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
} else if (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

}

上記の機能は、次のクエリ文と似ています.
SELECT _ID, word, frequency, locale FROM words WHERE word = <userinput> ORDER BY word ASC;

 
l悪意のある攻撃とSQL注入の防止
次のコードクリップで、
// Constructs a selection clause by concatenating the user's input to the column name
String mSelectionClause =  "var = " + mUserInput;

 
ユーザーがnothingを入力した場合.DROP TABLE*では、データベースのテーブルがすべて消去されます.
このような結果を避けるために、「?代替例:
 
// Constructs a selection clause with a replaceable parameter
String mSelectionClause =  "var = ?";

 
lデータセットの展示
ContentResolver.Query()クエリは、行ごとにデータに反復アクセスする方法を提供するCursorインスタンスを返します.
一致するクエリ結果がない場合、返されるCursorはgetCount()で0を返します.
異常が発生した場合nullを返します.
Cursorが行単位のレコード列(list of rows)である以上、SimpleCursorAdapterによってデータをバインドするListViewコントロールの形式がより良いことを知っています.例のクリップは次のとおりです.
 
// 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);

 
lデータセットデータの遍歴
 
// 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.
}

 
Cursorは、上記のgetString()のような異なるタイプのデータを取得するための多くの「get」メソッドを提供する.もちろん、getType()メソッドでは、あるカラムのデータ型を取得できます.
データの挿入、更新、削除
lデータの挿入
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
);

 
カラムのデータが空の場合はnullを割り当てるかContentValueを使用することができる.putNull();データを挿入するときに与えられていないことに気づきました.IDは、カラムが自己増加しているため、割り当てられます.必要ないIDの場合は全く不要(ListViewを除く);必要かUriの_ID、ContentUrisを呼び出す.parseId();
 
l更新データ
データの更新はContentResolverに使用する.update();例は次のとおりです.
 
// 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
);

 
lデータの削除
 
データを削除するにはgetContentResolver()を使用します.delete.
 
// 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
);

 
Providerデータ型
Providerは次のデータ型を提供します.
 
text
integer
long integer(long)
floating point(float)
long floating point(double)
Binary Large Object(BLOB)