コンテンツ プロバイダを作成する

コンテンツ プロバイダは、データのセントラル リポジトリへのアクセスを管理します。実装すると の要素とともに、Android アプリの 1 つ以上のクラスとして 指定します。クラスの 1 つが ContentProvider: プロバイダとプロバイダの間のインターフェース できます。

コンテンツ プロバイダは、他の Google サービスで アプリケーションでは、ユーザーが Google サービスを プロバイダによって管理されているデータのクエリと変更を行うことができます。

このページでは、コンテンツ プロバイダとリストを作成する基本的なプロセスについて説明します。 使用する API のリスト。

作成を始める前に

プロバイダの構築を開始する前に、次の点を考慮してください。

  • コンテンツ プロバイダが必要かどうかを判断する。コンテンツを作成し、 プロバイダを使用します。 <ph type="x-smartling-placeholder">
      </ph>
    • 複雑なデータやファイルを他のアプリケーションに提供したい場合。
    • ユーザーが複雑なデータを自分のアプリから他のアプリにコピーできるようにしたい場合。
    • 検索フレームワークを使用してカスタム検索候補を提供したいと考えています。
    • アプリケーション データをウィジェットに公開したいと考えています。
    • AbstractThreadedSyncAdapter を実装するとします。 CursorAdapter または CursorLoader

    プロバイダは必要ない 完全に独自のアプリケーション内で使用する場合は、永続ストレージ 上記の機能のいずれも必要ありません。代わりに ストレージ システムを使用する方法については、 データとファイル ストレージの概要

  • まだ読んでいない場合は、 <ph type="x-smartling-placeholder"></ph> コンテンツ プロバイダの基本をご覧ください。

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

  1. データの未加工ストレージを設計します。コンテンツ プロバイダは、次の 2 つの方法でデータを提供します。 <ph type="x-smartling-placeholder">
    </ph>
    ファイルデータ
    など、通常はファイルに格納されるデータ 写真、音声、動画などですアプリケーションのプライベート クラウドにファイルを保存 選択します。別のアプリケーションからファイルが要求されると、 プロバイダがファイルへのハンドルを提供できます。
    「構造化」データ
    通常、データベース、配列、または同様の構造に入るデータ。 行と列のテーブルと互換性のある形式でデータを保存します。行 人や在庫のアイテムなどのエンティティを表します。列は 人物の名前やアイテムの価格など、エンティティのデータ。一般的な SQLite データベースに保存しますが、あらゆるタイプのデータを使用できます。 使用されます利用可能なストレージ タイプについて詳しくは、 Android システムについては、 データ ストレージを設計するをご覧ください。
  2. ContentProvider クラスの具体的な実装を定義する。 呼び出すことができます。このクラスは、データと他のインフラストラクチャとの間の Android システム。このクラスの詳細については、このモジュールの ContentProvider クラスを実装するセクションを実行します。
  3. プロバイダの権限文字列、コンテンツ URI、列名を定義します。目標 プロバイダのアプリでインテントを処理します。また、インテントのアクション、エクストラ データ、 使用します。さらに、アプリケーションに対して必要な権限を定義して、 データにアクセスする必要があります。これらの値をすべて定数として定義することを検討してください。 独立したコントラクト クラスを使用します。このクラスは、後で他のデベロッパーに公開できます。詳細 詳しくは、 コンテンツ URI を設計するをご覧ください。 インテントについて詳しくは、このモジュールの インテントとデータアクセス セクション
  4. サンプルデータや実装など、他のオプション要素を追加する 次の間でデータを同期できる AbstractThreadedSyncAdapter クラウドベースのデータを 一元管理できます

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

コンテンツ プロバイダは、構造化された形式で保存されたデータへのインターフェースです。作成する前に データの保存方法を決定します。使用できる任意の形式でデータを 必要に応じてデータを読み書きするようにインターフェースを設計します。

