A menudo, los usuarios quieren comunicarse usando emojis, calcomanías y otros tipos de contenido. En versiones anteriores de Android, los teclados en pantalla, también conocidos como editores de métodos de entrada IME: Solo se podían enviar emojis Unicode a las apps. Para contenido enriquecido, apps creadas APIs específicas de una aplicación que no se podían usar en otras aplicaciones o que usaban soluciones alternativas, como Enviar imágenes mediante una simple acción de compartir o el portapapeles.
A partir de Android 7.1 (nivel de API 25), el SDK de Android incluye Commit Content API, que proporciona una forma universal para que los IME envíen imágenes y otras contenido enriquecido directamente en el editor de texto de una aplicación. La API también está disponible en la biblioteca de compatibilidad v13 a partir de la revisión 25.0.0. Recomendamos usar la página de asistencia porque contiene métodos auxiliares que simplifican la implementación.
Con esta API, puedes compilar apps de mensajería que acepten contenido enriquecido de cualquier además de los que permiten enviar contenido enriquecido a cualquier app. La página Teclado y apps como Messages by Google admitir la API de Commit Content en Android 7.1, como se muestra en la figura 1.
Este documento muestra cómo implementar la API de Commit Content en los IME y de Google Chat.
Cómo funciona
La inserción de imágenes en el teclado requiere la participación del IME y de la app. El En la siguiente secuencia, se describe cada paso del proceso de inserción de imágenes:
Cuando el usuario presiona un
EditText
, el editor envía una lista de los tipos de contenido MIME que acepta enEditorInfo.contentMimeTypes
El IME lee la lista de los tipos compatibles y muestra el contenido en el teclado en pantalla que puede aceptar el editor.
Cuando el usuario selecciona una imagen, el IME llama
commitContent()
y envía unInputContentInfo
al editor. La llamada acommitContent()
es análoga a lacommitText()
, pero para contenido enriquecido.InputContentInfo
contiene un URI que identifica el contenido de un contenido proveedor de servicios en la nube.
Este proceso se muestra en la figura 2:
Cómo agregar compatibilidad con imágenes a las apps
Para aceptar contenido enriquecido de los IME, las apps deben indicarles qué tipo de contenido
acepta y especifica un método de devolución de llamada que se ejecuta cuando se recibe contenido.
En el siguiente ejemplo, se muestra cómo crear un EditText
que acepte PNG
imágenes:
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; } };
A continuación, se incluye una explicación más detallada:
En este ejemplo se usa la biblioteca de compatibilidad, por lo que hay algunas referencias a
android.support.v13.view.inputmethod
en vez deandroid.view.inputmethod
En este ejemplo, se crea un
EditText
y se anula suonCreateInputConnection(EditorInfo)
método para modificar elInputConnection
ElInputConnection
es el canal de comunicación entre un IME y el que recibe la entrada.La llamada
super.onCreateInputConnection()
conserva el comportamiento integrado (enviar y recibir texto) y te da una referencia aInputConnection
.setContentMimeTypes()
agrega una lista de los tipos de MIME admitidos alEditorInfo
Llamadasuper.onCreateInputConnection()
antes delsetContentMimeTypes()
.callback
se ejecuta cada vez que el IME confirma el contenido. El métodoonCommitContent()
tiene una referencia aInputContentInfoCompat
, que incluye un URI de contenido.- Solicita y actualiza permisos si tu app se ejecuta en el nivel de API 25.
o una superior y la
INPUT_CONTENT_GRANT_READ_URI_PERMISSION
del IME. De lo contrario, ya tienes acceso al contenido. porque es un URI otorgado por el IME o porque el proveedor de contenido no restringe el acceso. Para obtener más información, consulta Cómo agregar compatibilidad con imágenes a IME
- Solicita y actualiza permisos si tu app se ejecuta en el nivel de API 25.
o una superior y la
createWrapper()
une elInputConnection
, elEditorInfo
modificado y la devolución de llamada. en un nuevo objetoInputConnection
y lo muestra.
Las siguientes son prácticas recomendadas:
Los editores que no admiten contenido enriquecido no llaman.
setContentMimeTypes()
y dejan suEditorInfo.contentMimeTypes
configurado anull
.Los editores ignoran el contenido si el tipo de MIME especificado en
InputContentInfo
. no coincide con ninguno de los tipos que aceptan.El contenido enriquecido no afecta la posición del texto ni la afecta. cursor. Los editores pueden ignorar la posición del cursor cuando trabajan con contenido.
En la sección del editor
OnCommitContentListener.onCommitContent()
, puedes mostrartrue
de forma asíncrona, incluso antes de cargar el contenido.A diferencia del texto, que puede editarse en el IME antes de confirmarlo, el texto el contenido se confirma de inmediato. Si quieres permitir que los usuarios editen o borren , implementa la lógica por tu cuenta.
Para probar tu app, asegúrate de que tu dispositivo o emulador tengan un teclado que pueda enviar notificaciones. contenido enriquecido. Puedes usar el Teclado de Google en Android 7.1 o versiones posteriores.
Cómo agregar compatibilidad con imágenes a los IME
Los IME que quieran enviar contenido enriquecido a apps deben implementar la opción de contenido de confirmación. como se muestra en el siguiente ejemplo:
- Anular
onStartInput()
oonStartInputView()
y lee la lista de tipos de contenido compatibles del destino. Editor. En el siguiente fragmento de código, se muestra cómo verificar si el editor de destino acepta imágenes 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. } }
- Confirma contenido en la app cuando el usuario seleccione una imagen. Evitar llamadas
commitContent()
cuando se redacta texto, ya que podría hacer que el editor pierda el foco. En el siguiente fragmento de código, se muestra cómo para confirmar una imagen 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); }
Como autor de IME, lo más probable es que tengas que implementar tu propio proveedor de contenido para
a las solicitudes de URI de contenido. La excepción es si tu IME admite contenido
desde proveedores de contenido existentes
MediaStore
Para obtener información sobre
creación de proveedores de contenido, consulta la documentación
Provider y file
del proveedor.
Si estás creando tu propio proveedor de contenido, te recomendamos que no lo exportes.
estableciendo
android:exported
a
false
En su lugar, habilita la concesión de permisos en el proveedor estableciendo
android:grantUriPermission
a true
. Luego, tu IME puede otorgar permisos para acceder al URI de contenido cuando se confirme el contenido. Existen dos maneras de hacerlo:
En Android 7.1 (nivel de API 25) y versiones posteriores, cuando llames a
commitContent()
, haz lo siguiente: establece el parámetro de marca enINPUT_CONTENT_GRANT_READ_URI_PERMISSION
Entonces, el objetoInputContentInfo
que reciba la app podrá solicitar y para liberar permisos de lectura temporales llamandorequestPermission()
yreleasePermission()
En Android 7.0 (nivel de API 24) y versiones anteriores, haz lo siguiente:
INPUT_CONTENT_GRANT_READ_URI_PERMISSION
se ignora, por lo que debes otorgar manualmente permiso al contenido. Una forma de hacer esto es congrantUriPermission()
, pero puedes implementar tu propio mecanismo que cumpla con tus propios requisitos.
Para probar tu IME, asegúrate de que tu dispositivo o emulador tengan una app que pueda recibir contenido enriquecido. Puedes usar la app de Google Messenger en Android 7.1 o versiones posteriores.