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. Einfügen über das Menü „Berühren und halten“ 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. Damit Apps leichter komplexe Inhalte empfangen können, wird in Android 12 (API-Level 31) eine einheitliche API eingeführt, mit der deine App Inhalte aus beliebigen Quellen annehmen kann: in der Zwischenablage, der Tastatur oder durch Ziehen.

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 zum zentralen Ort, an dem der Code den Empfang aller Inhalte verarbeitet – von Nur-Text und formatiertem Text bis hin zu Markups, Bildern, Videos, Audiodateien und anderen Elementen.

Zum Zweck der Abwärtskompatibilität mit früheren Android-Versionen ist diese API auch in Android X verfügbar, und zwar ab Core 1.7 und Appcompat 1.4. Wir empfehlen Ihnen, diese Funktion 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, das die verschiedenen Aktionen und die entsprechende API zeigt, die implementiert werden soll
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 einzige API für die Implementierung erstellt. So können Sie sich auf Ihre anwendungsspezifische Logik konzentrieren und den Rest der Plattform ü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 Sie bei neuen Möglichkeiten zum Einfügen von Inhalten auf der Plattform keine zusätzlichen Codeänderungen vornehmen müssen, um die Unterstützung in Ihrer App zu ermöglichen. Wenn Ihre App eine vollständige Anpassung für einen bestimmten Anwendungsfall implementieren muss, können Sie weiterhin die vorhandenen APIs verwenden, die weiterhin wie gewohnt funktionieren.

Implementierung

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

Um die API zu verwenden, müssen Sie den Listener implementieren. Geben Sie dazu an, welche Inhaltstypen die 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 Anwendung 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 bereits die Freigabe für Intents unterstützt, können Sie Ihre appspezifische Logik für die Verarbeitung von Inhalts-URIs wiederverwenden. Alle verbleibenden Daten zurückgeben, 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 der 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 erteilt und freigegeben, die an OnReceiveContentListener übergeben werden.

Normalerweise verarbeitet Ihre App Inhalts-URIs in einem Dienst oder einer Aktivität. Für eine Verarbeitung mit langer Ausführungszeit sollten Sie WorkManager verwenden. Wenn Sie dies implementieren, erweitern Sie die Berechtigungen auf den Zieldienst oder die Zielaktivität. Dazu übergeben Sie den Inhalt mit Intent.setClipData und legen das Flag FLAG_GRANT_READ_URI_PERMISSION fest.

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 Berechtigungen nicht vorzeitig von der Plattform widerrufen werden.

Benutzerdefinierte Ansichten

Wenn Ihre Anwendung eine benutzerdefinierte abgeleitete View-Klasse verwendet, achten Sie darauf, dass OnReceiveContentListener nicht umgangen wird.

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

Wenn die Klasse View die Methode onTextContextMenuItem überschreibt, delegieren Sie an Super, wenn der Menüpunkt R.id.paste oder R.id.pasteAsPlainText ist.

Vergleich mit der Keyboard Image API

Sie können sich die OnReceiveContentListener API als nächste Version der vorhandenen Tastatur Image API vorstellen. Diese einheitliche API unterstützt die Funktionalität 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-Level für Jetpack.
Aktion oder Funktion Von der Keyboard Image API unterstützt Von einheitlicher API unterstützt
Über die Tastatur einfügen Ja (API-Level 13 und höher) Ja (API-Level 13 und höher)
Mit „Einfügen“ aus dem Menü „Berühren und 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-Level für native APIs
Aktion oder Funktion Von der Keyboard Image API unterstützt Von einheitlicher API unterstützt
Über die Tastatur einfügen Ja (API-Level 25 und höher) Ja (Android 12 und höher)
Mit „Einfügen“ aus dem Menü „Berühren und halten“ einfügen Nein
Per Drag-and-drop einfügen Nein