a を使用するのContentProvider
は正しいことです。他のアプリは、コンテンツの構造や構成を理解する必要はありません。コンテンツ URI は不透明な識別子として使用でき、(API 11 以降では) 1 つの URI に複数のタイプを含めることができます。
テキストとして貼り付け
を実装するContentProvider.openTypedAssetFile
と、プロバイダーは画像を要求するクライアントに画像を提供し、ベンダー固有の MIME タイプを要求するクライアントに内部データ形式を提供できます。ClipData.Item.coerceToText
これは、が任意のコンテンツ URI からテキストを取得するために使用するメカニズムです: typetext/*
を要求し、返されたストリームを文字列に読み取ります。(無限のテキスト ストリームをコピーしようとしないでください!) この呼び出しが失敗した場合にのみ、URI 自体のテキストを配置します。レガシーgetText
API もこのcoerceToText
関数を使用します。これにより、従来のクライアントとテキストのみのクライアントが整理されます。
画像として貼り付け
画像のみが必要なクライアントは、上記と同じメカニズムを使用する必要があります。つまり、テキストContentProvider.openTypedAssetFile
として使用されますが、要求されたタイプはimage/*
. ただし、すべてのクライアントがそれを行うことに依存できるとは思わないため、(ベンダー固有のタイプではなく) その URI のイメージ タイプを実装ContentProvider.getType
して返すことをお勧めします。ContentProvider.getStreamTypes
query
(the value of) という列を持つカーソルを返すように実装しますMediaStore.Images.ImageColumns.DATA
。MediaStore.Images.ImageColumns
これらのクライアントにメタデータを提供する場合は、他の列を含めることもできます。
openFile
次に、画像のファイル記述子を返すように実装するだけです。引数を確認して、mode
他のアプリにファイルへの書き込みを許可しないようにしてください。あなたが持っているパスから戻る必要があるParcelFileDescriptor.open
を作成するために呼び出すことができます。ParcelFileDescriptor
ベンダー固有のオブジェクトとして貼り付け
これで、サービスのすべてのサードパーティ クライアントが処理されました。では、自分のアプリに貼り付けてみてはどうでしょうか? ここでできることは 2 つあります。前のセクションで述べたように、 を使用ContentResolver.openTypedAssetDescriptorFile
してベンダー固有の型を要求し、実装ContentProvider.openTypedAssetFile
してその型のストリームを返すことができます。これは、アプリ固有のデータがシリアル化されたデータなどを含む特別な種類のファイルである場合に適しています。アプリ固有のコンテンツがデータベースの行である場合は、 を使用できます。上記query
の列だけでなく、返されたカーソルに任意のアプリ固有のデータを配置できます。MediaStore
ContentProvider
これらの方法のいずれかを使用すると、ストレージ メカニズムからフロントエンドを抽象化するための便利な方法が提供されます。私は 1 つのアプリで共有を実装するときにそれを行いました。これは非常に前向きな変化であり、明確な境界を課し、データベースへの卑劣でカプセル化に違反するすべてのアクセスをクリーンアップすることを余儀なくされ、その結果、コードベースの保守が容易になりました。 . Loader
また、 s、Adapter
s、およびContentObserver
s の組み込みサポートを使用して、フロントエンド コードのサイズを縮小することも容易になりました。
しかし、この強制的なカプセル化の境界がアプリにとって不適切な場所にある場合や、貼り付け先がカーソルやシリアル化されたデータだけでなく、同じ Java オブジェクトにアクセスする必要がある場合もあります。その場合、貼り付け先のコードが貼り付けられた URI を解析し、そこから識別子を読み取るのは簡単です。次に、関連するデータ オブジェクトへの参照を取得するために、(既存のメカニズムを使用して) バックエンド コードと直接対話できます。使用する必要はまったくありませんContentResolver
。
結論
これらはすべて、開くには大きなワームの缶のように思えるかもしれませんが、ある意味ではそうです。しかしContentProvider
、実際には、1 つのことだけを実行したい場合に実装するのは非常に簡単です。また、いったん開始すると、解決に役立つ他の問題が見つかる可能性があります。