Nutzer möchten oft über Emojis, Sticker und andere Arten von Inhalten kommunizieren. In früheren Android-Versionen konnten über Softtastaturen, auch als Eingabemethoden-Editoren oder IMEs bezeichnet, nur Unicode-Emojis an Apps gesendet werden. Für Rich-Inhalte wurden in den Apps appspezifische APIs erstellt, die nicht in anderen Apps verwendet werden konnten, oder Behelfslösungen wie das Senden von Bildern über eine einfache Freigabeaktion oder die Zwischenablage verwendet.
Ab Android 7.1 (API-Ebene 25) enthält das Android SDK die Commit Content API. Damit können IMEs Bilder und andere Rich Content direkt an einen Texteditor in einer App senden. Die API ist auch in der Supportbibliothek von Version 13 ab Version 25.0.0 verfügbar. Wir empfehlen die Verwendung der Supportbibliothek, da sie Hilfsmethoden enthält, die die Implementierung vereinfachen.
Mit dieser API können Sie Messaging-Apps erstellen, die Rich-Content von jeder Tastatur sowie Tastaturen zulassen, die Rich-Content an jede App senden können. Die Google-Tastatur und Apps wie Messages von Google unterstützen die Commit Content API in Android 7.1 (siehe Abbildung 1).
In diesem Dokument wird beschrieben, wie die Commit Content API sowohl in IMEs als auch in Anwendungen implementiert wird.
So funktionierts
Das Einfügen von Tastaturbildern erfordert eine Beteiligung des IME und der Anwendung. In der folgenden Reihenfolge werden die einzelnen Schritte des Bildeinfügevorgangs beschrieben:
Wenn der Nutzer auf ein
EditText
tippt, sendet der Editor eine Liste von MIME-Inhaltstypen, die inEditorInfo.contentMimeTypes
akzeptiert werden.Der IME liest die Liste der unterstützten Typen und zeigt auf der Softtastatur Inhalte an, die der Editor akzeptieren kann.
Wenn der Nutzer ein Bild auswählt, ruft der IME
commitContent()
auf und sendet einInputContentInfo
-Element an den Editor. DercommitContent()
-Aufruf entspricht demcommitText()
-Aufruf, allerdings für Rich Content.InputContentInfo
enthält einen URI, der den Inhalt eines Contentanbieters identifiziert.
Dieser Prozess wird in Abbildung 2 dargestellt:
Bildunterstützung zu Apps hinzufügen
Um Rich Content von IMEs zu akzeptieren, muss eine App den IMEs mitteilen, welche Inhaltstypen akzeptiert werden, und eine Callback-Methode angeben, die beim Empfang von Inhalten ausgeführt wird.
Das folgende Beispiel zeigt, wie Sie ein EditText
erstellen, das PNG-Bilder akzeptiert:
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; } };
Im Folgenden finden Sie weitere Erläuterungen:
In diesem Beispiel wird die Supportbibliothek verwendet. Daher gibt es einige Verweise auf
android.support.v13.view.inputmethod
anstelle vonandroid.view.inputmethod
.In diesem Beispiel wird ein
EditText
erstellt und seine MethodeonCreateInputConnection(EditorInfo)
überschrieben, um denInputConnection
zu ändern. DerInputConnection
ist der Kommunikationskanal zwischen einem IME und der Anwendung, die ihre Eingabe empfängt.Durch den Aufruf
super.onCreateInputConnection()
wird das integrierte Verhalten beibehalten, d. h. Text wird gesendet und empfangen und es wird aufInputConnection
verwiesen.setContentMimeTypes()
fügt demEditorInfo
eine Liste der unterstützten MIME-Typen hinzu. Rufen Siesuper.onCreateInputConnection()
vor demsetContentMimeTypes()
auf.callback
wird immer dann ausgeführt, wenn der IME einen Commit für Inhalte durchführt. Die MethodeonCommitContent()
verweist aufInputContentInfoCompat
, das einen Inhalts-URI enthält.- Fordern Sie Berechtigungen an und geben Sie Berechtigungen frei, wenn Ihre App auf API-Level 25 oder höher ausgeführt wird und das Flag
INPUT_CONTENT_GRANT_READ_URI_PERMISSION
vom IME festgelegt wird. Andernfalls haben Sie bereits Zugriff auf den Inhalts-URI, da er vom IME gewährt wird oder der Contentanbieter den Zugriff nicht einschränkt. Weitere Informationen finden Sie unter Image-Unterstützung zu IMEIs hinzufügen.
- Fordern Sie Berechtigungen an und geben Sie Berechtigungen frei, wenn Ihre App auf API-Level 25 oder höher ausgeführt wird und das Flag
createWrapper()
fasst dieInputConnection
, die geänderteEditorInfo
und den Callback in eine neueInputConnection
zusammen und gibt sie zurück.
Wir empfehlen folgende Vorgehensweisen:
Editoren, die Rich-Content nicht unterstützen, rufen
setContentMimeTypes()
nicht auf und lassenEditorInfo.contentMimeTypes
aufnull
festgelegt.Bearbeiter ignorieren den Inhalt, wenn der in
InputContentInfo
angegebene MIME-Typ mit keinem der akzeptierten Typen übereinstimmt.Rich Content wirkt sich nicht auf die Position des Textcursors aus und wird auch nicht durch diese beeinflusst. Bearbeiter können die Cursorposition beim Arbeiten mit Inhalten ignorieren.
In der Methode
OnCommitContentListener.onCommitContent()
des Editors können Sietrue
asynchron zurückgeben, noch bevor der Inhalt geladen wird.Im Gegensatz zu Text, der vor dem Commit im IME bearbeitet werden kann, wird bei Rich Content sofort ein Commit durchgeführt. Wenn Sie möchten, dass Nutzer Inhalte bearbeiten oder löschen, implementieren Sie die Logik selbst.
Zum Testen Ihrer App muss Ihr Gerät oder Emulator eine Tastatur haben, die Rich-Content senden kann. Sie können die Google-Tastatur unter Android 7.1 oder höher verwenden.
Image-Unterstützung zu IMEs hinzufügen
IMEs, die Rich Content an Anwendungen senden möchten, müssen die Commit Content API implementieren, wie im folgenden Beispiel gezeigt:
- Überschreiben Sie
onStartInput()
oderonStartInputView()
und lesen Sie die Liste der unterstützten Inhaltstypen aus dem Zieleditor. Das folgende Code-Snippet zeigt, wie geprüft wird, ob der Zieleditor GIF-Bilder akzeptiert.
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. } }
- Sie können Inhalte an die App übergeben, wenn der Nutzer ein Bild auswählt. Rufen Sie
commitContent()
nicht auf, wenn Text geschrieben wird, da der Editor sonst möglicherweise den Fokus verliert. Das folgende Code-Snippet zeigt, wie ein Commit für ein GIF-Bild ausgeführt wird.
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); }
Als IME-Autor müssen Sie wahrscheinlich Ihren eigenen Contentanbieter implementieren, um auf Content-URI-Anfragen zu antworten. Eine Ausnahme gilt, wenn Ihr IME Inhalte vorhandener Contentanbieter wie MediaStore
unterstützt. Informationen zum Erstellen von Contentanbietern finden Sie in der Dokumentation zu Contentanbieter und Dateianbieter.
Wenn Sie einen eigenen Contentanbieter erstellen, wird empfohlen, ihn nicht zu exportieren. Dazu setzen Sie android:exported
auf false
. Aktivieren Sie stattdessen die Gewährung von Berechtigungen beim Anbieter. Setzen Sie dazu android:grantUriPermission
auf true
. Anschließend kann Ihr IME Berechtigungen für den Zugriff auf den Inhalts-URI gewähren, wenn für den Inhalt ein Commit durchgeführt wird. Dafür gibt es zwei Möglichkeiten:
Legen Sie unter Android 7.1 (API-Ebene 25) und höher den Flag-Parameter auf
INPUT_CONTENT_GRANT_READ_URI_PERMISSION
fest, wenn SiecommitContent()
aufrufen. Anschließend kann dasInputContentInfo
-Objekt, das die App empfängt, temporäre Leseberechtigungen anfordern und freigeben, indemrequestPermission()
undreleasePermission()
aufgerufen werden.Unter Android 7.0 (API-Level 24) und niedriger wird
INPUT_CONTENT_GRANT_READ_URI_PERMISSION
ignoriert. Gewähren Sie in diesem Fall manuell die Berechtigung für den Inhalt. Eine Möglichkeit dazu istgrantUriPermission()
. Sie können aber auch einen eigenen Mechanismus implementieren, der Ihre eigenen Anforderungen erfüllt.
Zum Testen des IME muss Ihr Gerät oder Emulator eine App haben, die Rich-Content empfangen kann. Sie können die Google Messenger App unter Android 7.1 oder höher verwenden.