Skip to content

Most visited

Recently visited

navigation

コンテンツ プロバイダの作成

コンテンツ プロバイダは、データの中央リポジトリへのアクセスを管理します。Android アプリケーションでは 1 つ以上のクラスとしてプロバイダを実装し、要素をマニフェスト ファイルで実装します。 いずれか 1 つのクラスがサブラス ContentProvider を実装します。これは、プロバイダと他のアプリケーションとの間のインターフェースになります。 コンテンツ プロバイダは他のアプリケーションへのデータの提供を意図したものですが、ユーザーがプロバイダに管理されるデータを照会、修正するアクティビティをアプリケーション内に設定することもできます。

このトピックの残りの部分では、コンテンツ プロバイダと使用する API のリストをビルドするための基本的な手順を挙げていきます。

ビルドを開始する前に

ビルドを開始する前に、次の操作を行います。

  1. コンテンツ プロバイダが必要かどうかを決定します。次のような機能を 1 つ以上提供する場合に、コンテンツ プロバイダをビルドする必要があります。
    • 他のアプリケーションに複雑なデータやファイルを提供する。
    • アプリから他のアプリへの複雑なデータのコピーをユーザーに許可する。
    • 検索フレームワークを使用してカスタムの検索候補を提供する。

    完全に独自アプリケーション内だけで使用する場合は、SQLite データベースを使用するプロバイダは必要はありません。

  2. 必要かどうかを決定していない場合は、プロバイダの詳細についてはコンテンツ プロバイダの基本のトピックをご覧ください。

次に、以下の手順に従ってプロバイダをビルドします。

  1. データの未処理のストレージを設計します。コンテンツ プロバイダは次の 2 つの方法でデータを提供します。
    ファイルデータ
    通常、写真、オーディオ、ビデオなどのファイルの形式となるデータです。 ファイルはアプリケーションのプライベート スペースに格納します。 ファイルに対する別のアプリケーションからの要求に応じて、プロバイダからファイルへのハンドルが提供されます。
    「構造化」データ
    通常、データベース、配列、類似の構造の形式となるデータです。 テーブルの行と列に互換性を持つ形式でデータが格納されます。行は、担当者や在庫にあるアイテムなどのエンティティを表します。 列は、担当者の名前やアイテムの価格などの、エンティティの一部のデータを表します。 一般的にこのタイプのデータは SQLite データベースに格納しますが、任意のタイプの永続ストレージを使用できます。 Android システムで使用できるストレージ タイプの詳細は、データ ストレージを設計するをご覧ください。
  2. ContentProvider クラスの具体的な実装とそれに必要なメソッドを定義します。 このクラスは、データと Android システムのそれ以外の部分とのインターフェースとなります。 このクラスの詳細は、ContentProvider クラスを実装するセクションをご覧ください。
  3. プロバイダの認証局の文字列、コンテンツ URI、列名を定義します。プロバイダのアプリケーションでインテントを処理する場合は、インテント アクション、エクストラ データ、フラグも定義します。 さらに、データにアクセスするアプリケーションに必要なパーミッションも定義します。 これらの値はすべて定数として個別のコントラクト クラスに定義するようにします。そうしておくと、後で他のデベロッパーに対してこのクラスを公開できます。 コンテンツ URI の詳細は、コンテンツ URI を設計するセクションをご覧ください。 インテントの使用に関する詳細については、インテントとデータアクセスセクションをご覧ください。
  4. サンプルデータや、プロバイダとクラウドベースのデータの間でデータを同期する AbstractThreadedSyncAdapter の実装などの、その他のオプション部分を追加します。

データ ストレージを設計する

コンテンツ プロバイダは、構造化された形式で保存されているデータへのインターフェースです。インターフェースを作成する前に、データの格納方法を決定しておく必要があります。 データは任意の形式で保存でき、必要に応じてデータの読み取りと書き込みを行うためのインターフェースを設計できます。

Android には、次のように、いくつかのデータ格納テクノロジーがあります。

データ設計上の考慮事項

次に、プロバイダのデータ構造を設計する際のヒントを示します。

コンテンツ URI を設計する

コンテンツ URI は、プロバイダのデータを特定する URI です。コンテンツ URI には、プロバイダ全体の識別名(認証局)とテーブルやファイルをポイントする名前(パス)が含まれます。 オプションの ID 部分は、テーブル内の個々の行を指します。 ContentProvider のそれぞれのデータアクセス メソッドは引数としてコンテンツ URI を使用します。これにより、アクセスするテーブル、行、ファイルを決定できます。

