イメージ キーボードのサポート

ユーザーは多くの場合、絵文字やステッカーなど、さまざまな情報を使用してコミュニケーションを 説明します。以前のバージョンの Android では、ソフト キーボード(別名「ソフト キーボード」)が インプット メソッド エディタ IME - Unicode 絵文字のみをアプリに送信できます。リッチ コンテンツの場合、 他のアプリで使用できない、または次のような回避策を使用したアプリ固有の API シンプルな共有操作による画像の送信 アクセスできます。

画像検索をサポートするキーボードの画像
図 1. イメージ キーボードのサポートの例。

Android 7.1(API レベル 25)以降、Android SDK には Content API は、IME が画像やその他のコンテンツを送信するためのユニバーサルな方法を提供します。 アプリのテキスト エディタに直接エクスポートできます。この API は サポート ライブラリをサポートしています。Support API の使用には、 実装を簡素化するヘルパー メソッドが含まれるためです。

この API を使用すると、あらゆるユーザーのリッチ コンテンツを受け入れるメッセージ アプリを構築できます。 あらゆるアプリにリッチ コンテンツを送信できるキーボードのほか、Google キーボード Google Chat でメッセージを Google Android 7.1 では、図 1 のとおり、Commit Content API をサポートしています。

このドキュメントでは、IME と 。

仕組み

キーボードの画像挿入には、IME とアプリからの参加が必要です。「 次の順序で、画像挿入プロセスの各ステップを説明します。

  1. ユーザーが EditText をタップすると、 エディタは、受け入れ可能な MIME コンテンツ タイプのリストを EditorInfo.contentMimeTypes

  2. IME は、サポートされているタイプのリストを読み取り、エディタが受け入れ可能なコンテンツをソフト キーボード内に表示します。

  3. ユーザーが画像を選択すると、IME は commitContent() 送信され、 InputContentInfo 移動します。commitContent() の呼び出しは、 commitText() の呼び出し。ただし、リッチ コンテンツ用です。InputContentInfo には、次の URI が含まれている。 は、コンテンツ内のコンテンツを識別します。 提供します

このプロセスを図 2 に示します。

アプリから IME とアプリに戻るシーケンスを示す画像
図 2. アプリケーションから IME へのフロー。

アプリに画像サポートを追加する

IME からのリッチ コンテンツを受け入れるには、アプリが IME にコンテンツ タイプを伝える必要があります。 は、コンテンツの受信時に実行されるコールバック メソッドを受け入れ、指定します。 次の例は、PNG を受け入れる EditText を作成する方法を示しています。 images:

Kotlin

var editText: EditText = object : EditText(this) {
    override fun onCreateInputConnection(outAttrs: EditorInfo): InputConnection {
        var ic = super.onCreateInputConnection(outAttrs)
        EditorInfoCompat.setContentMimeTypes(outAttrs, arrayOf("image/png"))
        val mimeTypes = ViewCompat.getOnReceiveContentMimeTypes(this)
        if (mimeTypes != null) {
            EditorInfoCompat.setContentMimeTypes(outAttrs, mimeTypes)
            ic = InputConnectionCompat.createWrapper(this, ic, outAttrs)
        }
        return ic
    }
}

Java

EditText editText = new EditText(this) {
    @Override
    public InputConnection onCreateInputConnection(EditorInfo outAttrs) {
        InputConnection ic = super.onCreateInputConnection(outAttrs);
        EditorInfoCompat.setContentMimeTypes(outAttrs, new String[]{"image/png"});
        String[] mimeTypes = ViewCompat.getOnReceiveContentMimeTypes(this);
        if (mimeTypes != null) {
            EditorInfoCompat.setContentMimeTypes(outAttrs, mimeTypes);
            ic = InputConnectionCompat.createWrapper(this, ic, outAttrs);
        }
        return ic;
    }
};

以下で詳しく説明します。

  • この例ではサポート ライブラリを使用しているため、 android.support.v13.view.inputmethodandroid.view.inputmethod

  • この例では、EditText を作成してそれをオーバーライドします。 onCreateInputConnection(EditorInfo) メソッドを InputConnectionInputConnection は、IME とデバイスの間の通信チャネルです。 応答します。

  • コール super.onCreateInputConnection() 組み込みの動作(テキストの送受信)が維持され、 InputConnection への参照を提供します。

  • setContentMimeTypes() は、サポートされている MIME タイプのリストを EditorInfo。発信 setContentMimeTypes()までに super.onCreateInputConnection()

  • IME がコンテンツをコミットするたびに、callback が実行されます。メソッド onCommitContent() 参照先が InputContentInfoCompat, コンテンツ URI が含まれています。

    • API レベル 25 でアプリを実行している場合は、権限をリクエストして解放する 以上、かつ INPUT_CONTENT_GRANT_READ_URI_PERMISSION フラグが IME によって設定されていること。それ以外の場合は、すでにコンテンツへのアクセス権があります URI は、IME によって付与されているか、コンテンツ プロバイダによって付与されているため、 アクセスは制限されません詳細については、イメージ サポートの追加先 IME
  • createWrapper() InputConnection、変更された EditorInfo、コールバックをラップ 新しい InputConnection に変換して返します。

