リッチ コンテンツを受信する

<ph type="x-smartling-placeholder">
</ph> <ph type="x-smartling-placeholder">
図 1.Unified API では 特定の UI メカニズムに関係なく、受信コンテンツを タッチ決済とメニューを長押しするか、ドラッグ&ドロップします。

ユーザーは画像や動画などの表現力豊かなコンテンツを好みますが、 アプリ内のコンテンツの移行は必ずしも容易ではありません。アプリが 機能に加え、Android 12(API レベル 31)では、 を使用すると、クリップボード、キーボード、ドラッグなど、あらゆるソースからのコンテンツを受け付けます。

次のようなインターフェースを接続できます。 OnReceiveContentListener コンテンツが挿入されたときにコールバックを受け取ることが メカニズムです。コードでは、このコールバック 1 か所で、プレーン テキストや書式付きテキストからマークアップ、画像、動画、音声ファイルまで、あらゆるコンテンツの受信を処理できるようになります。

以前の Android バージョンとの下位互換性を維持するため、この API は AndroidX で利用できますが、 Core 1.7Appcompat 1.4、 実装することをおすすめします

概要

その他の既存の API では、タップやクリックなどの各 UI メカニズムがメニューを長押しします それぞれ独自の API が用意されています。これは、コンテンツを挿入するメカニズムごとに類似のコードを追加して、各 API を個別に統合する必要があることを意味します。

さまざまなアクションと実装する相対 API を示す画像
図 2. 以前は UI ごとに異なる API がアプリで実装されていた メカニズムがあります。

OnReceiveContentListener API は実装する API を 1 つにし、このさまざまなコードパスを統合します。これにより、デベロッパーはアプリ固有のロジックに集中し、それ以外の処理はプラットフォームに委ねることができます。

簡素化された Unified API を示す画像
図 3. Unified API を使用すると、単一の すべての UI メカニズムをサポートする API。

このアプローチでは、コンテンツを挿入する新しい方法が すべてのプラットフォームでサポートを有効にするためにコードを追加で変更する必要はありません。 説明しますまた、アプリ用に完全なカスタマイズを実装する必要がある場合は、 引き続き使用できる既存の API は引き続き使用できます。 できます。

実装

この API は、単一メソッド OnReceiveContentListener とのリスナー インターフェースです。古いバージョンの Android プラットフォームをサポートするには、それに対応する AndroidX Core ライブラリの OnReceiveContentListener インターフェースの使用をおすすめします。

API を使用するには、コンテンツのタイプを指定してリスナーを実装し、 アプリで行える操作:

Kotlin

object MyReceiver : OnReceiveContentListener {
    val MIME_TYPES = arrayOf("image/*", "video/*")
    
    // ...
    
    override fun onReceiveContent(view: View, payload: ContentInfoCompat): ContentInfoCompat? {
        TODO("Not yet implemented")
    }
}

Java

public class MyReceiver implements OnReceiveContentListener {
     public static final String[] MIME_TYPES = new String[] {"image/*", "video/*"};
     // ...
}

アプリがサポートするすべてのコンテンツ MIME タイプを指定した後、リスナーの残りの部分を実装します。

Kotlin

class MyReceiver : OnReceiveContentListener {
    override fun onReceiveContent(view: View, contentInfo: ContentInfoCompat): ContentInfoCompat {
        val split = contentInfo.partition { item: ClipData.Item -> item.uri != null }
        val uriContent = split.first
        val remaining = split.second
        if (uriContent != null) {
            // App-specific logic to handle the URI(s) in uriContent.
        }
        // Return anything that your app didn't handle. This preserves the
        // default platform behavior for text and anything else that you aren't
        // implementing custom handling for.
        return remaining
    }

    companion object {
        val MIME_TYPES = arrayOf("image/*", "video/*")
    }
}

Java

 public class MyReceiver implements OnReceiveContentListener {
     public static final String[] MIME_TYPES = new String[] {"image/*", "video/*"};

     @Override
     public ContentInfoCompat onReceiveContent(View view, ContentInfoCompat contentInfo) {
         Pair<ContentInfoCompat, ContentInfoCompat> split = contentInfo.partition(
                 item -> item.getUri() != null);
         ContentInfo uriContent = split.first;
         ContentInfo remaining = split.second;
         if (uriContent != null) {
             // App-specific logic to handle the URI(s) in uriContent.
         }
         // Return anything that your app didn't handle. This preserves the
         // default platform behavior for text and anything else that you aren't
         // implementing custom handling for.
         return remaining;
     }
 }

アプリですでにインテントを使用した共有をサポートしている場合は、 コンテンツ URI を処理するためのアプリ固有のロジック。残りすべてのデータを結果から取得し、そのデータの処理をプラットフォームに委ねます。

リスナーを実装したら、アプリの適切な UI 要素でリスナーを設定します。

Kotlin

class MyActivity : Activity() {
    public override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        // ...
        val myInput = findViewById(R.id.my_input)
        ViewCompat.setOnReceiveContentListener(myInput, MyReceiver.MIME_TYPES, MyReceiver())
    }
}

Java

public class MyActivity extends Activity {
     @Override
     public void onCreate(Bundle savedInstanceState) {
         // ...

         AppCompatEditText myInput = findViewById(R.id.my_input);
         ViewCompat.setOnReceiveContentListener(myInput, MyReceiver.MIME_TYPES, new MyReceiver());
     }
}

URI 権限

読み取り権限は、すべてのリソースに対してプラットフォームによって自動的に付与、 コンテンツ URIOnReceiveContentListener に渡されます。

通常、アプリはサービスまたはアクティビティでコンテンツ URI を処理します。対象 長時間実行処理、 WorkManager。実装すると 引数を渡すことで、対象のサービスやアクティビティに権限を拡張できます。 コンテンツを Intent.setClipData フラグの設定 FLAG_GRANT_READ_URI_PERMISSION

また、現在のコンテキスト内でバックグラウンド スレッドを使用してコンテンツを処理することもできます。この場合は、サービス アカウントへの参照を維持する必要があります。 権限が不足しないように、リスナーが受信した payload オブジェクト 取り消されます。

カスタムビュー

アプリでカスタム View サブクラスを使用する場合は、 OnReceiveContentListener はバイパスされません。

View クラスで onCreateInputConnection メソッドをオーバーライドする場合は、Jetpack API の InputConnectionCompat.createWrapper を使用して InputConnection を構成してください。

View クラスが onTextContextMenuItem メソッド、メニュー項目が R.id.paste または R.id.pasteAsPlainText

Keyboard Image API との比較

OnReceiveContentListener API は、既存の Keyboard Image API の次期バージョンと考えることができます。この Unified API は、Keyboard Image API の機能に加えて、いくつかの追加機能をサポートします。デバイスと機能の互換性は、Jetpack ライブラリを使用するか、Android SDK のネイティブ API を使用するかによって異なります。

表 1. サポートされる機能と API レベル 。
アクションまたは機能 Keyboard Image API によるサポート Unified API によるサポート
キーボードからの挿入 あり(API レベル 13 以上) あり(API レベル 13 以上)
タッチ操作で貼り付けを使用して挿入メニューを長押しします なし あり
ドラッグ&ドロップで挿入する なし あり(API レベル 24 以上)
表 2. ネイティブでサポートされている機能と API レベル API。
アクションまたは機能 Keyboard Image API によるサポート Unified API によるサポート
キーボードからの挿入 あり(API レベル 25 以上) あり(Android 12 以降)
タッチ操作で貼り付けを使用して挿入メニューを長押しします なし
ドラッグ&ドロップによる挿入 なし