Nutzer lieben Bilder, Videos und andere ausdrucksstarke Inhalte, aber das Einfügen und Verschieben dieser Inhalte in Apps ist nicht immer einfach. Damit Apps Rich Content einfacher empfangen können, wird mit Android 12 (API-Level 31) eine einheitliche API eingeführt, mit der deine App Inhalte aus beliebigen Quellen akzeptieren kann: Zwischenablage, Tastatur oder Drag-and-drop.
Sie können eine Schnittstelle wie OnReceiveContentListener an UI-Komponenten anhängen und einen Callback erhalten, wenn Inhalte über einen beliebigen Mechanismus eingefügt werden. Der Callback wird zum einzigen Ort, an dem Ihr Code den Empfang aller Inhalte verarbeitet, von einfachem und formatiertem Text bis hin zu Markup, Bildern, Videos, Audiodateien und anderen Inhalten.
Zur Abwärtskompatibilität mit früheren Android-Versionen ist diese API auch in AndroidX ab Core 1.7 und Appcompat 1.4 verfügbar. Wir empfehlen, diese Versionen bei der Implementierung dieser Funktion zu verwenden.
Übersicht
Bei anderen vorhandenen APIs hat jeder UI-Mechanismus, z. B. das Menü „Berühren und halten“ oder das Ziehen, eine eigene entsprechende API. Das bedeutet, dass Sie jede API separat einbinden und für jeden Mechanismus, der Inhalte einfügt, ähnlichen Code hinzufügen müssen:
Die OnReceiveContentListener API konsolidiert diese verschiedenen Codepfade, indem sie eine einzige API zur Implementierung bereitstellt. So können Sie sich auf Ihre App-spezifische Logik konzentrieren und den Rest der Plattform überlassen:
Dieser Ansatz bedeutet auch, dass Sie keine zusätzlichen Codeänderungen vornehmen müssen, um die Unterstützung in Ihrer App zu aktivieren, wenn der Plattform neue Möglichkeiten zum Einfügen von Inhalten hinzugefügt werden. Und wenn Ihre App für einen bestimmten Anwendungsfall vollständig angepasst werden muss, können Sie weiterhin die vorhandenen APIs verwenden, die weiterhin auf dieselbe Weise funktionieren.
Implementierung
Die API ist eine Listener-Schnittstelle mit einer einzigen Methode, OnReceiveContentListener.
Zur Unterstützung älterer Versionen der Android-Plattform empfehlen wir die Verwendung der entsprechenden OnReceiveContentListener-Schnittstelle in der AndroidX Core-Bibliothek.
Wenn du die API verwenden möchtest, musst du den Listener implementieren und angeben, welche Arten von Inhalten deine App verarbeiten kann:
Kotlin
object MyReceiver : OnReceiveContentListener { val MIME_TYPES = arrayOf("image/*", "video/*") // ... override fun onReceiveContent(view: View, payload: ContentInfoCompat): ContentInfoCompat? { TODO("Not yet implemented") } }
Java
public class MyReceiver implements OnReceiveContentListener { public static final String[] MIME_TYPES = new String[] {"image/*", "video/*"}; // ... }
Nachdem du alle von deiner App unterstützten MIME-Typen für Inhalte angegeben hast, implementiere den Rest des Listeners:
Kotlin
class MyReceiver : OnReceiveContentListener { override fun onReceiveContent(view: View, contentInfo: ContentInfoCompat): ContentInfoCompat { val split = contentInfo.partition { item: ClipData.Item -> item.uri != null } val uriContent = split.first val remaining = split.second if (uriContent != null) { // App-specific logic to handle the URI(s) in uriContent. } // Return anything that your app didn't handle. This preserves the // default platform behavior for text and anything else that you aren't // implementing custom handling for. return remaining } companion object { val MIME_TYPES = arrayOf("image/*", "video/*") } }
Java
public class MyReceiver implements OnReceiveContentListener { public static final String[] MIME_TYPES = new String[] {"image/*", "video/*"}; @Override public ContentInfoCompat onReceiveContent(View view, ContentInfoCompat contentInfo) { Pair<ContentInfoCompat, ContentInfoCompat> split = contentInfo.partition( item -> item.getUri() != null); ContentInfo uriContent = split.first; ContentInfo remaining = split.second; if (uriContent != null) { // App-specific logic to handle the URI(s) in uriContent. } // Return anything that your app didn't handle. This preserves the // default platform behavior for text and anything else that you aren't // implementing custom handling for. return remaining; } }
Wenn Ihre App bereits das Teilen mit Intents unterstützt, können Sie Ihre App-spezifische Logik für die Verarbeitung von Inhalts-URIs wiederverwenden. Geben Sie alle verbleibenden Daten zurück, um die Verarbeitung dieser Daten an die Plattform zu delegieren.
Nachdem Sie den Listener implementiert haben, legen Sie ihn für die entsprechenden UI-Elemente in Ihrer App fest:
Kotlin
class MyActivity : Activity() { public override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) // ... val myInput = findViewById(R.id.my_input) ViewCompat.setOnReceiveContentListener(myInput, MyReceiver.MIME_TYPES, MyReceiver()) } }
Java
public class MyActivity extends Activity { @Override public void onCreate(Bundle savedInstanceState) { // ... AppCompatEditText myInput = findViewById(R.id.my_input); ViewCompat.setOnReceiveContentListener(myInput, MyReceiver.MIME_TYPES, new MyReceiver()); } }
URI-Berechtigungen
Leseberechtigungen werden von der Plattform automatisch für alle Inhalts-URIs in der Nutzlast gewährt und freigegeben, die an die OnReceiveContentListener übergeben wird.
Normalerweise verarbeitet Ihre App Inhalts-URIs in einem Dienst oder einer Aktivität. Verwenden Sie für langwierige Verarbeitungen WorkManager. Wenn Sie dies implementieren, erweitern Sie die Berechtigungen auf den Zieldienst oder die Zielaktivität, indem Sie den Inhalt mit Intent.setClipData übergeben und das Flag FLAG_GRANT_READ_URI_PERMISSION festlegen.
Alternativ können Sie einen Hintergrundthread im aktuellen Kontext verwenden, um den Inhalt zu verarbeiten. In diesem Fall müssen Sie einen Verweis auf das vom Listener empfangene payload-Objekt beibehalten, damit die Berechtigungen nicht vorzeitig von der Plattform widerrufen werden.
Benutzerdefinierte Ansichten
Wenn Ihre App eine benutzerdefinierte View-Unterklasse verwendet, achten Sie darauf, dass die OnReceiveContentListener nicht umgangen wird.
Wenn die Methode onCreateInputConnection von der Klasse View überschrieben wird, verwenden Sie die Jetpack API InputConnectionCompat.createWrapper, um die InputConnection zu konfigurieren.
Wenn die Methode onTextContextMenuItem von der Klasse View überschrieben wird, delegieren Sie an „super“, wenn der Menüpunkt R.id.paste oder R.id.pasteAsPlainText ist.
Vergleich mit der Keyboard Image API
Die OnReceiveContentListener API ist die nächste Version der vorhandenen Keyboard Image API. Diese einheitliche API unterstützt die Funktionen der Keyboard Image API sowie einige zusätzliche Funktionen. Die Geräte- und Funktionskompatibilität hängt davon ab, ob Sie die Jetpack-Bibliothek oder die nativen APIs aus dem Android SDK verwenden.
| Aktion oder Funktion | Unterstützt von der Keyboard Image API | Von der einheitlichen API unterstützt |
|---|---|---|
| Über die Tastatur einfügen | Ja (API-Level 13 und höher) | Ja (API-Level 13 und höher) |
| Über das Menü „Berühren und halten“ einfügen | Nein | Ja |
| Per Drag-and-drop einfügen | Nein | Ja (API-Level 24 und höher) |
| Aktion oder Funktion | Unterstützt von der Keyboard Image API | Von der einheitlichen API unterstützt |
|---|---|---|
| Über die Tastatur einfügen | Ja (API-Level 25 und höher) | Ja (Android 12 und höher) |
| Über das Menü „Berühren und halten“ einfügen | Nein | |
| Per Drag-and-drop einfügen | Nein |