Les utilisateurs souhaitent souvent communiquer à l'aide d'emoji, d'autocollants et d'autres types de contenus enrichis. Dans les versions précédentes d'Android, les claviers virtuels, également appelés éditeurs de mode de saisie, ou IME, ne pouvaient envoyer que des emoji Unicode aux applications. Pour le contenu enrichi, les applications développaient des API spécifiques qui ne pouvaient pas être utilisées dans d'autres applications ou utilisaient des solutions de contournement telles que l'envoi d'images via une action de partage simple ou le presse-papiers.
À partir d'Android 7.1 (niveau d'API 25), le SDK Android inclut Commit Content API, qui offre aux IME un moyen universel d'envoyer des images et d'autres contenus enrichis directement à 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 la bibliothèque Support, car elle contient des méthodes d'assistance qui simplifient l'implémentation.
Cette API vous permet de créer des applications de messagerie qui acceptent le contenu enrichi de n'importe quel clavier, ainsi que des claviers pouvant envoyer du contenu enrichi à n'importe quelle application. Le clavier Google et des applications telles que Messages par Google sont compatibles 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 les applications.
Fonctionnement
L'insertion d'images au clavier nécessite la participation de l'IME et de l'application. La séquence suivante décrit chaque étape du processus d'insertion d'images:
Lorsque l'utilisateur appuie sur un
EditText
, l'éditeur envoie une liste des types de contenu MIME acceptés dansEditorInfo.contentMimeTypes
.L'IME lit la liste des types compatibles et affiche dans le clavier virtuel le contenu que l'éditeur peut accepter.
Lorsque l'utilisateur sélectionne une image, l'IME appelle
commitContent()
et envoie unInputContentInfo
à l'éditeur. L'appelcommitContent()
est analogue à l'appelcommitText()
, mais pour du contenu enrichi.InputContentInfo
contient un URI qui identifie le contenu dans un fournisseur de contenu.
Ce processus est illustré dans la figure 2:
Ajouter la prise en charge des images aux applications
Pour accepter le contenu enrichi provenant des IME, une application doit indiquer aux IME les types de contenu acceptés et spécifier une méthode de rappel à exécuter lors de la réception du contenu.
L'exemple suivant montre comment créer un EditText
qui accepte les images PNG:
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:
Cet exemple utilise la bibliothèque Support. Il existe donc des références à
android.support.v13.view.inputmethod
au lieu deandroid.view.inputmethod
.Cet exemple crée un
EditText
et remplace sa méthodeonCreateInputConnection(EditorInfo)
pour modifierInputConnection
.InputConnection
est le canal de communication entre un IME et l'application qui reçoit son entrée.L'appel
super.onCreateInputConnection()
conserve le comportement intégré (envoi et réception de texte) et vous fait référence àInputConnection
.setContentMimeTypes()
ajoute une liste de types MIME pris en charge àEditorInfo
. Appelezsuper.onCreateInputConnection()
avantsetContentMimeTypes()
.callback
est exécuté chaque fois que l'IME valide du contenu. La méthodeonCommitContent()
comporte une référence àInputContentInfoCompat
, qui contient un URI de contenu.- Demandez et libérez des autorisations si votre application s'exécute sur le niveau d'API 25 ou supérieur et que l'indicateur
INPUT_CONTENT_GRANT_READ_URI_PERMISSION
est défini par l'IME. Sinon, vous avez déjà accès à l'URI du contenu, car il est accordé par l'IME ou parce que le fournisseur de contenu ne limite pas l'accès. Pour en savoir plus, consultez Ajouter la prise en charge d'images aux IME.
- Demandez et libérez des autorisations si votre application s'exécute sur le niveau d'API 25 ou supérieur et que l'indicateur
createWrapper()
encapsule leInputConnection
, leEditorInfo
modifié et le rappel dans un nouveauInputConnection
, puis le renvoie.
Voici les pratiques recommandées:
Les éditeurs qui n'acceptent pas le contenu enrichi n'appellent pas
setContentMimeTypes()
et laissent leurEditorInfo.contentMimeTypes
défini surnull
.Les éditeurs ignorent le contenu si le type MIME spécifié dans
InputContentInfo
ne correspond à aucun des types qu'ils acceptent.Le contenu enrichi n'a pas d'incidence ni d'impact sur la position du curseur de texte. Les éditeurs peuvent ignorer la position du curseur lorsqu'ils manipulent du contenu.
Dans la méthode
OnCommitContentListener.onCommitContent()
de l'éditeur, vous pouvez renvoyertrue
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é, le contenu enrichi est validé immédiatement. Si vous souhaitez autoriser les utilisateurs à modifier ou supprimer du contenu, 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 dans les IME
Les IME qui souhaitent envoyer du contenu enrichi aux applications doivent implémenter l'API Commit Content, comme illustré dans l'exemple suivant:
- Remplacez
onStartInput()
ouonStartInputView()
, puis lisez la liste des types de contenu compatibles à partir de l'éditeur cible. L'extrait de code suivant montre comment vérifier si l'éditeur cible 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. Évitez d'appeler
commitContent()
lorsqu'un texte est en cours de rédaction, car cela pourrait empêcher l'éditeur d'être sélectionné. L'extrait de code suivant montre comment 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 répondre aux requêtes d'URI de contenu. Il existe une exception si votre IME prend en charge le contenu de fournisseurs de contenu existants tels que MediaStore
. Pour en savoir plus sur la création de fournisseurs de contenu, consultez la documentation du fournisseur de contenu et du fournisseur de fichiers.
Si vous créez votre propre fournisseur de contenu, nous vous recommandons de ne pas l'exporter en définissant android:exported
sur false
. À la place, activez l'attribution d'autorisations dans le fournisseur en définissant android:grantUriPermission
sur true
. Votre IME peut ensuite 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 surINPUT_CONTENT_GRANT_READ_URI_PERMISSION
. Ensuite, l'objetInputContentInfo
reçu par l'application peut demander et libérer des autorisations de lecture temporaires en appelantrequestPermission()
etreleasePermission()
.Sur Android 7.0 (niveau d'API 24) et versions antérieures,
INPUT_CONTENT_GRANT_READ_URI_PERMISSION
est ignoré. Vous devez donc accorder manuellement l'autorisation au contenu. Pour ce faire, vous pouvez utilisergrantUriPermission()
, mais vous pouvez implémenter votre propre mécanisme répondant à vos propres besoins.
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 sous Android 7.1 ou version ultérieure.