コンテンツ URI の基本については、コンテンツ プロバイダの基本トピックをご覧ください。

認証局を設計する

通常、プロバイダは、Android 内部の名前として使用される認証局を 1 つ持ちます。他のプロバイダとの競合を避けるためには、(逆に)プロバイダの認証局の基礎としてインターネット ドメインの所有権を使用する必要があります。 この推奨事項は Android パッケージ名にもあてはまるため、プロバイダを含むパッケージの名前の拡張子として、プロバイダの認証局を定義できます。 たとえば、Android パッケージ名が com.example.<appname> の場合、プロバイダに認証局 com.example.<appname>.provider を付与する必要があります。

パス構造を設計する

デベロッパーは通常、個々のテーブルを指すパスを末尾に追加して認証局からコンテンツ URI を作成します。 たとえば、table1table2 の 2 つのテーブルがある場合、前の例の認証局を組み合わせてコンテンツ URI com.example.<appname>.provider/table1com.example.<appname>.provider/table2 を作成します。 パスは 1 つのセグメントに限定されず、パスの各レベルにテーブルを作成する必要はありません。

コンテンツ URI ID を処理する

慣例として、URI の末尾にある行の ID 値を持つコンテンツ URI を受け取ることで、プロバイダはテーブル内の 1 つの行へのアクセスを提供します。 さらに、慣例として、プロバイダは ID 値をテーブルの _ID 列とマッチングし、一致する行に対して要求されたアクセスを実行します。

この慣例により、プロバイダにアクセスするアプリの一般的なパターンを簡単に設計できます。アプリはプロバイダにクエリを実行し、CursorAdapter を使用して、取得した CursorListView に表示します。 CursorAdapter の定義には、Cursor のいずれかの列を _ID に設定する必要があります

その後、ユーザーはデータの確認や修正のために、表示された行のいずれかを UI から選択します。 アプリは ListView を返す Cursor から対応する行を取得し、この行の _ID 値を取得し、その値をコンテンツ URI の末尾に追加して、プロバイダにアクセス要求を送ります。 その後、プロバイダは、ユーザーが選択した行にクエリや修正を実行します。

コンテンツ URI パターン

受け取ったコンテンツ URI に対するアクションを簡単に選択できるように、プロバイダ API には UriMatcher という便利なクラスが用意されています。このクラスはコンテンツ URI 「パターン」を正数値にマッピングします。 この正数値を switch 文で使用することで、特定のパターンに一致する 1 つ以上のコンテンツ URI に目的のアクションを選択できます。

コンテンツ URI パターンは、次のワイルドカード文字を使用するコンテンツ URI に一致します。

コンテンツ URI 処理の設計とコーディングの例として、テーブルを指す次のコンテンツ URI を認識する認証局 com.example.app.provider を持つプロバイダを考えてみます。

さらに、行 ID が末尾に追加されていると、プロバイダではこれらのコンテンツ URI が認識されます。たとえば、table31 で特定される行は content://com.example.app.provider/table3/1 になります。

次のようなコンテンツ URI パターンを使用できます。

content://com.example.app.provider/*
プロバイダの任意のコンテンツ URI に一致します。
content://com.example.app.provider/table2/*:
テーブル dataset1dataset2 のコンテンツ URI に一致しますが、table1table3 のコンテンツ URI には一致しません。
content://com.example.app.provider/table3/#: table3 の 1 つの行のコンテンツ URI に一致します。6 で特定される行は content://com.example.app.provider/table3/6 になります。

次のコード スニペットでは、UriMatcher のメソッドが機能する仕組みを示します。 このコードでは、テーブルにコンテンツ URI パターン content://<authority>/<path> を使用し、1 つの行に content://<authority>/<path>/<id> を使用することで、表全体の URI と 1 つの行の URI を異なる方法で処理します。

メソッド addURI() は認証局とパスを整数値にマッピングします。 メソッド match() は URI に整数値を返します。次のように、switch 文によって、クエリをテーブル全体に実行するか、1 つのレコードに実行するかが決まります。

public class ExampleProvider extends ContentProvider {
...
    // Creates a UriMatcher object.
    private static final UriMatcher sUriMatcher = new UriMatcher(UriMatcher.NO_MATCH);

