Umfassende Inhalte erhalten

Abbildung 1: Die einheitliche API bietet einen zentralen Ort, um eingehende Inhalte unabhängig vom jeweiligen UI-Mechanismus zu verarbeiten, z. B. beim Einfügen über das Menü „Berühren und halten“ oder per Drag-and-drop.

Nutzer mögen Bilder, Videos und andere ausdrucksstarke Inhalte. Das Einfügen und Verschieben dieser Inhalte in Apps ist jedoch nicht immer einfach. In Android 12 (API-Level 31) wird eine einheitliche API eingeführt, mit der Ihre App Inhalte aus beliebigen Quellen – aus der Zwischenablage, über die Tastatur oder durch Ziehen – akzeptieren kann, um Apps das Empfangen von Rich Content zu erleichtern.

Sie können eine Schnittstelle wie OnReceiveContentListener an UI-Komponenten anhängen und einen Callback erhalten, wenn Inhalte mit einem beliebigen Mechanismus eingefügt werden. Der Callback wird der einzige Ort, an dem Ihr Code den Empfang aller Inhalte verarbeitet, von einfachem Text bis hin zu Markup, Bildern, Videos, Audiodateien usw.

Aus Gründen der 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 die Verwendung bei der Implementierung dieser Funktion.

Übersicht

Bei anderen vorhandenen APIs verfügt jeder UI-Mechanismus, z. B. das Menü zum Berühren und Halten oder das Ziehen, über eine eigene entsprechende API. Dies bedeutet, dass Sie die Integration in jede API separat vornehmen müssen und für jeden Mechanismus, der Inhalte einfügt, ähnlichen Code hinzufügen müssen:

Ein Bild, das die verschiedenen zu implementierenden Aktionen und die entsprechende API zeigt
Abbildung 2. Zuvor wurde in Apps für jeden UI-Mechanismus zum Einfügen von Inhalten eine andere API implementiert.

Die OnReceiveContentListener API konsolidiert diese verschiedenen Codepfade, indem sie eine einzige zu implementierende API erstellt. So können Sie sich auf Ihre anwendungsspezifische Logik konzentrieren und der Plattform den Rest überlassen:

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

Dieser Ansatz bedeutet auch, dass du keine zusätzlichen Codeänderungen vornehmen musst, wenn die Plattform neue Möglichkeiten zum Einfügen von Inhalten bietet. Wenn deine App eine vollständige Anpassung für einen bestimmten Anwendungsfall implementieren muss, kannst du weiterhin die vorhandenen APIs verwenden, die weiterhin auf dieselbe Weise funktionieren.

Implementierung

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

Implementieren Sie den Listener zur Verwendung der API. Geben Sie dazu an, welche Inhaltstypen Ihre Anwendung 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 von Ihrer App unterstützten Inhalts-MIME-Typen angegeben haben, 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 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 die Freigabe für Intents bereits unterstützt, können Sie Ihre anwendungsspezifische 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. Für eine Verarbeitung über einen längeren Zeitraum verwenden Sie WorkManager. Erweitern Sie bei der Implementierung 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 im aktuellen Kontext einen Hintergrundthread verwenden, um den Inhalt zu verarbeiten. In diesem Fall müssen Sie einen Verweis auf das payload-Objekt beibehalten, das der Listener empfangen hat, damit Berechtigungen nicht vorzeitig von der Plattform widerrufen werden.

Benutzerdefinierte Ansichten

Wenn Ihre Anwendung eine benutzerdefinierte abgeleitete View-Klasse verwendet, dürfen die OnReceiveContentListener nicht umgangen werden.

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

Wenn Ihre View-Klasse die Methode onTextContextMenuItem überschreibt, delegieren Sie die Funktion für Super, wenn der Menüpunkt R.id.paste oder R.id.pasteAsPlainText lautet.

Vergleich mit der Keyboard Image API

Sie können sich die OnReceiveContentListener API als die nächste Version der vorhandenen Keyboard Image API vorstellen. Diese einheitliche API unterstützt die Funktionalität der Keyboard Image API sowie einige zusätzliche Funktionen. Die Kompatibilität von Geräten und Funktionen hängt davon ab, ob Sie die Jetpack-Bibliothek oder die nativen APIs aus dem Android SDK verwenden.

Tabelle 1 Unterstützte Features und API-Level für Jetpack.
Aktion oder Funktion Unterstützt von der Keyboard Image API Von einheitlicher API unterstützt
Über die Tastatur einfügen Ja (API-Level 13 und höher) Ja (API-Level 13 und höher)
Elemente mithilfe des Menüs „Berühren und halten“ einfügen Nein Ja
Elemente per Drag-and-drop einfügen Nein Ja (API-Level 24 und höher)
Tabelle 2 Unterstützte Funktionen und API-Ebenen für native APIs.
Aktion oder Funktion Unterstützt von der Keyboard Image API Von einheitlicher API unterstützt
Über die Tastatur einfügen Ja (API-Level 25 und höher) Ja (Android 12 und höher)
Elemente mithilfe des Menüs „Berühren und halten“ einfügen Nein
Elemente per Drag-and-drop einfügen Nein