Android で利用できるデータ ストレージ技術には、次のようなものがあります。

  • 構造化データを扱う場合は、構造化データなどのリレーショナル データベース SQLite または非リレーショナル Key-Value データストア LevelDB。作業している場合 使用する場合は、音声、画像、動画メディアなどの非構造化データを 保存できます。複数の異なるタイプのストレージを組み合わせて公開できる 単一のコンテンツ プロバイダを使用できます。
  • Android システムは Room 永続ライブラリとやり取りできます。 Android 独自のプロバイダである SQLite Database API へのアクセスを提供します。 保存するために使用できます。これを使用してデータベースを作成するには、 そのサブクラスをインスタンス化し、 <ph type="x-smartling-placeholder"></ph> RoomDatabase。説明: Room を使用してローカル データベースにデータを保存する

    リポジトリを実装するためにデータベースを使用する必要はありません。プロバイダ 外部にはリレーショナル データベースと同様に一連のテーブルとして見えますが、 プロバイダの内部実装の要件ではありません。

  • ファイルデータを保存するために、Android にはさまざまなファイル指向 API があります。 ファイル ストレージについて詳しくは、 データとファイル ストレージの概要もし 音楽や動画などのメディア関連データを提供するプロバイダを設計する場合は、 テーブルのデータとファイルを結合するプロバイダがある。
  • まれに、複数のコンテンツ プロバイダを実装して、 1 つのアプリですたとえば、Google Chat を使用して 他のコンテンツ プロバイダと共有するために別のデータセットを公開する 説明します。
  • ネットワーク ベースのデータを操作するには、java.net のクラスと android.net。また、ネットワーク ベースのデータをローカル データと同期することもできます。 そのデータをテーブルやファイルとして提供できます。

: 変更が反映されていない変更をリポジトリに 下位互換性がある場合は、リポジトリを新しいバージョンに あります。また、アプリのデフォルト バージョンを 新しいコンテンツ プロバイダを実装します。この変更を加えると システムの再インストールを試みたときに、システムがクラッシュする状況から 互換性のないコンテンツ プロバイダが設定されているアプリ。

データ設計上の考慮事項

プロバイダのデータ構造を設計するためのヒントをいくつか紹介します。

  • テーブルデータには「主キー」が常に必要ですこの列はプロバイダが保持する 各行に一意の数値として渡されますこの値を使用して、行を関連する (「外部キー」として使用)できます。任意の名前を使用できますが、 この列には、BaseColumns._ID を使用するのが最適です。 最も簡単な選択肢です。プロバイダ クエリの結果を ListView には、取得した列のいずれかに名前を付ける必要があります。 _ID
  • ビットマップ画像やその他大量のファイル指向データを提供する場合は、 データをファイルに保存してから、 表しますこれを行う場合は、プロバイダのユーザーに、 ContentResolver ファイル メソッドを使用してデータにアクセスします。
  • バイナリ ラージ オブジェクト(BLOB)データ型は、サイズが異なるデータや 構造もさまざまです。たとえば、BLOB 列を使用して プロトコル バッファ JSON 構造

    BLOB を使用して、スキーマに依存しないテーブルを実装することもできます。イン このタイプのテーブルでは、主キー列、MIME タイプの列、1 つまたは複数の列を定義します。 BLOB として扱うことができます。BLOB 列内のデータの意味が指示される MIME タイプ列の値で識別されますこれにより、さまざまな行タイプを 同じテーブルに格納されます連絡先プロバイダの「データ」テーブル ContactsContract.Data は、スキーマに依存しない 表します

コンテンツ URI を設計する

コンテンツ URI は、プロバイダのデータを特定する URI です。コンテンツ URI に含まれるもの プロバイダ全体のシンボリック名(オーソリティ)と テーブルまたはファイルを指す名前(パス)。オプションの ID 部分は、 テーブル内の個々の行を表します。Google Cloud のすべてのデータアクセス方法は ContentProvider には、引数としてコンテンツ URI があります。これにより、 アクセスするテーブル、行、ファイルを決定します。

コンテンツ URI について詳しくは、以下をご覧ください。 <ph type="x-smartling-placeholder"></ph> コンテンツ プロバイダの基本をご覧ください。

オーソリティを設計する

プロバイダには通常、Android 内部の名前として機能する 1 つのオーソリティがあります。宛先 他のプロバイダとの競合を回避する、インターネット ドメインの所有権を使用する(逆方向) プロバイダ オーソリティのベースとして設定できます。この推奨事項は Android や プロバイダ オーソリティを名前の拡張子として定義できます。 パッケージの 1 つを取得します。