おすすめの方法は次のとおりです。

  • リッチ コンテンツに対応していないエディタでは、 setContentMimeTypes()EditorInfo.contentMimeTypes の設定はそのままにします。 null に送信。

  • InputContentInfo で指定された MIME タイプの場合、エディタはコンテンツを無視します。 使用できるタイプのいずれにも一致しません。

  • リッチ コンテンツはテキストの位置に影響せず、テキストの位置の影響も受けない カーソルを合わせます。コンテンツを操作する際、エディタはカーソルの位置を無視できます。

  • エディタの OnCommitContentListener.onCommitContent() メソッドを使用すると、非同期で true を返すことができます。 コンテンツを読み込みます。

  • コミットする前に IME で編集できるテキストとは異なり、リッチ 即座に commit されます。ユーザーにファイルの編集や削除を許可するには、 自分でロジックを実装する必要があります。

アプリをテストするには、デバイスまたはエミュレータに、送信可能なキーボードが備わっていることを確認してください。 リッチ コンテンツを利用できます。Android 7.1 以降の場合は、Google キーボードを使用できます。

IME に画像サポートを追加する

リッチ コンテンツをアプリに送信する IME はコミット コンテンツを実装する必要がある 必要があります。

  • オーバーライド onStartInput() または onStartInputView() を実行して、サポートされているコンテンツ タイプのリストをターゲットから読み取る クリックします。ターゲット エディタが GIF 画像を受け入れるかどうかをチェックするコード スニペットを以下に示します。

Kotlin

override fun onStartInputView(editorInfo: EditorInfo, restarting: Boolean) {
    val mimeTypes: Array<String> = EditorInfoCompat.getContentMimeTypes(editorInfo)

    val gifSupported: Boolean = mimeTypes.any {
        ClipDescription.compareMimeTypes(it, "image/gif")
    }

    if (gifSupported) {
        // The target editor supports GIFs. Enable the corresponding content.
    } else {
        // The target editor doesn't support GIFs. Disable the corresponding
        // content.
    }
}

Java

@Override
public void onStartInputView(EditorInfo info, boolean restarting) {
    String[] mimeTypes = EditorInfoCompat.getContentMimeTypes(editorInfo);

    boolean gifSupported = false;
    for (String mimeType : mimeTypes) {
        if (ClipDescription.compareMimeTypes(mimeType, "image/gif")) {
            gifSupported = true;
        }
    }

    if (gifSupported) {
        // The target editor supports GIFs. Enable the corresponding content.
    } else {
        // The target editor doesn't support GIFs. Disable the corresponding
        // content.
    }
}
  • ユーザーが画像を選択したときに、アプリにコンテンツを commit します。電話をかけない commitContent(): 作成中のテキストがある場合 エディタがフォーカスを 失う可能性があります次のコード スニペットは、 GIF 画像を確定できます。

Kotlin

// Commits a GIF image.

// @param contentUri = Content URI of the GIF image to be sent.
// @param imageDescription = Description of the GIF image to be sent.

fun commitGifImage(contentUri: Uri, imageDescription: String) {
    val inputContentInfo = InputContentInfoCompat(
            contentUri,
            ClipDescription(imageDescription, arrayOf("image/gif")),
            null
    )
    val inputConnection = currentInputConnection
    val editorInfo = currentInputEditorInfo
    var flags = 0
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N_MR1) {
        flags = flags or InputConnectionCompat.INPUT_CONTENT_GRANT_READ_URI_PERMISSION
    }
    InputConnectionCompat.commitContent(inputConnection, editorInfo, inputContentInfo, flags, null)
}

Java

// Commits a GIF image.

// @param contentUri = Content URI of the GIF image to be sent.
// @param imageDescription = Description of the GIF image to be sent.

public static void commitGifImage(Uri contentUri, String imageDescription) {
    InputContentInfoCompat inputContentInfo = new InputContentInfoCompat(
            contentUri,
            new ClipDescription(imageDescription, new String[]{"image/gif"}),
            null
    );
    InputConnection inputConnection = getCurrentInputConnection();
    EditorInfo editorInfo = getCurrentInputEditorInfo();
    Int flags = 0;
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N_MR1) {
        flags |= InputConnectionCompat.INPUT_CONTENT_GRANT_READ_URI_PERMISSION;
    }
    InputConnectionCompat.commitContent(
            inputConnection, editorInfo, inputContentInfo, flags, null);
}

IME 作成者は、ほとんどの場合、独自のコンテンツ プロバイダを実装して コンテンツ URI リクエストに応答できます。例外は、IME がコンテンツをサポートしている場合です。 コンテンツプロバイダ MediaStore。詳細については、 コンテンツ プロバイダについて詳しくは、 providerfile を指定 プロバイダに関するドキュメントをご覧ください。

独自のコンテンツ プロバイダを作成している場合は、エクスポートしないことをおすすめします。 「新規顧客の獲得」目標を android:exportedfalse。代わりに、プロバイダで権限の付与を有効にするには、 android:grantUriPermission 宛先: true。IME は、コンテンツがコミットされると、コンテンツ URI にアクセスするパーミッションを付与できるようになります。変換には次の 2 つの方法があります。

  • Android 7.1(API レベル 25)以降では、commitContent() を呼び出すときに以下を行います。 フラグ パラメータを INPUT_CONTENT_GRANT_READ_URI_PERMISSION。 その後、アプリが受け取る InputContentInfo オブジェクトは、 一時的な読み取り権限を解放するには、 requestPermission() および releasePermission()

  • Android 7.0(API レベル 24)以前では、 INPUT_CONTENT_GRANT_READ_URI_PERMISSION は無視されるため、手動で付与してください 許可する必要があります。これを行う方法の一つは grantUriPermission() ですが、独自のメカニズムを実装して、 独自の要件を満たすことができます。

IME をテストするには、デバイスまたはエミュレータに搭載されているアプリが リッチ コンテンツを利用できます。Google Messenger アプリは Android 7.1 以降で利用できます。