Compatibilité avec le clavier d'images

Les utilisateurs veulent souvent communiquer à l'aide d'emoji, d'autocollants et d'autres types d'outils enrichissants contenus. Dans les versions précédentes d'Android, les claviers virtuels, également appelés claviers virtuels, Éditeurs de mode de saisie IME : seuls les emoji Unicode peuvent être envoyés aux applications. Pour un contenu enrichi, les applications API spécifiques à l'application qui ne pouvaient pas être utilisées dans d'autres applications ou qui utilisaient des solutions telles que L'envoi d'images par le biais d'une simple action de partage ou le presse-papiers.

Image montrant un clavier compatible avec la recherche d'images
Figure 1 : Exemple de prise en charge du clavier d'images.

À partir d'Android 7.1 (niveau d'API 25), le SDK Android inclut le commit Content API, qui permet aux IME d'envoyer des images et d'autres du contenu enrichi directement dans un éditeur de texte dans une application. L'API est également disponible dans la bibliothèque Support v13 à partir de la révision 25.0.0. Nous vous recommandons d'utiliser le , car elle contient des méthodes d'assistance qui simplifient l'implémentation.

Cette API vous permet de créer des applications de chat qui acceptent le contenu enrichi provenant de et les claviers qui peuvent envoyer du contenu enrichi à n'importe quelle application. L'application Google Clavier et des applications telles que Messages de Google est compatible avec Commit Content API dans Android 7.1, comme illustré dans la figure 1.

Ce document explique comment implémenter Commit Content API dans les IME et applications.

Fonctionnement

L'insertion d'images de clavier nécessite la participation de l'IME et de l'application. La La séquence suivante décrit chaque étape du processus d'insertion d'images:

  1. Lorsque l'utilisateur appuie sur un EditText, l'éditeur envoie la liste des types de contenu MIME qu'il accepte dans EditorInfo.contentMimeTypes

  2. L'IME lit la liste des types pris en charge et affiche le contenu dans le logiciel que l'éditeur peut accepter.

  3. Lorsque l'utilisateur sélectionne une image, l'IME appelle commitContent() et envoie une InputContentInfo à l'éditeur. L'appel commitContent() est analogue à l'appel l'appel commitText(), mais pour le contenu enrichi. InputContentInfo contient un URI qui identifie le contenu dans un contenu fournisseur.

Ce processus est illustré dans la figure 2:

Image montrant la séquence entre l'application et l'IME, puis l'application
Figure 2 : Flux entre l'application et l'IME

Ajouter la prise en charge des images dans les applications

Pour accepter le contenu enrichi des IME, une application doit indiquer aux éditeurs de quel type de contenu il s'agit accepte et spécifie une méthode de rappel qui est exécutée lors de la réception de contenu. L'exemple suivant montre comment créer un élément EditText qui accepte le format PNG. 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;
    }
};

Voici une explication supplémentaire:

Voici les pratiques recommandées:

  • Les éditeurs qui n'acceptent pas le contenu enrichi n'appellent pas setContentMimeTypes(), et ils quittent leur ensemble EditorInfo.contentMimeTypes à null.

  • Les éditeurs ignorent le contenu si le type MIME spécifié dans InputContentInfo est spécifié. ne correspond à aucun des types acceptés.

  • Le contenu enrichi n'a aucune incidence sur la position du texte et n'a aucune incidence sur sa position curseur. Les éditeurs peuvent ignorer la position du curseur lorsqu'ils travaillent sur du contenu.

  • Dans OnCommitContentListener.onCommitContent(), vous pouvez renvoyer true de manière asynchrone, même avant de charger le contenu.

  • Contrairement au texte, qui peut être modifié dans l'IME avant d'être validé, s'applique immédiatement. Si vous souhaitez autoriser les utilisateurs à modifier ou supprimer implémentez la logique vous-même.

Pour tester votre application, assurez-vous que votre appareil ou votre émulateur dispose d'un clavier capable d'envoyer du contenu enrichi. Vous pouvez utiliser le clavier Google sur Android 7.1 ou version ultérieure.

Ajouter la prise en charge des images aux IME

Les IME qui souhaitent envoyer du contenu enrichi aux applications doivent implémenter le commit de contenu API, comme illustré dans l'exemple suivant:

  • Remplacement onStartInput() ou onStartInputView() et lire la liste des types de contenus compatibles à partir de la cible éditeur. L'extrait de code suivant montre comment vérifier si la cible éditeur accepte les images 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.
    }
}
  • Validez le contenu dans l'application lorsque l'utilisateur sélectionne une image. Éviter d'appeler commitContent() lorsqu'un texte est en cours de composition, car il peut faire perdre le focus à l'éditeur. L'extrait de code suivant montre comment pour valider une image 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);
}

En tant qu'auteur IME, vous devrez probablement implémenter votre propre fournisseur de contenu pour pour répondre aux requêtes d'URI de contenu. La seule exception est si votre IME prend en charge le contenu de fournisseurs de contenu existants, MediaStore Pour plus d'informations sur création de fournisseurs de contenu, consultez la section Contenu fournisseur et file du fournisseur.

Si vous créez votre propre fournisseur de contenu, nous vous recommandons de ne pas l'exporter en définissant android:exported jusqu'à false Activez plutôt l'octroi d'autorisations chez le fournisseur en paramétrant android:grantUriPermission à true. Ensuite, votre IME peut accorder des autorisations pour accéder à l'URI de contenu lorsque le contenu est validé. Pour cela, vous pouvez procéder de deux façons :

  • Sur Android 7.1 (niveau d'API 25) ou version ultérieure, lorsque vous appelez commitContent(), définissez le paramètre d'indicateur sur INPUT_CONTENT_GRANT_READ_URI_PERMISSION Ensuite, l'objet InputContentInfo que l'application reçoit peut demander et des autorisations de lecture temporaires en appelant requestPermission() et releasePermission()

  • Sur Android 7.0 (niveau d'API 24) ou version antérieure, INPUT_CONTENT_GRANT_READ_URI_PERMISSION est ignoré. Par conséquent, accordez manuellement l'autorisation d'accès au contenu. Pour ce faire, vous pouvez utiliser grantUriPermission(), mais vous pouvez implémenter votre propre mécanisme qui répond à vos propres exigences.

Pour tester votre IME, assurez-vous que votre appareil ou votre émulateur dispose d'une application pouvant recevoir du contenu enrichi. Vous pouvez utiliser l'application Google Messenger sur Android 7.1 ou version ultérieure.