たとえば、Android パッケージ名が com.example.<appname> の場合は、プロバイダに 権限 com.example.<appname>.provider

パス構造を設計する

デベロッパーは通常、認証局からのコンテンツ URI を作成するには、 できます。たとえば、table1table2 のリストを取得するには、前の例の権限と組み合わせて コンテンツ URI com.example.<appname>.provider/table1com.example.<appname>.provider/table2。パスは セグメントは 1 つだけで、パスの各レベルに表を用意する必要はありません。

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

慣例として、プロバイダはコンテンツ URI を受け入れることで、テーブル内の 1 行へのアクセスを提供 URI の末尾にある行の ID 値に置き換えます。また、慣例により、プロバイダは ID 値をテーブルの _ID 列に追加して、リクエストされたアクセスを実行します。 表示されます。

この規則により、プロバイダにアクセスするアプリの一般的な設計パターンが容易になります。アプリ プロバイダに対してクエリを実行し、結果の Cursor を表示します。 の ListViewCursorAdapter を使用します。 CursorAdapter の定義には、 Cursor_ID に設定

ユーザーは表示された行のいずれかを UI から選択して、 分析できますアプリは、Cursor から対応する行を取得し、 ListView は、この行の _ID 値を取得して、 コンテンツ URI を受け取り、アクセス リクエストをプロバイダに送信します。その後、プロバイダは ユーザーが選択した行に対するクエリまたは修正です。

コンテンツ URI パターン

受信コンテンツの URI に対して実行するアクションを選択できるように、Provider API には UriMatcher というコンビニエンス クラス: コンテンツ URI パターンを 使用します。次の switch ステートメントで整数値を使用できます。 は、特定のパターンに一致するコンテンツ 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 を認識します。たとえば、content://com.example.app.provider/table3/1 1table3)。

使用できるコンテンツ URI パターンは次のとおりです。

content://com.example.app.provider/*
プロバイダ内のすべてのコンテンツ URI と一致します。
content://com.example.app.provider/table2/*
テーブル dataset1 のコンテンツ URI と照合します。 および dataset2 ですが、table1 またはコンテンツ URI とは一致しません table3
content://com.example.app.provider/table3/#
コンテンツ URI と一致 次のように table3 の単一行に対して によって識別される行に対する content://com.example.app.provider/table3/6 6

次のコード スニペットは、UriMatcher のメソッドの動作を示しています。 このコードは、テーブル全体の URI を、別のテーブルの URI とは異なる方法で処理します。 コンテンツ URI パターンを使用して行を 1 つに テーブルに対する content://<authority>/<path> 単一行の場合は content://<authority>/<path>/<id>

メソッド addURI() は、 権限とパスを指定します。メソッド match() は URI の整数値を返します。switch ステートメント クエリの対象はテーブル全体か、単一レコードかを選択します。

Kotlin

private val sUriMatcher = UriMatcher(UriMatcher.NO_MATCH).apply {
    /*
     * The calls to addURI() go here for all the content URI patterns that the provider
     * recognizes. 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.
     */
    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.
     */
    addURI("com.example.app.provider", "table3/#", 2)
}
...
class ExampleProvider : ContentProvider() {
    ...
    // Implements ContentProvider.query()
    override fun query(
            uri: Uri?,
            projection: Array<out String>?,
            selection: String?,
            selectionArgs: Array<out String>?,
            sortOrder: String?
    ): Cursor? {
        var localSortOrder: String = sortOrder ?: ""
        var localSelection: String = selection ?: ""
        when (sUriMatcher.match(uri)) {
            1 -> { // If the incoming URI was for all of table3
                if (localSortOrder.isEmpty()) {
                    localSortOrder = "_ID ASC"
                }
            }
            2 -> {  // If the incoming URI was for a single row
                /*
                 * 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.
                 */
                localSelection += "_ID ${uri?.lastPathSegment}"
            }
            else -> { // If the URI isn't recognized,
                // do some error handling here
            }
        }

        // Call the code to actually do the query
    }
}

