Umfassende Inhalte erhalten

Abbildung 1. Die einheitliche API bietet einen zentralen Ort für die Verarbeitung eingehender Inhalte, unabhängig vom jeweiligen UI-Mechanismus, z. B. beim Einfügen über das Kontextmenü oder per Drag-and-drop.

Nutzer lieben Bilder, Videos und andere ausdrucksstarke Inhalte, aber das Einfügen und Verschieben dieser Inhalte in Apps ist nicht immer einfach. Um den Empfang von Rich Content für Apps zu vereinfachen, wird mit Android 12 (API-Level 31) eine einheitliche API eingeführt, mit der Ihre 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 Rückruf erhalten, wenn Inhalte über einen beliebigen Mechanismus eingefügt werden. Der Callback ist der einzige Ort, an dem Ihr Code alle Inhalte empfängt, von einfachem und formatiertem Text bis hin zu Markup, Bildern, Videos, Audiodateien und anderen.

Aus Gründen der Abwärtskompatibilität mit früheren Android-Versionen ist diese API auch in AndroidX verfügbar, beginnend mit Core 1.7 und Appcompat 1.4. Wir empfehlen, diese API 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, mit dem Inhalte eingefügt werden, ähnlichen Code hinzufügen müssen:

Ein Bild mit den verschiedenen Aktionen und der entsprechenden API, die implementiert werden muss
Abbildung 2. Bisher wurde in Apps für jeden UI-Mechanismus zum Einfügen von Inhalten eine andere API implementiert.

Die OnReceiveContentListener API fasst diese verschiedenen Codepfade zusammen, indem sie eine einzelne API für die Implementierung erstellt. So können Sie sich auf Ihre app-spezifische Logik konzentrieren und die Plattform übernimmt den Rest:

Bild der vereinfachten einheitlichen API
Abbildung 3: Mit der einheitlichen API können Sie eine einzelne API implementieren, die alle UI-Mechanismen unterstützt.

Wenn neue Möglichkeiten zum Einfügen von Inhalten auf der Plattform hinzugefügt werden, müssen Sie keine zusätzlichen Codeänderungen vornehmen, um die Unterstützung in Ihrer App zu aktivieren. Wenn Ihre App eine vollständige Anpassung für einen bestimmten Anwendungsfall erfordert, können Sie weiterhin die vorhandenen APIs verwenden, die weiterhin auf dieselbe Weise funktionieren.

Implementierung

Die API ist eine Listener-Schnittstelle mit einer einzelnen Methode: OnReceiveContentListener. Zur Unterstützung älterer Versionen der Android-Plattform empfehlen wir die Verwendung der entsprechenden OnReceiveContentListener-Schnittstelle in der AndroidX Core-Bibliothek.

Wenn Sie die API verwenden möchten, müssen Sie den Listener implementieren und angeben, welche Arten von Inhalten Ihre 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 Sie alle MIME-Typen für Inhalte angegeben haben, die von Ihrer App unterstützt werden, implementieren Sie 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 die Freigabe mit Intents unterstützt, können Sie die 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 OnReceiveContentListener übergeben wird.

Normalerweise verarbeitet Ihre App Inhalts-URIs in einem Dienst oder einer Aktivität. Verwenden Sie für die Verarbeitung mit langer Ausführungszeit WorkManager. Wenn Sie dies implementieren, erweitern Sie die Berechtigungen für den Zieldienst oder die Zielaktivität, indem Sie den Inhalt über Intent.setClipData übergeben und das Flag FLAG_GRANT_READ_URI_PERMISSION festlegen.

Alternativ können Sie einen Hintergrundthread im aktuellen Kontext verwenden, um die Inhalte zu verarbeiten. In diesem Fall müssen Sie eine Referenz auf das vom Listener empfangene payload-Objekt beibehalten, um zu verhindern, dass Berechtigungen von der Plattform vorzeitig widerrufen werden.

Benutzerdefinierte Ansichten

Wenn Ihre App eine benutzerdefinierte View-Unterklasse verwendet, achten Sie darauf, dass OnReceiveContentListener nicht umgangen wird.

Wenn Ihre View-Klasse die Methode onCreateInputConnection überschreibt, verwenden Sie die Jetpack API InputConnectionCompat.createWrapper, um die InputConnection zu konfigurieren.

Wenn Ihre View-Klasse die Methode onTextContextMenuItem überschreibt, delegieren Sie an die Superklasse, wenn das Menüelement 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.

Tabelle 1 Unterstützte Funktionen und API-Levels für Jetpack.
Aktion oder Funktion Von der Keyboard Image API unterstützt Wird 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ü „Gedrückt halten“ einfügen Nein Ja
Per Drag-and-drop einfügen Nein Ja (API-Level 24 und höher)
Tabelle 2 Unterstützte Funktionen und API-Levels für native APIs.
Aktion oder Funktion Von der Keyboard Image API unterstützt Wird 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ü „Gedrückt halten“ einfügen Nein
Per Drag-and-drop einfügen Nein