    static {
        /*
         * 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
    }

別の ContentUris には、コンテンツ URI の一部である id で作業するための便利なメソッドが備わっています。 クラス UriUri.Builder には、既存の Uri オブジェクトを解析して新しいオブジェクトをビルドするための便利なメソッドがあります。

ContentProvider クラスを実装する

ContentProvider インスタンスは、他のアプリケーションからの要求を処理することで、一連の構造化されたデータへのアクセスを管理します。 どのような形式でアクセスする場合も、最終的には ContentResolver が呼び出されます。その後 ContentProvider の具象メソッドが呼び出され、アクセスを取得します。

必須メソッド

抽象クラス ContentProvider は 6 つの抽象メソッドを定義しますが、これらのメソッドは独自の具象サブクラスの一部として実装する必要があります。 次のように、onCreate() を除くこれらのメソッドは、コンテンツ プロバイダへのアクセスを試みるクライアント アプリケーションによって呼び出されます。

query()
プロバイダからデータを取得します。引数を使って、クエリを実行するテーブル、返す行と列、結果の並び順を選択します。 データは Cursor オブジェクトとして返されます。
insert()
プロバイダに新しい行を挿入します。引数を使って、挿入先のテーブルを選択し、使用する列の値を取得します。 新たに挿入した行のコンテンツ URI が返されます。
update()
プロバイダ内の既存の行を更新します。引数を使って、更新するテーブルと行を選び、更新された列の値を取得します。 更新された行の数が返されます。
delete()
プロバイダから行を削除します。引数を使って、削除するテーブルと行を選びます。 削除された行の数が返されます。
getType()
コンテンツ URI に対応する MIME タイプを返します。このメソッドの詳細は、コンテンツ プロバイダ MIME を実装するセクションをご覧ください。
onCreate()
プロバイダを初期化します。プロバイダが作成されると、Android システムがこのメソッドを即座に呼び出します。 ContentResolver オブジェクトがアクセスを試みるまでは、プロバイダは作成されません。

これらのメソッドが持つ署名は、同じ名前の ContentResolver メソッドの署名と同じになります。

これらのメソッドを実装する場合は、次の点を考慮する必要があります。

query() メソッドを実装する

ContentProvider.query() メソッドは Cursor オブジェクトを返す必要があります。失敗した場合は、Exception をスローします。 SQLite データベースをデータストレージとして使用する場合は、SQLiteDatabase クラスのいずれかの query() メソッドが返す Cursor を返します。 クエリがどの行にも一致しない場合は、getCount() メソッドが 0 を返す Cursor インスタンスを返す必要があります。クエリプロセス中に内部エラーが発生した場合にのみ null を返します。

SQLite データベースをデータストレージとして使用しない場合は、Cursor クラスのいずれかの具象サブクラスを使用します。 たとえば、MatrixCursor クラスは、各行が Object の配列となるカーソルを実装します。 このクラスでは、addRow() を使って新しい行を追加します。

Android システムは、プロセスの境界をまたいで Exception を送信できるように設定する必要があることにご注意ください。 Android では、クエリエラーを処理するのに便利な、次の例外を送信できます。

insert() メソッドを実装する

insert() メソッドは、ContentValues 引数の値を使用して、適切なテーブルに新しい行を追加します。 列名が ContentValues 引数にない場合は、プロバイダ コードがデータベース スキーマのいずれかで、デフォルト値を設定できます。

このメソッドは新しい行のコンテンツ URI を返します。作成するには、withAppendedId() を使用して、新しい行の _ID(または他のプライマリキー)の値をテーブルのコンテンツ URI の末尾に追加します。

delete() メソッドを実装する

delete() メソッドでは、データストレージから行を物理的に削除する必要はありません。 プロバイダで同期アダプタを使用する場合は、行全体を削除するのではなく、削除された行に「削除」フラグを付けるようにします。 同期アダプタは削除された行を探して、プロバイダから削除される前に、サーバーから行を削除できます。

update() メソッドを実装する

update() メソッドは insert() が使用するのと同じ ContentValues 引数、delete()ContentProvider.query() が使用するのと同じ selectionselectionArgs 引数を使用します。 これにより、これらのメソッド間でコードを再利用できます。

onCreate() メソッドを実装する

Android システムはプロバイダを起動する際に onCreate() を呼び出します。このメソッドでは迅速に実行できる初期化タスクのみを実行するようにし、プロバイダが実際にデータの要求を受け取るまでは、データベースの作成とデータロードを保留します。 onCreate() で冗長なタスクを行う場合は、プロバイダの起動が遅くなります。 同様に、プロバイダから他のアプリケーションへの応答も遅くなります。

たとえば、SQLite データベースを使用すると、ContentProvider.onCreate()SQLiteOpenHelper オブジェクトを作成し、データベースを初めて開くときに SQL テーブルを作成できます。 この操作を簡単にするために、getWritableDatabase() を初めて呼び出すときには、SQLiteOpenHelper.onCreate() メソッドが自動的に呼び出されます。

次の 2 つのスニペットは、ContentProvider.onCreate()SQLiteOpenHelper.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();
    }
}

次のスニペットは 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);
    }
}

ContentProvider MIME タイプを実装する

ContentProvider クラスには、MIME タイプを返すための次の 2 つのクラスがあります。

getType()
任意のプロバイダに実装する必要がある必須メソッドの 1 つです。
getStreamTypes()
ファイルを提供するプロバイダの場合に、実装が考えられるメソッドです。

テーブルの MIME タイプ

getType() メソッドは、MIME 形式で String を返します。これは、コンテンツ URI 引数によって返されるデータのタイプを表します。 Uri 引数には特定の URI ではなくパターンを指定することもできます。この場合、パターンに一致するコンテンツ URI に関連付けられているデータのタイプを返します。

テキスト、HTML、JPEG といった一般的なタイプのデータの場合、getType() では該当するデータの標準的な MIME タイプを返す必要があります。 利用できるこれらの標準的なタイプの詳細なリストは、IANA MIME Media Types のウェブサイトをご覧ください。

テーブル データの 1 つ以上の行を指すコンテンツ URI の場合、getType() は、Android のベンダー固有の MIME 形式で MIME タイプを返す必要があります。

たとえば、プロバイダの認証局が 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

ファイルの MIME タイプ

ファイルを提供するプロバイダの場合は、getStreamTypes() を実装します。 このメソッドは、プロバイダが特定のコンテンツ URI に対して返すことができるファイルの MIME タイプの String 配列を返します。 クライアントで処理する MIME タイプのみを返すには、MIME タイプフィルタ引数によって、提供する MIME タイプをフィルタする必要があります。

たとえば、写真画像を .jpg.png.gif 形式で提供するプロバイダについて考えてみます。 アプリケーションが ContentResolver.getStreamTypes() をフィルタ文字列 image/* (何らかの形式の「画像」)で呼び出す場合、ContentProvider.getStreamTypes() メソッドは次のような配列を返します。

{ "image/jpeg", "image/png", "image/gif"}

アプリの対象が .jpg ファイルのみであり、アプリが ContentResolver.getStreamTypes() をフィルタ文字列 *\/jpeg で呼び出す場合、ContentProvider.getStreamTypes() は次の項目を返します。

{"image/jpeg"}

プロバイダが、フィルタ文字列で要求した MIME タイプを提供していない場合、getStreamTypes()null を返します。

コントラクト クラスを実装する

コントラクト クラスは public final クラスであり、URI、列名、MIME タイプ、プロバイダに関連するその他のメタデータを含みます。 このクラスは、URI や列名などの実際の値が変更された場合にも、プロバイダに正しくアクセスできることを保証することで、プロバイダとその他のアプリケーションとの間にコントラクトを構築します。

さらに、通常、コントラクト クラスではその定数にニーモニック名が設定されているため、デベロッパーが列名や URI に誤った値を使用しにくいようになっています。 クラスであるため、Javadoc ドキュメントを含めることができます。 Android Studio などの統合型開発環境では、コントラクト クラスから定数名が自動的に設定され、定数の Javadoc が表示されます。

デベロッパーはアプリケーションからコントラクト クラスのクラスファイルにアクセスできませんが、提供する .jar ファイルからクラスファイルをアプリケーションに静的にコンパイルできます。

ContactsContract クラスとそのネストされたクラスは、コントラクト クラスの例です。

コンテンツ プロバイダ パーミッションを実装する

Android システムのあらゆる領域に対するパーミッションとクラスについては、セキュリティとパーミッションのトピックをご覧ください。 また、データ ストレージのトピックにも、ストレージのさまざまなタイプに有効なセキュリティとパーミッションについて記載されています。 重要な点をまとめると次のようになります。

コンテンツ プロバイダ パーミッションを使用してデータへのアクセスを制御する場合は、内部ファイル、SQLite データベース、「クラウド」(リモート サーバーなど)にデータを格納し、ファイルやデータベースを自分のアプリケーションにのみ公開するように設定します。

パーミッションを実装する

デフォルトではプロバイダにはパーミッションが設定されていないため、基礎となるデータがプライベートに設定されている場合でも、すべてのアプリケーションは自分のプロバイダからの読み取りとプロバイダへの書き込みを実行できます。 これを変更するには、 <provider> 要素の属性や子要素を使用して、マニフェスト ファイルでプロバイダのパーミッションを設定します。 プロバイダ全体に適用するパーミッションを設定することもできますし、特定のテーブル、特定のレコード、これら 3 つすべてに適用するパーミッションを設定することもできます。

マニフェスト ファイルで 1 つ以上の <permission> 要素を使用して、プロバイダのパーミッションを定義します。 自分のプロバイダに独自のパーミッションを作成するには、 android:name 属性に Java スタイルのスコーピングを使用します たとえば、読み取りパーミッションの名前を com.example.app.provider.permission.READ_PROVIDER とします。

次のリストは、プロバイダ パーミッションの範囲を示しています。プロバイダ全体に適用するパーミッションから始まり、より詳細な範囲のものになっています。 より広い範囲を持つパーミッションよりも、範囲が限定されるパーミッションの方が優先されます。

プロバイダ レベルで 1 つの読み取りと書き込みのパーミッション
1 つのパーミッションでプロバイダ全体の読み取りと書き込みのアクセスの両方を制御します。 <provider> 要素の android:permission 属性で指定します。
プロバイダ レベルで別々の読み取りと書き込みパーミッション
プロバイダ全体の読み取りパーミッションと書き込みパーミッションです。これらのパーミッションは <provider> 要素の android:readPermission 属性と android:writePermission 属性で指定します。 これらは、 android:permission で要求するパーミッションよりも優先されます。
パスレベルのパーミッション
プロバイダのコンテンツ URI の読み取り、書き込み、読み取り / 書き込みパーミッションです。 <provider> 要素の <path-permission> 子要素を使用して、制御対象の各 URI を指定します。 指定する各コンテンツ URI に対して、読み取り / 書き込みパーミッション、読み取りパーミッション、書き込みパーミッション、3 つすべてを指定できます。 読み取りパーミッションと書き込みパーミッションは、読み取り / 書き込みパーミッションに優先します。 また、パスレベルのパーミッションはプロバイダ レベルのパーミッションに優先します。
一時的なパーミッション
アプリケーションへの一時的なアクセスを付与するパーミッション レベルです。アプリケーションに通常必要とするパーミッションが付与されていない場合でも付与できます。 一時的なアクセス機能により、アプリケーションのマニフェストに必要なパーミッションの数を減らせます。 一時的なパーミッションを有効にすると、プロバイダへの「永続的な」パーミッションを必要とするアプリケーションのみが、継続的にすべてのデータにアクセスできます。

プロバイダからの写真の添付ファイルを外部の画像ビューワ アプリケーションで表示する場合に、メール プロバイダとアプリに実装するパーミッションを考えてみます。 パーミッションを要求しなくても、画像ビューワに必要なアクセスを付与するには、写真のコンテンツ URI に一時的なパーミッションを設定します。 ユーザーが写真を表示しようとしたときに、アプリから写真のコンテンツ URI とパーミッション フラグを含むインテントを画像ビューワに送信するようにメール アプリを設計します。 ビューワにプロバイダの通常の読み取りパーミッションが付与されていない場合でも、画像ビューワはメール プロバイダにクエリを実行して写真を取得します。

一時的なパーミッションを有効にするには、 <provider> 要素の android:grantUriPermissions 属性を設定するか、1 つ以上の <grant-uri-permission> 子要素を <provider> 要素に追加します。 一時的なパーミッションを使用する場合、プロバイダからのコンテンツ URI のサポートを削除したときは常に Context.revokeUriPermission() を呼び出す必要があります。そうすると、コンテンツ URI が一時的なパーミッションに関連付けられます。

属性の値によって、プロバイダへのアクセスレベルが決まります。 属性を true に設定すると、システムによってプロバイダ全体への一時的なパーミッションが付与されます。このパーミッションは、プロバイダ レベルやパスレベルのパーミッションで必要になるその他のパーミッションよりも優先されます。

このフラグを false に設定する場合は、 <grant-uri-permission> 子要素を <provider> 要素に追加する必要があります。 それぞれの子要素は、一時的なアクセスが付与される 1 つ以上のコンテンツ URI を指定します。

一時的なアクセスをアプリケーションに委任するには、インテントに FLAG_GRANT_READ_URI_PERMISSION フラグか FLAG_GRANT_WRITE_URI_PERMISSION フラグ、またはその両方を含める必要があります。 これらは、setFlags() メソッドで設定します。

android:grantUriPermissions 属性がない場合は、false であると仮定されます。

<provider> 要素

Activity コンポーネントや Service コンポーネントと同様に、 <provider> 要素を使用して ContentProvider のサブクラスをアプリケーションのマニフェスト ファイルに定義する必要があります。 Android システムは要素から次の情報を取得します。

認証局(android:authorities
システム内のプロバイダ全体を特定する識別名です。この属性の詳細は、コンテンツ URI を設計するセクションをご覧ください。
プロバイダ クラス名( android:name
ContentProvider を実装するクラスです。このクラスの詳細は、ContentProvider クラスを実装するセクションをご覧ください。
パーミッション
他のアプリケーションがプロバイダのデータにアクセスするのに必要なパーミッションを指定する属性です。

パーミッションとそれに対応する属性の詳細は、コンテンツ プロバイダ パーミッションを実装するセクションをご覧ください。

起動と制御の属性
これらの属性は、Android システムの起動方法とそのタイミング、プロバイダのプロセスの特性、その他の実行時の設定を決定します。
  • android:enabled: システムにプロバイダの起動を許可するフラグです。
  • android:exported: 他のアプリケーションにこのプロバイダの使用を許可するフラグです。
  • android:initOrder: 同じプロセス内の他のプロバイダに対して、このプロバイダを起動する順番です。
  • android:multiProcess: システムに呼び出しクライアントと同じプロセスでのプロバイダの開始を許可するフラグです。
  • android:process: プロバイダを実行するプロセスの名前です。
  • android:syncable: プロバイダのデータをサーバー上のデータと同期することを示すフラグです。

属性に関する詳細は、開発ガイドの <provider> 要素に関するトピックに記載されています。

情報に関する属性
プロバイダのオプションのアイコンとラベルです。
  • android:icon: プロバイダのアイコンを含むドローアブル リソースです。 [Settings] > [Apps] > [All] にあるアプリのリストのプロバイダラベルの横に表示されるアイコンです。
  • android:label: プロバイダ、データ、その両方を説明する、情報ラベルです。 [Settings] > [Apps] > [All] にあるアプリのリストのプロバイダラベルの横に表示されるアイコンです。

属性に関する詳細は、開発ガイドの <provider> 要素に関するトピックに記載されています。

インテントとデータアクセス

Intent を使用すると、アプリケーションはコンテンツ プロバイダに間接的にアクセスできます。 アプリケーションは、ContentResolverContentProvider のメソッドを呼び出しません。 その代わりに、アクティビティを起動するインテントを送信します。これは通常、プロバイダ独自のアプリケーションの一部となっています。 対象のアクティビティは UI のデータの取得と表示を担当します。 インテントのアクションに応じて、対象のアクティビティにより、ユーザーにプロバイダのデータの修正を求めるメッセージが表示されることがあります。 さらに、インテントには、対象のアクティビティが UI に表示する「エクストラ」データが含まれることがあります。ユーザーは使用前に、このデータを変更してプロバイダのデータを修正することもできます。

インテント アクセスを使用して、データの整合性を保証できます。プロバイダのデータの挿入、更新、削除は、厳格に定義されたビジネス ロジックによって規定されることがあります。 この場合、他のアプリケーションにデータを直接修正できるように許可すると、無効なデータが発生することがあります。 デベロッパーがインテント アクセスを使用する場合は、すべての操作を完全に文書化します。 コードを使用してデータを修正するよりも、独自のアプリケーションの UI を使用したインテント アクセスの方が優れている理由を説明します。

プロバイダのデータを修正するための受信インテントの処理は、その他のインテントの処理と同じです。 インテントの使用についての詳細は、インテントとインテント フィルタをご覧ください。

This site uses cookies to store your preferences for site-specific language and display options.

Get the latest Android developer news and tips that will help you find success on Google Play.

* Required Fields

Hooray!

Browse this site in ?

You requested a page in , but your language preference for this site is .

Would you like to change your language preference and browse this site in ? If you want to change your language preference later, use the language menu at the bottom of each page.

This class requires API level or higher

This doc is hidden because your selected API level for the documentation is . You can change the documentation API level with the selector above the left navigation.

For more information about specifying the API level your app requires, read Supporting Different Platform Versions.

Take a short survey?
Help us improve the Android developer experience.
(Sep 2017 survey)