Java

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

    static {
        /*
         * The calls to addURI() go here for all the content URI patterns that the provider
         * recognizes. For this snippet, only the calls for table 3 are shown.
         */

        /*
         * Sets the integer value for multiple rows in table 3 to one. No wildcard is used
         * in the path.
         */
        uriMatcher.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.
         */
        uriMatcher.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 (uriMatcher.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 isn't recognized, do some error handling here
        }
        // Call the code to actually do the query
    }

もう 1 つのクラス 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 メソッド。

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

  • onCreate() を除くすべてのメソッド 同時に複数のスレッドから呼び出せるため、スレッドセーフである必要があります。学習内容 複数のスレッドの詳細については、 <ph type="x-smartling-placeholder"></ph> プロセスとスレッドの概要
  • onCreate() では長時間のオペレーションを行わないでください。実際に必要になるまで初期化タスクを延期する。 onCreate() メソッドの実装に関するセクション 詳しく説明します。
  • これらのメソッドは実装する必要がありますが、コード内で 期待されるデータ型を返します。たとえば、Gmail 以外のアプリが テーブルへのデータ挿入を禁止するには、 insert()と復路 0.

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

ContentProvider.query() メソッドは Cursor オブジェクトを返す必要があります。そうでない場合は、 失敗した場合は Exception をスローします。データとして SQLite データベースを使用している場合 次のフィールドのいずれかから返された CursorSQLiteDatabase クラスの query() メソッド。

クエリがどの行とも一致しない場合は、Cursor を返します。 getCount() メソッドが 0 を返すインスタンス。 クエリ処理中に内部エラーが発生した場合のみ null を返します。

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

Android システムが Exception と通信できる必要があります。 必要があります。Android では、役に立つ次の例外に対してこれを実行できます。 いくつかご紹介します

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

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

このメソッドは、新しい行のコンテンツ URI を返します。これを構築するには、新しい を使用して、行の主キー(通常は _ID 値)をテーブルのコンテンツ URI にマッピングします。 withAppendedId()

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

delete() メソッド データストレージから行を削除する必要は ありません同期アダプターを使用している場合 削除する場合は、削除した行を 「削除」コマンドをフラグを設定することをおすすめします。同期アダプターは、 プロバイダから削除する前に、削除された行をチェックし、サーバーから削除する。

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

update() メソッドは、Pod 内で使用されるのと同じ ContentValues 引数を取ります。 insert() および 使用されるのと同じ selection 引数と selectionArgs 引数。 delete()ContentProvider.query()。 これにより、これらのメソッド間でコードを再利用できる場合があります。

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

Android システムが onCreate() を呼び出す API によって開始されます。高速実行の初期化のみを実行する プロバイダが実際にデータを取得するまで、データベースの作成とデータの読み込みを遅らせます。 受信します。時間のかかるタスクを onCreate()さん、スピードを 確認します。逆に、これによりプロバイダから他のシステムへの応答が遅くなります。 説明します。

次の 2 つのスニペットは、Google Cloud コンソールと ContentProvider.onCreate()、 <ph type="x-smartling-placeholder"></ph> Room.databaseBuilder()。最初の スニペットは、Terraform の ContentProvider.onCreate()。ここで、 データベース オブジェクトが作成され、データアクセス オブジェクトに対するハンドルが作成されます。

Kotlin

// Defines the database name
private const val DBNAME = "mydb"
...
class ExampleProvider : ContentProvider() {

    // Defines a handle to the Room database
    private lateinit var appDatabase: AppDatabase

    // Defines a Data Access Object to perform the database operations
    private var userDao: UserDao? = null

    override fun onCreate(): Boolean {

        // Creates a new database object
        appDatabase = Room.databaseBuilder(context, AppDatabase::class.java, DBNAME).build()

        // Gets a Data Access Object to perform the database operations
        userDao = appDatabase.userDao

        return true
    }
    ...
    // Implements the provider's insert method
    override fun insert(uri: Uri, values: ContentValues?): Uri? {
        // Insert code here to determine which DAO to use when inserting data, handle error conditions, etc.
    }
}

Java

