page.title=コンテンツ プロバイダの作成 @jd:body
コンテンツ プロバイダは、データの中央リポジトリへのアクセスを管理します。Android アプリケーションでは 1 つ以上のクラスとしてプロバイダを実装し、要素をマニフェスト ファイルで実装します。 いずれか 1 つのクラスがサブラス {@link android.content.ContentProvider} を実装します。これは、プロバイダと他のアプリケーションとの間のインターフェースになります。 コンテンツ プロバイダは他のアプリケーションへのデータの提供を意図したものですが、ユーザーがプロバイダに管理されるデータを照会、修正するアクティビティをアプリケーション内に設定することもできます。
このトピックの残りの部分では、コンテンツ プロバイダと使用する API のリストをビルドするための基本的な手順を挙げていきます。
ビルドを開始する前に、次の操作を行います。
完全に独自アプリケーション内だけで使用する場合は、SQLite データベースを使用するプロバイダは必要はありません。
次に、以下の手順に従ってプロバイダをビルドします。
コンテンツ プロバイダは、構造化された形式で保存されているデータへのインターフェースです。インターフェースを作成する前に、データの格納方法を決定しておく必要があります。 データは任意の形式で保存でき、必要に応じてデータの読み取りと書き込みを行うためのインターフェースを設計できます。
Android には、次のように、いくつかのデータ格納テクノロジーがあります。
リポジトリを実装するのに、データベースを使用する必要がありません。外部的には、プロバイダはリレーショナル データベースに似た一連のテーブルとして表示されますが、プロバイダの内部実装をそのような形式にする必要はありません。
次に、プロバイダのデータ構造を設計する際のヒントを示します。
_ID
になっている必要があるため、{@link android.provider.BaseColumns#_ID BaseColumns._ID} を使用することをお勧めします。
さらに、BLOB を使用してスキーマに依存しないテーブルを実装できます。このタイプのテーブルでは、プライマリキー列、MIME タイプ列、1 つ以上の汎用列を BLOB として定義します。 BLOB 列内のデータの内容は、MIME タイプ列の値によって示されます。 これにより、同じテーブルにさまざまな行タイプを格納できます。 連絡先プロバイダの「データ」テーブル {@link android.provider.ContactsContract.Data} は、スキーマに依存しないテーブルの例です。
コンテンツ URI は、プロバイダのデータを特定する URI です。コンテンツ URI には、プロバイダ全体の識別名(認証局)とテーブルやファイルをポイントする名前(パス)が含まれます。 オプションの ID 部分は、テーブル内の個々の行を指します。 {@link android.content.ContentProvider} のそれぞれのデータアクセス メソッドは引数としてコンテンツ URI を使用します。これにより、アクセスするテーブル、行、ファイルを決定できます。
コンテンツ URI の基本については、「コンテンツ プロバイダの基本」トピックをご覧ください。
通常、プロバイダは、Android 内部の名前として使用される認証局を 1 つ持ちます。他のプロバイダとの競合を避けるためには、(逆に)プロバイダの認証局の基礎としてインターネット ドメインの所有権を使用する必要があります。
この推奨事項は Android パッケージ名にもあてはまるため、プロバイダを含むパッケージの名前の拡張子として、プロバイダの認証局を定義できます。
たとえば、Android パッケージ名が com.example.<appname>
の場合、プロバイダに認証局 com.example.<appname>.provider
を付与する必要があります。
デベロッパーは通常、個々のテーブルを指すパスを末尾に追加して認証局からコンテンツ URI を作成します。
たとえば、table1 と table2 の 2 つのテーブルがある場合、前の例の認証局を組み合わせてコンテンツ URI com.example.<appname>.provider/table1
と com.example.<appname>.provider/table2
を作成します。
パスは 1 つのセグメントに限定されず、パスの各レベルにテーブルを作成する必要はありません。
慣例として、URI の末尾にある行の ID 値を持つコンテンツ URI を受け取ることで、プロバイダはテーブル内の 1 つの行へのアクセスを提供します。さらに、慣例として、プロバイダは ID 値をテーブルの _ID
列とマッチングし、一致する行に対して要求されたアクセスを実行します。
この慣例により、プロバイダにアクセスするアプリの一般的なパターンを簡単に設計できます。アプリはプロバイダにクエリを実行し、{@link android.widget.CursorAdapter} を使用して、取得した {@link android.database.Cursor} を {@link android.widget.ListView} に表示します。
{@link android.widget.CursorAdapter} の定義には、{@link android.database.Cursor} のいずれかの列を _ID
に設定する必要があります
その後、ユーザーはデータの確認や修正のために、表示された行のいずれかを UI から選択します。
アプリは {@link android.widget.ListView} を返す {@link android.database.Cursor} から対応する行を取得し、この行の _ID
値を取得し、その値をコンテンツ URI の末尾に追加して、プロバイダにアクセス要求を送ります。
その後、プロバイダは、ユーザーが選択した行にクエリや修正を実行します。
受け取ったコンテンツ URI に対するアクションを簡単に選択できるように、プロバイダ API には {@link android.content.UriMatcher} という便利なクラスが用意されています。このクラスはコンテンツ URI 「パターン」を正数値にマッピングします。
この正数値を switch
文で使用することで、特定のパターンに一致する 1 つ以上のコンテンツ URI に目的のアクションを選択できます。
コンテンツ URI パターンは、次のワイルドカード文字を使用するコンテンツ URI に一致します。
*
: 任意の長さの任意の有効な文字で構成される文字列に一致します。
#
: 任意の長さの任意の数字で構成される文字列に一致します。
コンテンツ URI 処理の設計とコーディングの例として、テーブルを指す次のコンテンツ URI を認識する認証局 com.example.app.provider
を持つプロバイダを考えてみます。
content://com.example.app.provider/table1
: table1
という名前のテーブル。
content://com.example.app.provider/table2/dataset1
: dataset1
という名前のテーブル。
content://com.example.app.provider/table2/dataset2
: dataset2
という名前のテーブル。
content://com.example.app.provider/table3
: table3
という名前のテーブル。
さらに、行 ID が末尾に追加されていると、プロバイダではこれらのコンテンツ URI が認識されます。たとえば、table3
の 1
で特定される行は content://com.example.app.provider/table3/1
になります。
次のようなコンテンツ URI パターンを使用できます。
content://com.example.app.provider/*
content://com.example.app.provider/table2/*
:
dataset1
と dataset2
のコンテンツ URI に一致しますが、table1
や table3
のコンテンツ URI には一致しません。
content://com.example.app.provider/table3/#
: table3
の 1 つの行のコンテンツ URI に一致します。6
で特定される行は content://com.example.app.provider/table3/6
になります。
次のコード スニペットでは、{@link android.content.UriMatcher} のメソッドが機能する仕組みを示します。
このコードでは、テーブルにコンテンツ URI パターン content://<authority>/<path>
を使用し、1 つの行に content://<authority>/<path>/<id>
を使用することで、表全体の URI と 1 つの行の URI を異なる方法で処理します。
メソッド {@link android.content.UriMatcher#addURI(String, String, int) addURI()} は認証局とパスを正数値にマッピングします。
メソッド {@link android.content.UriMatcher#match(Uri)
match()} は URI に正数値を返します。次のように、switch
文によって、クエリをテーブル全体に実行するか、1 つのレコードに実行するかが決まります。
public class ExampleProvider extends ContentProvider { ... // Creates a UriMatcher object. private static final UriMatcher sUriMatcher; ... /* * The calls to addURI() go here, for all of the content URI patterns that the provider * should recognize. For this snippet, only the calls for table 3 are shown. */ ... /* * Sets the integer value for multiple rows in table 3 to 1. Notice that no wildcard is used * in the path */ sUriMatcher.addURI("com.example.app.provider", "table3", 1); /* * Sets the code for a single row to 2. In this case, the "#" wildcard is * used. "content://com.example.app.provider/table3/3" matches, but * "content://com.example.app.provider/table3 doesn't. */ sUriMatcher.addURI("com.example.app.provider", "table3/#", 2); ... // Implements ContentProvider.query() public Cursor query( Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) { ... /* * Choose the table to query and a sort order based on the code returned for the incoming * URI. Here, too, only the statements for table 3 are shown. */ switch (sUriMatcher.match(uri)) { // If the incoming URI was for all of table3 case 1: if (TextUtils.isEmpty(sortOrder)) sortOrder = "_ID ASC"; break; // If the incoming URI was for a single row case 2: /* * Because this URI was for a single row, the _ID value part is * present. Get the last path segment from the URI; this is the _ID value. * Then, append the value to the WHERE clause for the query */ selection = selection + "_ID = " uri.getLastPathSegment(); break; default: ... // If the URI is not recognized, you should do some error handling here. } // call the code to actually do the query }
別の {@link android.content.ContentUris} には、コンテンツ URI の一部である id
で作業するための便利なメソッドが備わっています。
クラス {@link android.net.Uri} と {@link android.net.Uri.Builder} には、既存の {@link android.net.Uri} オブジェクトを解析して新しいオブジェクトをビルドするための便利なメソッドがあります。
{@link android.content.ContentProvider} インスタンスは、他のアプリケーションからの要求を処理することで、一連の構造化されたデータへのアクセスを管理します。 どのような形式でアクセスする場合も、最終的には {@link android.content.ContentResolver} が呼び出されます。その後 {@link android.content.ContentProvider} の具象メソッドが呼び出され、アクセスを取得します。
抽象クラス {@link android.content.ContentProvider} は 6 つの抽象メソッドを定義しますが、これらのメソッドは独自の具象サブクラスの一部として実装する必要があります。 次のように、{@link android.content.ContentProvider#onCreate() onCreate()} を除くこれらのメソッドは、コンテンツ プロバイダへのアクセスを試みるクライアント アプリケーションによって呼び出されます。
これらのメソッドが持つ署名は、同じ名前の {@link android.content.ContentResolver} メソッドの署名と同じになります。
これらのメソッドを実装する場合は、次の点を考慮する必要があります。
{@link android.content.ContentProvider#query(Uri, String[], String, String[], String)
ContentProvider.query()} メソッドは {@link android.database.Cursor} オブジェクトを返す必要があります。失敗した場合は、{@link java.lang.Exception} をスローします。
SQLite データベースをデータストレージとして使用する場合は、{@link android.database.sqlite.SQLiteDatabase} クラスのいずれかの query()
メソッドが返す {@link android.database.Cursor} を返します。
クエリがどの行にも一致しない場合は、{@link android.database.Cursor#getCount()} メソッドが 0 を返す {@link android.database.Cursor} インスタンスを返す必要があります。
クエリプロセス中にエラーが発生した場合にのみ null
を返します。
SQLite データベースをデータストレージとして使用しない場合は、{@link android.database.Cursor} クラスのいずれかの具象サブクラスを使用します。 たとえば、{@link android.database.MatrixCursor} クラスは、各行が {@link java.lang.Object} の配列となるカーソルを実装します。 このクラスでは、{@link android.database.MatrixCursor#addRow(Object[]) addRow()} を使って新しい行を追加します。
Android システムは、プロセスの境界をまたいで {@link java.lang.Exception} を送信できるように設定する必要があることにご注意ください。 Android では、クエリエラーを処理するのに便利な、次の例外を送信できます。
{@link android.content.ContentProvider#insert(Uri, ContentValues) insert()} メソッドは、{@link android.content.ContentValues} 引数の値を使用して、適切なテーブルに新しい行を追加します。 列名が {@link android.content.ContentValues} 引数にない場合は、プロバイダ コードがデータベース スキーマのいずれかで、デフォルト値を設定できます。
このメソッドは新しい行のコンテンツ URI を返します。作成するには、{@link android.content.ContentUris#withAppendedId(Uri, long) withAppendedId()} を使用して、新しい行の _ID
(または他のプライマリキー)の値をテーブルのコンテンツ URI の末尾に追加します。
{@link android.content.ContentProvider#delete(Uri, String, String[]) delete()} メソッドでは、データストレージから行を物理的に削除する必要はありません。 プロバイダで同期アダプタを使用する場合は、行全体を削除するのではなく、削除された行に「削除」フラグを付けるようにします。 同期アダプタは削除された行を探して、プロバイダから削除される前に、サーバーから行を削除できます。
{@link android.content.ContentProvider#update(Uri, ContentValues, String, String[])
update()} メソッドは {@link android.content.ContentProvider#insert(Uri, ContentValues) insert()} が使用するのと同じ {@link android.content.ContentValues} 引数、{@link android.content.ContentProvider#delete(Uri, String, String[]) delete()} と {@link android.content.ContentProvider#query(Uri, String[], String, String[], String)
ContentProvider.query()} が使用するのと同じ selection
と selectionArgs
引数を使用します。
これにより、これらのメソッド間でコードを再利用できます。
Android システムはプロバイダを起動する際に {@link android.content.ContentProvider#onCreate() onCreate()} を呼び出します。このメソッドでは迅速に実行できる初期化タスクのみを実行するようにし、プロバイダが実際にデータの要求を受け取るまでは、データベースの作成とデータロードを保留します。 {@link android.content.ContentProvider#onCreate() onCreate()} で冗長なタスクを行う場合は、プロバイダの起動が遅くなります。 同様に、プロバイダから他のアプリケーションへの応答も遅くなります。
たとえば、SQLite データベースを使用すると、{@link android.content.ContentProvider#onCreate() ContentProvider.onCreate()} に {@link android.database.sqlite.SQLiteOpenHelper} オブジェクトを作成し、データベースを初めて開くときに SQL テーブルを作成できます。 この操作を簡単にするために、{@link android.database.sqlite.SQLiteOpenHelper#getWritableDatabase getWritableDatabase()} を初めて呼び出すときには、{@link android.database.sqlite.SQLiteOpenHelper#onCreate(SQLiteDatabase) SQLiteOpenHelper.onCreate()} メソッドが自動的に呼び出されます。
次の 2 つのスニペットは、{@link android.content.ContentProvider#onCreate() ContentProvider.onCreate()} と {@link android.database.sqlite.SQLiteOpenHelper#onCreate(SQLiteDatabase) SQLiteOpenHelper.onCreate()} との間のやり取りを表しています。 最初のスニペットは {@link android.content.ContentProvider#onCreate() ContentProvider.onCreate()} の実装です。
public class ExampleProvider extends ContentProvider /* * Defines a handle to the database helper object. The MainDatabaseHelper class is defined * in a following snippet. */ private MainDatabaseHelper mOpenHelper; // Defines the database name private static final String DBNAME = "mydb"; // Holds the database object private SQLiteDatabase db; public boolean onCreate() { /* * Creates a new helper object. This method always returns quickly. * Notice that the database itself isn't created or opened * until SQLiteOpenHelper.getWritableDatabase is called */ mOpenHelper = new MainDatabaseHelper( getContext(), // the application context DBNAME, // the name of the database) null, // uses the default SQLite cursor 1 // the version number ); return true; } ... // Implements the provider's insert method public Cursor insert(Uri uri, ContentValues values) { // Insert code here to determine which table to open, handle error-checking, and so forth ... /* * Gets a writeable database. This will trigger its creation if it doesn't already exist. * */ db = mOpenHelper.getWritableDatabase(); } }
次のスニペットは {@link android.database.sqlite.SQLiteOpenHelper#onCreate(SQLiteDatabase) SQLiteOpenHelper.onCreate()} の実装であり、ヘルパークラスを含みます。
... // A string that defines the SQL statement for creating a table private static final String SQL_CREATE_MAIN = "CREATE TABLE " + "main " + // Table's name "(" + // The columns in the table " _ID INTEGER PRIMARY KEY, " + " WORD TEXT" " FREQUENCY INTEGER " + " LOCALE TEXT )"; ... /** * Helper class that actually creates and manages the provider's underlying data repository. */ protected static final class MainDatabaseHelper extends SQLiteOpenHelper { /* * Instantiates an open helper for the provider's SQLite data repository * Do not do database creation and upgrade here. */ MainDatabaseHelper(Context context) { super(context, DBNAME, null, 1); } /* * Creates the data repository. This is called when the provider attempts to open the * repository and SQLite reports that it doesn't exist. */ public void onCreate(SQLiteDatabase db) { // Creates the main table db.execSQL(SQL_CREATE_MAIN); } }
{@link android.content.ContentProvider} クラスには、MIME タイプを返すための次の 2 つのクラスがあります。
{@link android.content.ContentProvider#getType(Uri) getType()} メソッドは、MIME 形式で {@link java.lang.String} を返します。これは、コンテンツ URI 引数によって返されるデータのタイプを表します。 {@link android.net.Uri} 引数には特定の URI ではなくパターンを指定することもできます。この場合、パターンに一致するコンテンツ URI に関連付けられているデータのタイプを返します。
テキスト、HTML、JPEG といった一般的なタイプのデータの場合、{@link android.content.ContentProvider#getType(Uri) getType()} では該当するデータの標準的な MIME タイプを返す必要があります。 利用できるこれらの標準的なタイプの詳細なリストは、「IANA MIME Media Types」のウェブサイトをご覧ください。
テーブル データの 1 つ以上の行を指すコンテンツ URI の場合、{@link android.content.ContentProvider#getType(Uri) getType()} は、Android のベンダー固有の MIME 形式で MIME タイプを返す必要があります。
vnd
android.cursor.item/
android.cursor.dir/
vnd.<name>
.<type>
<name>
と <type>
を指定します。
<name>
の値はグローバルに一意の値とし、<type>
の値は対応する URI パターンに一意のものとする必要があります。
<name>
には、企業名や、アプリケーションの Android パッケージ名の一部を使うことをお勧めします。
<type>
には、URI に関連付けられているテーブルを特定する文字列を使うことをお勧めします。
たとえば、プロバイダの認証局が com.example.app.provider
の場合、テーブル名は table1
となり、table1
の複数行の MIME タイプは次のようになります。
vnd.android.cursor.dir/vnd.com.example.provider.table1
table1
の 1 つの行の場合は、MIME タイプは次のようになります。
vnd.android.cursor.item/vnd.com.example.provider.table1
ファイルを提供するプロバイダの場合は、{@link android.content.ContentProvider#getStreamTypes(Uri, String) getStreamTypes()} を実装します。 このメソッドは、プロバイダが特定のコンテンツ URI に対して返すことができるファイルの MIME タイプの {@link java.lang.String} 配列を返します。クライアントで処理する MIME タイプのみを返すには、MIME タイプフィルタ引数によって、提供する MIME タイプをフィルタする必要があります。
たとえば、写真画像を .jpg
、.png
、.gif
形式で提供するプロバイダについて考えてみます。
アプリケーションが {@link android.content.ContentResolver#getStreamTypes(Uri, String)
ContentResolver.getStreamTypes()} をフィルタ文字列 image/*
(何らかの形式の「画像」)で呼び出す場合、{@link android.content.ContentProvider#getStreamTypes(Uri, String)
ContentProvider.getStreamTypes()} メソッドは次のような配列を返します。
{ "image/jpeg", "image/png", "image/gif"}
アプリの対象が .jpg
ファイルのみであり、アプリが {@link android.content.ContentResolver#getStreamTypes(Uri, String)
ContentResolver.getStreamTypes()} をフィルタ文字列 *\/jpeg
で呼び出す場合、{@link android.content.ContentProvider#getStreamTypes(Uri, String)
ContentProvider.getStreamTypes()} は次の項目を返します。
{"image/jpeg"}
プロバイダが、フィルタ文字列で要求した MIME タイプを提供していない場合、{@link android.content.ContentProvider#getStreamTypes(Uri, String) getStreamTypes()} は null
を返します。
コントラクト クラスは public final
クラスであり、URI、列名、MIME タイプ、プロバイダに関連するその他のメタデータを含みます。
このクラスは、URI や列名などの実際の値が変更された場合にも、プロバイダに正しくアクセスできることを保証することで、プロバイダとその他のアプリケーションとの間にコントラクトを構築します。
さらに、通常、コントラクト クラスではその定数にニーモニック名が設定されているため、デベロッパーが列名や URI に誤った値を使用しにくいようになっています。 クラスであるため、Javadoc ドキュメントを含めることができます。 Eclipse などの統合型開発環境では、コントラクト クラスから定数名が自動的に設定され、定数の Javadoc が表示されます。
デベロッパーはアプリケーションからコントラクト クラスのクラスファイルにアクセスできませんが、提供する .jar
ファイルからクラスファイルをアプリケーションに静的にコンパイルできます。
{@link android.provider.ContactsContract} クラスとそのネストされたクラスは、コントラクト クラスの例です。
Android システムのあらゆる領域に対するパーミッションとクラスについては、「セキュリティとパーミッション」トピックをご覧ください。 また、トピック「Data Storage」にも、ストレージのさまざまなタイプに有効なセキュリティとパーミッションについて記載されています。 重要な点をまとめると次のようになります。
コンテンツ プロバイダ パーミッションを使用してデータへのアクセスを制御する場合は、内部ファイル、SQLite データベース、「クラウド」(リモート サーバーなど)にデータを格納し、ファイルやデータベースを自分のアプリケーションにのみ公開するように設定します。
デフォルトではプロバイダにはパーミッションが設定されていないため、基礎となるデータがプライベートに設定されている場合でも、すべてのアプリケーションは自分のプロバイダからの読み取りとプロバイダへの書き込みを実行できます。
これを変更するには、
<provider>
要素の属性や子要素を使用して、マニフェスト ファイルでプロバイダのパーミッションを設定します。
プロバイダ全体に適用するパーミッションを設定することもできますし、特定のテーブル、特定のレコード、これら 3 つすべてに適用するパーミッションを設定することもできます。
マニフェスト ファイルで 1 つ以上の
<permission>
要素を使用して、プロバイダのパーミッションを定義します。
自分のプロバイダに独自のパーミッションを作成するには、
android:name
属性に Java スタイルのスコーピングを使用します
たとえば、読み取りパーミッションの名前を com.example.app.provider.permission.READ_PROVIDER
とします。
次のリストは、プロバイダ パーミッションの範囲を示しています。プロバイダ全体に適用するパーミッションから始まり、より詳細な範囲のものになっています。 より広い範囲を持つパーミッションよりも、範囲が限定されるパーミッションの方が優先されます。
<provider>
要素の
android:permission
属性で指定します。
<provider>
要素の
android:readPermission
属性と
android:writePermission
属性で指定します。
これらは、
android:permission
で要求するパーミッションよりも優先されます。
<provider>
要素の
<path-permission>
子要素を使用して、制御対象の各 URI を指定します。
指定する各コンテンツ URI に対して、読み取り / 書き込みパーミッション、読み取りパーミッション、書き込みパーミッション、3 つすべてを指定できます。
読み取りパーミッションと書き込みパーミッションは、読み取り / 書き込みパーミッションに優先します。
また、パスレベルのパーミッションはプロバイダ レベルのパーミッションに優先します。
プロバイダからの写真の添付ファイルを外部の画像ビューワ アプリケーションで表示する場合に、メール プロバイダとアプリに実装するパーミッションを考えてみます。 パーミッションを要求しなくても、画像ビューワに必要なアクセスを付与するには、写真のコンテンツ URI に一時的なパーミッションを設定します。 ユーザーが写真を表示しようとしたときに、アプリから写真のコンテンツ URI とパーミッション フラグを含むインテントを画像ビューワに送信するようにメール アプリを設計します。 ビューワにプロバイダの通常の読み取りパーミッションが付与されていない場合でも、画像ビューワはメール プロバイダにクエリを実行して写真を取得します。
一時的なパーミッションを有効にするには、
<provider>
要素の
android:grantUriPermissions
属性を設定するか、1 つ以上の
<grant-uri-permission>
子要素を
<provider>
要素に追加します。
一時的なパーミッションを使用する場合、プロバイダからのコンテンツ URI のサポートを削除したときは常に {@link android.content.Context#revokeUriPermission(Uri, int)
Context.revokeUriPermission()} を呼び出す必要があります。そうすると、コンテンツ URI が一時的なパーミッションに関連付けられます。
属性の値によって、プロバイダへのアクセスレベルが決まります。
属性を true
に設定すると、システムによってプロバイダ全体への一時的なパーミッションが付与されます。このパーミッションは、プロバイダ レベルやパスレベルのパーミッションで必要になるその他のパーミッションよりも優先されます。
このフラグを false
に設定する場合は、
<grant-uri-permission>
子要素を
<provider>
要素に追加する必要があります。
それぞれの子要素は、一時的なアクセスが付与される 1 つ以上のコンテンツ URI を指定します。
一時的なアクセスをアプリケーションに委任するには、インテントに {@link android.content.Intent#FLAG_GRANT_READ_URI_PERMISSION} フラグか {@link android.content.Intent#FLAG_GRANT_WRITE_URI_PERMISSION} フラグ、またはその両方を含める必要があります。 これらは、{@link android.content.Intent#setFlags(int) setFlags()} メソッドで設定します。
android:grantUriPermissions
属性がない場合は、false
であると仮定されます。
{@link android.app.Activity} コンポーネントや {@link android.app.Service} コンポーネントと同様に、
<provider>
要素を使用して {@link android.content.ContentProvider} のサブクラスをアプリケーションのマニフェスト ファイルに定義する必要があります。
Android システムは要素から次の情報を取得します。
android:name
)
android:grantUriPermssions
: 一時的なパーミッションのフラグです。
android:permission
: 1 つのプロバイダ全体の読み取り / 書き込みパーミッションです。
android:readPermission
: プロバイダ全体の読み取りパーミッションです。
android:writePermission
: プロバイダ全体の書き込みパーミッションです。
パーミッションとそれに対応する属性の詳細は、コンテンツ プロバイダ パーミッションを実装するセクションをご覧ください。
android:enabled
: システムにプロバイダの起動を許可するフラグです。
android:exported
: 他のアプリケーションにこのプロバイダの使用を許可するフラグです。
android:initOrder
: 同じプロセス内の他のプロバイダに対して、このプロバイダを起動する順番です。
android:multiProcess
: システムに呼び出しクライアントと同じプロセスでのプロバイダの開始を許可するフラグです。
android:process
: プロバイダを実行するプロセスの名前です。
android:syncable
: プロバイダのデータをサーバー上のデータと同期することを示すフラグです。
属性に関する詳細は、開発ガイドの
<provider>
要素に関するトピックに記載されています。
android:icon
: プロバイダのアイコンを含むドローアブル リソースです。
[設定] > [アプリ] > [すべて] にあるアプリのリストのプロバイダラベルの横に表示されるアイコンです。
android:label
: プロバイダ、データ、その両方を説明する、情報ラベルです。
[設定] > [アプリ] > [すべて] にあるアプリのリストのプロバイダラベルの横に表示されるアイコンです。
属性に関する詳細は、開発ガイドの
<provider>
要素に関するトピックに記載されています。
{@link android.content.Intent} を使用すると、アプリケーションはコンテンツ プロバイダに間接的にアクセスできます。 アプリケーションは、{@link android.content.ContentResolver} や {@link android.content.ContentProvider} のメソッドを呼び出しません。 その代わりに、アクティビティを起動するインテントを送信します。これは通常、プロバイダ独自のアプリケーションの一部となっています。 対象のアクティビティは UI のデータの取得と表示を担当します。インテントのアクションに応じて、対象のアクティビティにより、ユーザーにプロバイダのデータの修正を求めるメッセージが表示されることがあります。 さらに、インテントには、対象のアクティビティが UI に表示する「エクストラ」データが含まれることがあります。ユーザーは使用前に、このデータを変更してプロバイダのデータを修正することもできます。
インテント アクセスを使用して、データの整合性を保証できます。プロバイダのデータの挿入、更新、削除は、厳格に定義されたビジネス ロジックによって規定されることがあります。 この場合、他のアプリケーションにデータを直接修正できるように許可すると、無効なデータが発生することがあります。 デベロッパーがインテント アクセスを使用する場合は、すべての操作を完全に文書化します。 コードを使用してデータを修正するよりも、独自のアプリケーションの UI を使用したインテント アクセスの方が優れている理由を説明します。
プロバイダのデータを修正するための受信インテントの処理は、その他のインテントの処理と同じです。 インテントの使用についての詳細は、「インテントとインテント フィルタ」をご覧ください。