Gli utenti spesso vogliono comunicare utilizzando emoji, adesivi e altri tipi di contenuti multimediali contenuti. Nelle versioni precedenti di Android, le tastiere software, note anche come editor dei metodi di input oppure IME: potrebbe inviare solo emoji Unicode alle app. Per i contenuti avanzati, le app API specifiche per le app che non è stato possibile usare in altre app o soluzioni alternative come invio di immagini tramite una semplice azione di condivisione o negli appunti.
A partire da Android 7.1 (livello API 25), l'SDK per Android include il campo API Content, che fornisce agli IME un metodo universale per inviare immagini e altri contenuto multimediale direttamente in un editor di testo in un'app. L'API è disponibile anche in la v13 Support Library a partire dalla revisione 25.0.0. È consigliabile utilizzare il Centro assistenza Libreria perché contiene metodi helper che semplificano l'implementazione.
Con questa API, puoi creare app di messaggistica che accettano contenuti avanzati da qualsiasi e tastiere che consentono di inviare contenuti multimediali a qualsiasi app. Il Google Tastiera e app come Messaggi di Google Supportano la Commit Content API in Android 7.1, come mostrato nella figura 1.
Questo documento mostra come implementare l'API Commit Content sia negli IME che app.
Come funziona
L'inserimento di immagini con la tastiera richiede la partecipazione dell'IME e dell'app. La nella sequenza seguente viene descritto ogni passaggio del processo di inserimento dell'immagine:
Quando l'utente tocca una
EditText
, l'editor invia un elenco dei tipi di contenuti MIME accettati inEditorInfo.contentMimeTypes
.L'IME legge l'elenco dei tipi supportati e visualizza i contenuti nel software tastiera accettata dall'editor.
Quando l'utente seleziona un'immagine, l'IME chiama
commitContent()
e invia un'emailInputContentInfo
all'editore. La chiamatacommitContent()
è analoga allacommitText()
, ma per contenuti avanzati.InputContentInfo
contiene un URI che identifica i contenuti presenti in un contenuti del cloud privato.
Questo processo è illustrato nella figura 2:
Aggiungi il supporto delle immagini alle app
Per accettare contenuti avanzati dagli IME, un'app deve indicare agli IME di che tipi di contenuti
accetta e specifica un metodo di callback da eseguire alla ricezione di contenuti.
L'esempio seguente mostra come creare un elemento EditText
che accetta PNG
immagini:
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; } };
Di seguito sono riportate ulteriori spiegazioni:
In questo esempio viene utilizzata la libreria di supporto, quindi sono presenti alcuni riferimenti a
android.support.v13.view.inputmethod
anzichéandroid.view.inputmethod
.In questo esempio viene creato un
EditText
e ne esegue l'overrideonCreateInputConnection(EditorInfo)
per modificareInputConnection
.InputConnection
è il canale di comunicazione tra un IME e il che riceve l'input.La chiamata
super.onCreateInputConnection()
conserva il comportamento integrato, ovvero l'invio e la ricezione di testo, e fornisce un riferimento aInputConnection
.setContentMimeTypes()
aggiunge un elenco di tipi MIME supportatiEditorInfo
. Chiamasuper.onCreateInputConnection()
prima del giornosetContentMimeTypes()
.callback
viene eseguito ogni volta che l'IME esegue il commit dei contenuti. Il metodoonCommitContent()
fa riferimento aInputContentInfoCompat
, che contiene un URI dei contenuti.- Richiedi e rilascia le autorizzazioni se la tua app è in esecuzione al livello API 25
o superiore e
INPUT_CONTENT_GRANT_READ_URI_PERMISSION
è impostato dall'IME. In caso contrario, hai già accesso ai contenuti. URI perché è concesso dall'IME o perché il fornitore di contenuti non limita l'accesso. Per ulteriori informazioni, consulta la sezione Aggiungere il supporto delle immagini a: IME.
- Richiedi e rilascia le autorizzazioni se la tua app è in esecuzione al livello API 25
o superiore e
createWrapper()
aggregaInputConnection
,EditorInfo
modificato e il callback in un nuovoInputConnection
e lo restituisce.
Di seguito sono riportate alcune pratiche consigliate:
Gli editor che non supportano i contenuti avanzati non chiamano
setContentMimeTypes()
e lascia impostatoEditorInfo.contentMimeTypes
anull
.Gli editor ignorano i contenuti se il tipo MIME specificato in
InputContentInfo
non corrisponde a nessuno dei tipi accettati.I contenuti avanzati non incidono sulla posizione del testo né sulla posizione del testo il cursore del mouse. Gli editor possono ignorare la posizione del cursore quando lavorano con i contenuti.
Nella sezione
OnCommitContentListener.onCommitContent()
, puoi restituiretrue
in modo asincrono, prima di caricare i contenuti.A differenza del testo, che può essere modificato nell'IME prima del commit, il commit dei contenuti è immediato. Se vuoi consentire agli utenti di modificare o eliminare di implementare direttamente la logica.
Per testare la tua app, assicurati che il dispositivo o l'emulatore abbia una tastiera in grado di inviare contenuti avanzati. Puoi usare la tastiera Google su Android 7.1 o versioni successive.
Aggiungi il supporto delle immagini agli IME
Gli IME che desiderano inviare contenuti avanzati alle app devono implementare l'opzione Contenuti del commit come mostrato nell'esempio seguente:
- Esegui override
onStartInput()
oppureonStartInputView()
e leggere l'elenco dei tipi di contenuti supportati dalla destinazione editor. Il seguente snippet di codice mostra come verificare se il target l'editor di codice accetta immagini 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. } }
- Esegui il commit dei contenuti nell'app quando l'utente seleziona un'immagine. Evita di chiamare
commitContent()
quando viene composto qualsiasi testo, perché potrebbe far perdere lo stato attivo all'editor. Il seguente snippet di codice mostra come per eseguire il commit di un'immagine 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); }
In qualità di autore di IME, molto probabilmente dovrai implementare un tuo fornitore di contenuti per
rispondere alle richieste URI dei contenuti. Fa eccezione il caso in cui l'IME supporta contenuti
di fornitori di contenuti esistenti, come
MediaStore
Per informazioni su
dei fornitori di contenuti, consulta i contenuti
provider e file
del fornitore.
Se stai creando un tuo fornitore di contenuti, ti consigliamo di non esportarlo
impostando
Da android:exported
a
false
. Abilita invece la concessione delle autorizzazioni nel provider impostando
android:grantUriPermission
a true
. Successivamente, l'IME può concedere le autorizzazioni per accedere all'URI dei contenuti quando
il commit dei contenuti. Esistono due metodi per effettuare questa operazione:
Su Android 7.1 (livello API 25) e versioni successive, durante la chiamata a
commitContent()
, imposta il parametro flag suINPUT_CONTENT_GRANT_READ_URI_PERMISSION
Quindi, l'oggettoInputContentInfo
ricevuto dall'app può richiedere e rilascia autorizzazioni di lettura temporanee chiamandorequestPermission()
ereleasePermission()
.Su Android 7.0 (livello API 24) e versioni precedenti,
INPUT_CONTENT_GRANT_READ_URI_PERMISSION
viene ignorato, quindi concedilo manualmente autorizzazione all'accesso ai contenuti. Un modo per farlo ègrantUriPermission()
, ma puoi implementare un tuo meccanismo che che soddisfi le tue esigenze.
Per testare l'IME, assicurati che il dispositivo o l'emulatore disponga di un'app in grado di ricevere contenuti avanzati. Puoi utilizzare l'app Google Messenger in Android 7.1 o versioni successive.