public class ExampleProvider extends ContentProvider

    // Defines a handle to the Room database
    private AppDatabase appDatabase;

    // Defines a Data Access Object to perform the database operations
    private UserDao userDao;

    // Defines the database name
    private static final String DBNAME = "mydb";

    public boolean onCreate() {

        // Creates a new database object
        appDatabase = Room.databaseBuilder(getContext(), AppDatabase.class, DBNAME).build();

        // Gets a Data Access Object to perform the database operations
        userDao = appDatabase.getUserDao();

        return true;
    }
    ...
    // Implements the provider's insert method
    public Cursor insert(Uri uri, ContentValues values) {
        // Insert code here to determine which DAO to use when inserting data, handle error conditions, etc.
    }
}

ContentProvider MIME タイプを実装する

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

getType()
任意のプロバイダに実装する必須メソッドの 1 つ。
getStreamTypes()
プロバイダがファイルを提供する場合に実装が期待されるメソッド。

テーブルの MIME タイプ

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

テキスト、HTML、JPEG などの一般的なデータタイプの場合、 getType() は標準の そのデータの MIME タイプ。これらの標準タイプの完全なリストは、 IANA MIME メディアタイプ 確認できます

テーブルデータの行を指すコンテンツ URI の場合、 返品可能(返品手数料: getType()) Android のベンダー固有の MIME 形式の MIME タイプ:

  • タイプ部分: vnd
  • サブタイプの部分: <ph type="x-smartling-placeholder">
      </ph>
    • URI パターンが 1 行の場合: android.cursor.item/
    • URI パターンが複数の行の場合: 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

ファイルの MIME タイプ

プロバイダがファイルを提供している場合は、 getStreamTypes()。 このメソッドは、プロバイダが使用しているファイルの MIME タイプの String 配列を返します。 返すことができます。提供する MIME タイプを MIME タイプでフィルタする クライアントが処理する必要のある MIME タイプのみを返すようにできます。

たとえば、写真の画像を JPG、 PNG、GIF のいずれかの形式にします。 アプリケーションでフィルタ文字列 image/* を指定して ContentResolver.getStreamTypes() を呼び出した場合、 「image」です。 ContentProvider.getStreamTypes() メソッドは配列を返します。

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

アプリが JPG ファイルのみを必要とする場合は、呼び出します。 ContentResolver.getStreamTypes() は、フィルタ文字列 *\/jpeg に置き換えます。 getStreamTypes() の戻り値:

{"image/jpeg"}

フィルタ文字列でリクエストされた MIME タイプをプロバイダが提供していない場合は、 getStreamTypes() null を返します。

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

コントラクト クラスは public final クラスであり、 URI、列名、MIME タイプ、プロバイダに関連するその他のメタデータ。クラス Google は、プロバイダとその他のアプリケーションの間の契約を、プロバイダが URI、列名、列の実際の値が変更された場合でも 使用できます。

コントラクト クラスは通常、定数、 そのため、デベロッパーが列名や URI に誤った値を使用する可能性が低くなります。なぜなら、 Javadoc ドキュメントを含めることができます。統合開発環境である Android Studio では、コントラクト クラスから定数名を予測入力し、Javadoc を 定数。

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

ContactsContract クラスとそのネストされたクラスは、 構築できます。

コンテンツ プロバイダの権限を実装する

Android システムのあらゆる側面の権限とアクセスについては、 セキュリティに関するヒント データとファイル ストレージの概要でも、 では、さまざまなタイプのストレージで有効になっているセキュリティと権限について説明します。 簡単に言うと、重要なポイントは次のとおりです。

  • デフォルトでは、デバイスの内部ストレージに保存されたデータファイルは、 保証します。
  • 作成した SQLiteDatabase データベースは 保証します。
  • 外部ストレージに保存したデータファイルは、デフォルトでは「一般公開」になっています。 誰でも読み取れるようにできます。コンテンツ プロバイダを使用して、フォルダ内のファイルへのアクセスを制限することはできません 外部ストレージ。外部ストレージは、他のアプリケーションが他の API 呼び出しを使用してそれらのファイルを読み書きできるためです。
  • このメソッドは、デバイスの内部ストレージにあるファイルや SQLite データベースを開くか作成するための呼び出しです。 他のすべてのアプリケーションに読み取りと書き込みの両方のアクセス権が付与される可能性があります。もし 内部ファイルまたはデータベースをプロバイダのリポジトリとして使用し、 「誰でも読み取れる」または「world-writeable」プロバイダに設定した権限のほか、Google Workspace の データは保護されません。Google Cloud 内のファイルとデータベースへの 内部ストレージは「非公開」です。プロバイダのリポジトリでは変更しないでください。

コンテンツ プロバイダの権限を使用してデータへのアクセスを制御する場合は、 次のような内部ファイル、SQLite データベース、クラウドにデータを保存できます。 アプリケーションを作成し、ファイルやデータベースをそのアプリケーションに公開することはできません。

権限を実装する

デフォルトでは、基盤となるデータが デフォルトではプロバイダに権限が設定されていないためです。これを変更するには マニフェスト ファイルで、属性または子要素を使用してプロバイダの権限を設定する <provider> 要素の要素です。プロバイダ全体に適用する権限を設定できますが、 特定のテーブル、特定のレコード、 または 3 つすべてに対して適用できます

プロバイダの権限を定義するには、1 つ以上の マニフェスト ファイル内の <permission> 要素。Pod を スコープを設定する場合は、プロバイダに Java スタイルのスコープを android:name 属性。たとえば、読み取り権限に com.example.app.provider.permission.READ_PROVIDER

次のリストは、プロバイダ権限の範囲を よりきめ細かく制御できます。 スコープが広い権限よりも、きめ細かい権限が優先されます。

単一の読み取り / 書き込みプロバイダ レベルの権限
プロバイダ全体に対する読み取りと書き込みの両方を制御する 1 つの権限。 次のメソッドの android:permission 属性を <provider> 要素。
プロバイダ レベルの読み取り権限と書き込み権限を分離する
プロバイダ全体に対する読み取り権限と書き込み権限。お客様が指定する android:readPermission と 次の属性の android:writePermission 属性: <provider> 要素。権限は、Compute Engine インスタンスで android:permission
パスレベルの権限
プロバイダのコンテンツ URI に対する読み取り、書き込み、読み取り/書き込み権限。お客様が指定 各 URI の情報を 次の要素の <path-permission> 子要素: <provider> 要素。指定するコンテンツ URI ごとに、1 つずつ 読み取り/書き込み権限、読み取り権限、書き込み権限、またはこの 3 つすべてです。読み取りと 書き込み権限は、読み取り/書き込み権限よりも優先されます。また、パスレベル プロバイダ レベルの権限よりも優先されます。
一時的な権限
アプリケーションへの一時的なアクセスを許可する権限レベル。アプリケーションが 必要な権限がないということです。一時的な アクセス機能を使用することで、アプリケーションがリクエストする権限の数を削減できます。 確認します。一時的な権限をオンにすると、必要なすべてのアプリが 永続的な権限とは、永続的なアクセス手段のことで、 保護します。

たとえば、メール プロバイダとアプリを実装していて、 外部の画像ビューア アプリケーションで、組織の 接続します。権限を要求せずに画像ビューアに必要なアクセス権を付与するには、 写真のコンテンツ URI に対して一時的な権限を設定できます。

メールアプリを設計する際は、 ユーザーが写真を表示しようとしたときに、アプリから 権限フラグを画像ビューアに提供します。画像ビューアは その写真をメール プロバイダに照会します。閲覧者が写真を取得していなくても プロバイダに対する通常の読み取り権限があることを確認します。

一時的な権限を有効にするには、 次の要素の android:grantUriPermissions 属性: <provider> 要素を指定するか、1 つ以上の要素を追加します。 <grant-uri-permission> 個の子要素を <provider> 要素。発信 Context.revokeUriPermission() で、一時的な権限に関連付けられたコンテンツ URI のサポートを 接続します。

この属性の値により、プロバイダのどの程度をアクセス可能にするかが決まります。 この属性が "true" に設定されている場合、システムによって一時的な権限が付与されます。 権限を付与して、必要な他の権限がオーバーライドされる プロバイダ レベルまたはパスレベルの権限で設定できます。

このフラグが "false" に設定されている場合は、次を追加します。 <grant-uri-permission> 個の子要素を <provider> 要素。各子要素では、コンテンツ URI または 一時的なアクセス権が付与される URI。

一時的なアクセス権をアプリに委任するには、インテントに FLAG_GRANT_READ_URI_PERMISSION フラグ、 FLAG_GRANT_WRITE_URI_PERMISSION フラグ、またはその両方。これらの setFlags() メソッドで設定します。

android:grantUriPermissions 属性が存在しない場合は、 "false"

<provider>要素

Activity コンポーネントや Service コンポーネントと同様に、 ContentProvider のサブクラス は、アプリケーションのマニフェスト ファイルで定義され、 <provider> 要素。Android システムは次の情報を取得します。 要素:

権限 (android:authorities
システム内のプロバイダ全体を識別するシンボリック名。この 属性の詳細については、このモジュールの コンテンツ URI を設計するをご覧ください。
プロバイダのクラス名 (android:name)
ContentProvider を実装するクラス。このクラスは、 詳しくは ContentProvider クラスを実装するセクションを実行します。
権限
他のアプリがアクセスするために必要とする権限を指定する属性 次のように指定します。 <ph type="x-smartling-placeholder">

権限とそれに対応する属性については、 詳細は コンテンツ プロバイダの権限を実装するセクション。

起動と制御の属性
これらの属性により、Android システムがプロバイダ、 次のようなランタイム設定があります。 <ph type="x-smartling-placeholder">
    </ph>
  • android:enabled: システムにプロバイダの起動を許可するフラグ
  • android:exported: 他のアプリがこのプロバイダを使用することを許可するフラグ
  • android:initOrder: このプロバイダを起動する順序。 他のプロバイダとの比較
  • android:multiProcess: システムにプロバイダの起動を許可するフラグ (呼び出し側クライアントと同じプロセスで処理)
  • android:process: プロバイダが実行されるプロセスの名前
  • android:syncable: プロバイダのデータがエクスポートされることを示すフラグ サーバー上のデータと同期される

これらの属性の詳細については、 <provider> 要素。

情報属性
プロバイダのオプションのアイコンとラベル: <ph type="x-smartling-placeholder">
    </ph>
  • android:icon: プロバイダのアイコンを含むドローアブル リソース。 アイコンは、Google Chat のアプリのリストでプロバイダのラベルの横に [設定] >アプリ >すべて
  • android:label: プロバイダを説明する情報ラベル。 分析できますこのラベルは、 [設定] >アプリ >すべて

これらの属性の詳細については、 <provider> 要素。

注: Android 11 以降を対象としている場合は、 パッケージの公開設定に関するドキュメント 詳細な構成が必要です。

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

アプリは Intent で間接的にコンテンツ プロバイダにアクセスできます。 アプリは、ContentResolver または ContentProvider。代わりに、アクティビティを開始するインテントを送信します。 これは多くの場合、プロバイダ独自のアプリケーションの一部です。デスティネーション アクティビティの管理 UI でデータを取得して表示します。

インテントのアクションに応じて、 デスティネーション アクティビティでは、ユーザーにプロバイダのデータを変更するよう促すこともできます。 インテントに「エクストラ」が含まれる場合もあります。デスティネーション アクティビティが表示するデータ 確認できます。ユーザーは、このデータを使用して変更する前に、 必要があります。

インテント アクセスを使用すると、データの整合性を確保できます。プロバイダによっては、 厳密に定義されたビジネス ロジックに従って、データの挿入、更新、削除が行われること。条件 その場合、他のアプリがデータを直接変更できるようにすると、 無効なデータを検出します

開発者にインテント アクセスを使用してもらいたい場合は、その内容を徹底的に文書化してください。 インテント アクセスを試みるよりもアプリの UI を使用した方がよい理由を説明する コードを使用してデータを変更できます

プロバイダのデータを変更する受信インテントの処理は、 他のインテントを処理する方法を紹介します。インテントの使用について詳しくは、 インテントとインテント フィルタ

その他の関連情報については、 カレンダー プロバイダの概要