Kopieren und einfügen

Android bietet ein leistungsstarkes Framework auf Basis von Zwischenablagen zum Kopieren und Einfügen. Sie unterstützt einfache und komplexe Datentypen wie Textstrings, komplexe Datenstrukturen, Text- und Binärstreamdaten sowie Anwendungs-Assets. Einfache Textdaten werden direkt in der Zwischenablage gespeichert. Komplexe Daten werden als Referenz gespeichert, die durch die Anwendung zum Einfügen mit einem Contentanbieter aufgelöst wird. Das Kopieren und Einfügen funktioniert sowohl innerhalb einer Anwendung als auch zwischen Anwendungen, die das Framework implementieren.

Da ein Teil des Frameworks Contentanbieter verwendet, wird in diesem Dokument davon ausgegangen, dass Sie mit der Android Content Provider API vertraut sind, die unter Contentanbieter beschrieben wird.

Nutzer erwarten beim Kopieren von Inhalten in die Zwischenablage Feedback. Daher zeigt Android Nutzern neben dem Framework, das Kopieren und Einfügen ermöglicht, beim Kopieren in Android 13 (API-Level 33) und höher eine Standard-UI an. Es besteht die Gefahr, dass Benachrichtigungen doppelt gesendet werden. Weitere Informationen zu diesem Grenzfall finden Sie im Abschnitt Doppelte Benachrichtigungen vermeiden.

Eine Animation, die Benachrichtigungen in der Zwischenablage für Android 13 zeigt
Abbildung 1: Benutzeroberfläche, die angezeigt wird, wenn Inhalte unter Android 13 und höher in die Zwischenablage gelangen.

Gib Nutzern beim Kopieren in Android 12L (API-Level 32) und niedriger manuell Feedback. Empfehlungen dazu finden Sie in diesem Dokument.

Das Zwischenablage-Framework

Wenn Sie das Framework der Zwischenablage verwenden, legen Sie Daten in ein Clipobjekt und das Clipobjekt dann in die systemweite Zwischenablage. Das Clip-Objekt kann eine von drei Formen annehmen:

Text
Ein Textstring. Fügen Sie den String direkt in das Clip-Objekt ein, das Sie dann in die Zwischenablage kopieren. Rufen Sie zum Einfügen des Strings das Clip-Objekt aus der Zwischenablage ab und kopieren Sie den String in den Speicher Ihrer Anwendung.
URI
Ein Uri-Objekt, das eine beliebige Form von URI darstellt. Dies dient in erster Linie zum Kopieren komplexer Daten von einem Contentanbieter. Um Daten zu kopieren, platziere ein Uri-Objekt in ein Clipobjekt und das Clipobjekt in die Zwischenablage. Wenn Sie die Daten einfügen möchten, rufen Sie das Clip-Objekt ab, rufen Sie das Uri-Objekt ab, lösen Sie es in einer Datenquelle wie einem Contentanbieter auf und kopieren Sie die Daten aus der Quelle in den Speicher Ihrer Anwendung.
Intent
Ein Intent. Dadurch wird das Kopieren von Anwendungsverknüpfungen unterstützt. Wenn du Daten kopieren möchtest, erstelle ein Intent, füge es in ein Clipobjekt und das Clipobjekt in die Zwischenablage. Rufen Sie zum Einfügen der Daten das Clip-Objekt ab und kopieren Sie dann das Intent-Objekt in den Arbeitsspeicherbereich Ihrer Anwendung.

Die Zwischenablage enthält jeweils nur ein Clipobjekt. Wenn eine Anwendung ein Clipobjekt in der Zwischenablage platziert, wird das vorherige Clipobjekt ausgeblendet.

Wenn Sie Nutzern erlauben möchten, Daten in Ihre Anwendung einzufügen, müssen Sie nicht alle Datentypen verarbeiten. Sie können die Daten in der Zwischenablage prüfen, bevor Sie Nutzern die Option zum Einfügen geben. Neben einem bestimmten Datenformat enthält das Clip-Objekt auch Metadaten, die Aufschluss darüber geben, welche MIME-Typen verfügbar sind. Anhand dieser Metadaten können Sie entscheiden, ob Ihre Anwendung die Daten aus der Zwischenablage verwenden kann. Wenn Sie beispielsweise eine Anwendung haben, die hauptsächlich Text verarbeitet, können Sie Clip-Objekte ignorieren, die einen URI oder Intent enthalten.

Möglicherweise möchten Sie Nutzern auch erlauben, Text unabhängig von der Form der Daten in der Zwischenablage einzufügen. Erzwingen Sie dazu die Daten aus der Zwischenablage in eine Textdarstellung und fügen Sie diesen Text ein. Dies wird im Abschnitt Zwischenablage in Text umwandeln beschrieben.

Klassen der Zwischenablage

In diesem Abschnitt werden die vom Clipboard-Framework verwendeten Klassen beschrieben.

Zwischenablage-Manager

Die Android-Systemzwischenablage wird durch die globale Klasse ClipboardManager dargestellt. Instanziieren Sie diese Klasse nicht direkt. Rufen Sie stattdessen einen Verweis darauf ab, indem Sie getSystemService(CLIPBOARD_SERVICE) aufrufen.

ClipData, ClipData.Item und ClipDescription

Wenn Sie der Zwischenablage Daten hinzufügen möchten, erstellen Sie ein ClipData-Objekt, das eine Beschreibung der Daten und der Daten selbst enthält. Die Zwischenablage enthält jeweils nur ein ClipData. ClipData enthält ein ClipDescription-Objekt und ein oder mehrere ClipData.Item-Objekte.

Ein ClipDescription-Objekt enthält Metadaten zum Clip. Er enthält insbesondere ein Array verfügbarer MIME-Typen für die Daten des Clips. Unter Android 12 (API-Level 31) und höher enthalten die Metadaten außerdem Informationen darüber, ob das Objekt stilisierten Text enthält und über den Texttyp im Objekt. Wenn Sie einen Clip in die Zwischenablage speichern, stehen diese Informationen für Einfügen-Anwendungen zur Verfügung, die prüfen können, ob sie die Clipdaten verarbeiten können.

Ein ClipData.Item-Objekt enthält den Text, den URI oder die Intent-Daten:

Text
Ein CharSequence.
URI
Ein Uri. Sie enthält normalerweise einen Contentanbieter-URI, es ist jedoch jeder URI zulässig. Die Anwendung, die die Daten bereitstellt, legt den URI in der Zwischenablage ab. Anwendungen, die die Daten einfügen möchten, rufen den URI aus der Zwischenablage ab und greifen damit auf den Contentanbieter oder eine andere Datenquelle zu und rufen die Daten ab.
Intent
Ein Intent. Mit diesem Datentyp kannst du eine Anwendungsverknüpfung in die Zwischenablage kopieren. Nutzer können die Verknüpfung dann zur späteren Verwendung in ihre Anwendungen einfügen.

Du kannst einem Clip mehr als ein ClipData.Item-Objekt hinzufügen. So können Nutzer Mehrfachauswahlen als einzelnen Clip kopieren und einfügen. Wenn Sie beispielsweise ein Listen-Widget haben, mit dem der Nutzer mehr als ein Element gleichzeitig auswählen kann, können Sie alle Elemente gleichzeitig in die Zwischenablage kopieren. Dazu erstellst du eine separate ClipData.Item für jedes Listenelement und fügst dann die ClipData.Item-Objekte dem ClipData-Objekt hinzu.

ClipData-Convenience-Methoden

Die ClipData-Klasse bietet statische praktische Methoden zum Erstellen eines ClipData-Objekts mit einem einzelnen ClipData.Item-Objekt und einem einfachen ClipDescription-Objekt:

newPlainText(label, text)
Gibt ein ClipData-Objekt zurück, dessen einzelnes ClipData.Item-Objekt einen Textstring enthält. Das Label des ClipDescription-Objekts ist auf label festgelegt. Der einzelne MIME-Typ in ClipDescription ist MIMETYPE_TEXT_PLAIN.

Mit newPlainText() können Sie einen Clip aus einer Textzeichenfolge erstellen.

newUri(resolver, label, URI)
Gibt ein ClipData-Objekt zurück, dessen einzelnes ClipData.Item-Objekt einen URI enthält. Das Label des ClipDescription-Objekts ist auf label festgelegt. Wenn der URI ein Inhalts-URI ist, also Uri.getScheme() content: zurückgibt, verwendet die Methode das in resolver angegebene Objekt ContentResolver, um die verfügbaren MIME-Typen vom Contentanbieter abzurufen. Anschließend werden sie in ClipDescription gespeichert. Für einen URI, der kein content:-URI ist, legt die Methode den MIME-Typ auf MIMETYPE_TEXT_URILIST fest.

Verwenden Sie newUri(), um einen Clip aus einem URI zu erstellen, insbesondere aus einem content:-URI.

newIntent(label, intent)
Gibt ein ClipData-Objekt zurück, dessen einzelnes ClipData.Item-Objekt einen Intent enthält. Das Label des ClipDescription-Objekts ist auf label festgelegt. Der MIME-Typ ist auf MIMETYPE_TEXT_INTENT festgelegt.

Mit newIntent() kannst du einen Clip aus einem Intent-Objekt erstellen.

Daten aus der Zwischenablage in Text umwandeln

Auch wenn Ihre Anwendung nur Text verarbeitet, können Sie Nicht-Textdaten aus der Zwischenablage kopieren, indem Sie sie mit der Methode ClipData.Item.coerceToText() konvertieren.

Diese Methode wandelt die Daten in ClipData.Item in Text um und gibt eine CharSequence zurück. Der von ClipData.Item.coerceToText() zurückgegebene Wert basiert auf der Form der Daten in ClipData.Item:

Text
Wenn ClipData.Item Text ist, d. h., wenn getText() nicht null ist, gibt coerceToText() den Text zurück.
URI
Wenn ClipData.Item ein URI ist, also getUri() nicht null ist, versucht coerceToText(), ihn als Inhalts-URI zu verwenden.
  • Wenn der URI ein Inhalts-URI ist und der Anbieter einen Textstream zurückgeben kann, gibt coerceToText() einen Textstream zurück.
  • Wenn der URI ein Inhalts-URI ist, der Anbieter aber keinen Textstream anbietet, gibt coerceToText() eine Darstellung des URI zurück. Die Darstellung ist dieselbe, die von Uri.toString() zurückgegeben wird.
  • Wenn der URI kein Inhalts-URI ist, gibt coerceToText() eine Darstellung des URI zurück. Die Darstellung ist dieselbe, die von Uri.toString() zurückgegeben wird.
Intent
Wenn ClipData.Item ein Intent ist, d. h. wenn getIntent() nicht null ist, wandelt coerceToText() ihn in einen Intent-URI um und gibt ihn zurück. Die Darstellung ist dieselbe, die von Intent.toUri(URI_INTENT_SCHEME) zurückgegeben wird.

Das Zwischenablage-Framework ist in Abbildung 2 zusammengefasst. Zum Kopieren von Daten setzt eine Anwendung ein ClipData-Objekt in die globale Zwischenablage ClipboardManager. ClipData enthält ein oder mehrere ClipData.Item-Objekte und ein ClipDescription-Objekt. Zum Einfügen von Daten erhält eine Anwendung die ClipData, ihren MIME-Typ aus ClipDescription und die Daten von ClipData.Item oder von dem Contentanbieter, auf den ClipData.Item verweist.

Bild, das ein Blockdiagramm des Frameworks zum Kopieren und Einfügen zeigt
Abbildung 2: Das Zwischenablage-Framework von Android

In die Zwischenablage kopieren

Um Daten in die Zwischenablage zu kopieren, rufen Sie einen Handle zum globalen ClipboardManager-Objekt ab, erstellen ein ClipData-Objekt und fügen ihm ein ClipDescription sowie ein oder mehrere ClipData.Item-Objekte hinzu. Fügen Sie dann das fertige ClipData-Objekt in das ClipboardManager-Objekt ein. Dies wird im folgenden Verfahren näher beschrieben:

  1. Wenn Sie Daten mithilfe eines Inhalts-URI kopieren, richten Sie einen Contentanbieter ein.
  2. Systemzwischenablage abrufen:

    Kotlin

    when(menuItem.itemId) {
        ...
        R.id.menu_copy -> { // if the user selects copy
            // Gets a handle to the clipboard service.
            val clipboard = getSystemService(Context.CLIPBOARD_SERVICE) as ClipboardManager
        }
    }
    

    Java

    ...
    // If the user selects copy.
    case R.id.menu_copy:
    
    // Gets a handle to the clipboard service.
    ClipboardManager clipboard = (ClipboardManager)
            getSystemService(Context.CLIPBOARD_SERVICE);
    
  3. Kopieren Sie die Daten in ein neues ClipData-Objekt:

    • Für Text

      Kotlin

      // Creates a new text clip to put on the clipboard.
      val clip: ClipData = ClipData.newPlainText("simple text", "Hello, World!")
      

      Java

      // Creates a new text clip to put on the clipboard.
      ClipData clip = ClipData.newPlainText("simple text", "Hello, World!");
      
    • Für einen URI

      Mit diesem Snippet wird ein URI erstellt, indem eine Eintrags-ID im Inhalts-URI für den Anbieter codiert wird. Diese Technik wird im Abschnitt Eine Kennung im URI codieren ausführlicher behandelt.

      Kotlin

      // Creates a Uri using a base Uri and a record ID based on the contact's last
      // name. Declares the base URI string.
      const val CONTACTS = "content://com.example.contacts"
      
      // Declares a path string for URIs, used to copy data.
      const val COPY_PATH = "/copy"
      
      // Declares the Uri to paste to the clipboard.
      val copyUri: Uri = Uri.parse("$CONTACTS$COPY_PATH/$lastName")
      ...
      // Creates a new URI clip object. The system uses the anonymous
      // getContentResolver() object to get MIME types from provider. The clip object's
      // label is "URI", and its data is the Uri previously created.
      val clip: ClipData = ClipData.newUri(contentResolver, "URI", copyUri)
      

      Java

      // Creates a Uri using a base Uri and a record ID based on the contact's last
      // name. Declares the base URI string.
      private static final String CONTACTS = "content://com.example.contacts";
      
      // Declares a path string for URIs, used to copy data.
      private static final String COPY_PATH = "/copy";
      
      // Declares the Uri to paste to the clipboard.
      Uri copyUri = Uri.parse(CONTACTS + COPY_PATH + "/" + lastName);
      ...
      // Creates a new URI clip object. The system uses the anonymous
      // getContentResolver() object to get MIME types from provider. The clip object's
      // label is "URI", and its data is the Uri previously created.
      ClipData clip = ClipData.newUri(getContentResolver(), "URI", copyUri);
      
    • Für einen Intent

      Mit diesem Snippet wird ein Intent für eine Anwendung erstellt und dann im Clip-Objekt eingefügt:

      Kotlin

      // Creates the Intent.
      val appIntent = Intent(this, com.example.demo.myapplication::class.java)
      ...
      // Creates a clip object with the Intent in it. Its label is "Intent"
      // and its data is the Intent object created previously.
      val clip: ClipData = ClipData.newIntent("Intent", appIntent)
      

      Java

      // Creates the Intent.
      Intent appIntent = new Intent(this, com.example.demo.myapplication.class);
      ...
      // Creates a clip object with the Intent in it. Its label is "Intent"
      // and its data is the Intent object created previously.
      ClipData clip = ClipData.newIntent("Intent", appIntent);
      
  4. Lege das neue Clipobjekt in die Zwischenablage:

    Kotlin

    // Set the clipboard's primary clip.
    clipboard.setPrimaryClip(clip)
    

    Java

    // Set the clipboard's primary clip.
    clipboard.setPrimaryClip(clip);
    

Beim Kopieren in die Zwischenablage Feedback geben

Nutzer erwarten visuelles Feedback, wenn eine App Inhalte in die Zwischenablage kopiert. Bei Nutzern mit Android 13 und höher erfolgt dies automatisch. In früheren Versionen muss die Implementierung jedoch manuell erfolgen.

Ab Android 13 zeigt das System eine standardmäßige visuelle Bestätigung an, wenn Inhalte der Zwischenablage hinzugefügt werden. Die neue Bestätigung führt folgende Schritte aus:

  • Dadurch wird bestätigt, dass der Inhalt kopiert wurde.
  • Stellt eine Vorschau des kopierten Inhalts bereit.

Eine Animation, die Benachrichtigungen in der Zwischenablage für Android 13 zeigt
Abbildung 3: Benutzeroberfläche, die angezeigt wird, wenn Inhalte unter Android 13 und höher in die Zwischenablage gelangen.

Unter Android 12L (API-Level 32) und niedriger sind Nutzer möglicherweise nicht sicher, ob sie Inhalte erfolgreich kopiert haben. Diese Funktion standardisiert die verschiedenen Benachrichtigungen, die von Apps nach dem Kopieren angezeigt werden, und bietet Nutzern mehr Kontrolle über die Zwischenablage.

Doppelte Benachrichtigungen vermeiden

Unter Android 12L (API-Level 32) und niedriger empfehlen wir, Nutzer zu benachrichtigen, wenn sie den Inhalt erfolgreich kopieren. Hierzu können sie nach dem Kopieren visuelles Feedback in der App mit einem Widget wie Toast oder Snackbar senden.

Damit keine Informationen doppelt angezeigt werden, empfehlen wir dringend, bei Android 13 und höher Toasts oder Snackbars zu entfernen, die nach einem In-App-Text angezeigt werden.

Snackbar nach dem In-App-Text posten.
Abbildung 4: Wenn unter Android 13 eine Snackbar für die Kopierbestätigung angezeigt wird, werden dem Nutzer doppelte Nachrichten angezeigt.
Toast nach einem In-App-Text posten.
Abbildung 5. Wenn unter Android 13 ein Toast zur Bestätigung der Kopie angezeigt wird, werden dem Nutzer doppelte Nachrichten angezeigt.

Hier ist ein Beispiel für die Implementierung:

fun textCopyThenPost(textCopied:String) {
    val clipboardManager = getSystemService(CLIPBOARD_SERVICE) as ClipboardManager
    // When setting the clipboard text.
    clipboardManager.setPrimaryClip(ClipData.newPlainText   ("", textCopied))
    // Only show a toast for Android 12 and lower.
    if (Build.VERSION.SDK_INT <= Build.VERSION_CODES.S_V2)
        Toast.makeText(context, “Copied”, Toast.LENGTH_SHORT).show()
}

Sensible Inhalte in die Zwischenablage einfügen

Wenn Nutzer in Ihrer Anwendung vertrauliche Inhalte wie Passwörter oder Kreditkartendaten in die Zwischenablage kopieren können, müssen Sie ClipDescription in ClipData ein Flag hinzufügen, bevor Sie ClipboardManager.setPrimaryClip() aufrufen. Durch dieses Flag wird verhindert, dass unter Android 13 und höher sensible Inhalte in der visuellen Bestätigung von kopierten Inhalten angezeigt werden.

Textvorschau kopiert, ohne sensible Inhalte zu kennzeichnen
Abbildung 6. Textvorschau ohne Markierung für sensible Inhalte kopiert.
Textvorschau mit Meldung sensibler Inhalte kopiert.
Abbildung 7. Textvorschau mit Markierung für sensible Inhalte kopiert.

Um sensible Inhalte zu kennzeichnen, fügen Sie ClipDescription einen booleschen Extrapunkt hinzu. Dies gilt für alle Apps, unabhängig vom Ziel-API-Level.

// If your app is compiled with the API level 33 SDK or higher.
clipData.apply {
    description.extras = PersistableBundle().apply {
        putBoolean(ClipDescription.EXTRA_IS_SENSITIVE, true)
    }
}

// If your app is compiled with a lower SDK.
clipData.apply {
    description.extras = PersistableBundle().apply {
        putBoolean("android.content.extra.IS_SENSITIVE", true)
    }
}

Aus der Zwischenablage einfügen

Wie bereits beschrieben, können Sie Daten aus der Zwischenablage einfügen, indem Sie das globale Zwischenablage-Objekt abrufen, das Clip-Objekt abrufen, seine Daten ansehen und die Daten nach Möglichkeit vom Clip-Objekt in Ihren eigenen Speicher kopieren. In diesem Abschnitt wird ausführlich erläutert, wie Sie die drei Formen von Daten aus der Zwischenablage einfügen.

Nur Text einfügen

Um Nur-Text einzufügen, rufen Sie die globale Zwischenablage ab und überprüfen Sie, ob Text zurückgegeben werden kann. Rufen Sie dann das Clip-Objekt ab und kopieren Sie seinen Text mithilfe von getText() in Ihren eigenen Speicher. Gehen Sie dazu so vor:

  1. Rufen Sie das globale ClipboardManager-Objekt mit getSystemService(CLIPBOARD_SERVICE) ab. Deklarieren Sie außerdem eine globale Variable, die den eingefügten Text enthalten soll:

    Kotlin

    var clipboard = getSystemService(Context.CLIPBOARD_SERVICE) as ClipboardManager
    var pasteData: String = ""
    

    Java

    ClipboardManager clipboard = (ClipboardManager) getSystemService(Context.CLIPBOARD_SERVICE);
    String pasteData = "";
    
  2. Ermitteln Sie, ob Sie die Option „Einfügen“ in der aktuellen Aktivität aktivieren oder deaktivieren müssen. Prüfen Sie, ob die Zwischenablage einen Clip enthält und ob Sie den Datentyp verarbeiten können, der durch den Clip dargestellt wird:

    Kotlin

    // Gets the ID of the "paste" menu item.
    val pasteItem: MenuItem = menu.findItem(R.id.menu_paste)
    
    // If the clipboard doesn't contain data, disable the paste menu item.
    // If it does contain data, decide whether you can handle the data.
    pasteItem.isEnabled = when {
        !clipboard.hasPrimaryClip() -> {
            false
        }
        !(clipboard.primaryClipDescription.hasMimeType(MIMETYPE_TEXT_PLAIN)) -> {
            // Disables the paste menu item, since the clipboard has data but it
            // isn't plain text.
            false
        }
        else -> {
            // Enables the paste menu item, since the clipboard contains plain text.
            true
        }
    }
    

    Java

    // Gets the ID of the "paste" menu item.
    MenuItem pasteItem = menu.findItem(R.id.menu_paste);
    
    // If the clipboard doesn't contain data, disable the paste menu item.
    // If it does contain data, decide whether you can handle the data.
    if (!(clipboard.hasPrimaryClip())) {
    
        pasteItem.setEnabled(false);
    
    } else if (!(clipboard.getPrimaryClipDescription().hasMimeType(MIMETYPE_TEXT_PLAIN))) {
    
        // Disables the paste menu item, since the clipboard has data but
        // it isn't plain text.
        pasteItem.setEnabled(false);
    } else {
    
        // Enables the paste menu item, since the clipboard contains plain text.
        pasteItem.setEnabled(true);
    }
    
  3. Kopieren Sie die Daten aus der Zwischenablage. Dieser Punkt im Code ist nur erreichbar, wenn der Menüpunkt „Einfügen“ aktiviert ist. Daher können Sie davon ausgehen, dass die Zwischenablage reinen Text enthält. Sie wissen noch nicht, ob sie eine Textzeichenfolge oder einen URI enthält, die bzw. der auf Nur-Text verweist. Das folgende Code-Snippet testet dies, zeigt aber nur den Code für die Verarbeitung von Nur-Text an:

    Kotlin

    when (menuItem.itemId) {
        ...
        R.id.menu_paste -> {    // Responds to the user selecting "paste".
            // Examines the item on the clipboard. If getText() doesn't return null,
            // the clip item contains the text. Assumes that this application can only
            // handle one item at a time.
            val item = clipboard.primaryClip.getItemAt(0)
    
            // Gets the clipboard as text.
            pasteData = item.text
    
            return if (pasteData != null) {
                // If the string contains data, then the paste operation is done.
                true
            } else {
                // The clipboard doesn't contain text. If it contains a URI,
                // attempts to get data from it.
                val pasteUri: Uri? = item.uri
    
                if (pasteUri != null) {
                    // If the URI contains something, try to get text from it.
    
                    // Calls a routine to resolve the URI and get data from it.
                    // This routine isn't presented here.
                    pasteData = resolveUri(pasteUri)
                    true
                } else {
    
                    // Something is wrong. The MIME type was plain text, but the
                    // clipboard doesn't contain text or a Uri. Report an error.
                    Log.e(TAG,"Clipboard contains an invalid data type")
                    false
                }
            }
        }
    }
    

    Java

    // Responds to the user selecting "paste".
    case R.id.menu_paste:
    
    // Examines the item on the clipboard. If getText() does not return null,
    // the clip item contains the text. Assumes that this application can only
    // handle one item at a time.
     ClipData.Item item = clipboard.getPrimaryClip().getItemAt(0);
    
    // Gets the clipboard as text.
    pasteData = item.getText();
    
    // If the string contains data, then the paste operation is done.
    if (pasteData != null) {
        return true;
    
    // The clipboard doesn't contain text. If it contains a URI, attempts to get
    // data from it.
    } else {
        Uri pasteUri = item.getUri();
    
        // If the URI contains something, try to get text from it.
        if (pasteUri != null) {
    
            // Calls a routine to resolve the URI and get data from it.
            // This routine isn't presented here.
            pasteData = resolveUri(Uri);
            return true;
        } else {
    
            // Something is wrong. The MIME type is plain text, but the
            // clipboard doesn't contain text or a Uri. Report an error.
            Log.e(TAG, "Clipboard contains an invalid data type");
            return false;
        }
    }
    

Daten aus einem Inhalts-URI einfügen

Wenn das Objekt ClipData.Item einen Inhalts-URI enthält und Sie feststellen, dass Sie einen seiner MIME-Typen verarbeiten können, erstellen Sie ein ContentResolver und rufen Sie die entsprechende Contentanbietermethode auf, um die Daten abzurufen.

Im Folgenden wird beschrieben, wie Sie Daten von einem Contentanbieter anhand eines Inhalts-URI in der Zwischenablage abrufen. Er prüft, ob ein MIME-Typ, den die Anwendung verwenden kann, beim Anbieter verfügbar ist.

  1. Deklarieren Sie eine globale Variable, die den MIME-Typ enthalten soll:

    Kotlin

    // Declares a MIME type constant to match against the MIME types offered
    // by the provider.
    const val MIME_TYPE_CONTACT = "vnd.android.cursor.item/vnd.example.contact"
    

    Java

    // Declares a MIME type constant to match against the MIME types offered by
    // the provider.
    public static final String MIME_TYPE_CONTACT = "vnd.android.cursor.item/vnd.example.contact";
    
  2. Globale Zwischenablage abrufen Rufen Sie auch einen Content-Resolver auf, damit Sie auf den Contentanbieter zugreifen können:

    Kotlin

    // Gets a handle to the Clipboard Manager.
    val clipboard = getSystemService(Context.CLIPBOARD_SERVICE) as ClipboardManager
    
    // Gets a content resolver instance.
    val cr = contentResolver
    

    Java

    // Gets a handle to the Clipboard Manager.
    ClipboardManager clipboard = (ClipboardManager) getSystemService(Context.CLIPBOARD_SERVICE);
    
    // Gets a content resolver instance.
    ContentResolver cr = getContentResolver();
    
  3. Rufen Sie den primären Clip aus der Zwischenablage ab und rufen Sie seinen Inhalt als URI ab:

    Kotlin

    // Gets the clipboard data from the clipboard.
    val clip: ClipData? = clipboard.primaryClip
    
    clip?.run {
    
        // Gets the first item from the clipboard data.
        val item: ClipData.Item = getItemAt(0)
    
        // Tries to get the item's contents as a URI.
        val pasteUri: Uri? = item.uri
    

    Java

    // Gets the clipboard data from the clipboard.
    ClipData clip = clipboard.getPrimaryClip();
    
    if (clip != null) {
    
        // Gets the first item from the clipboard data.
        ClipData.Item item = clip.getItemAt(0);
    
        // Tries to get the item's contents as a URI.
        Uri pasteUri = item.getUri();
    
  4. Durch Aufrufen von getType(Uri) können Sie testen, ob der URI ein Inhalts-URI ist. Diese Methode gibt null zurück, wenn Uri nicht auf einen gültigen Contentanbieter verweist.

    Kotlin

        // If the clipboard contains a URI reference...
        pasteUri?.let {
    
            // ...is this a content URI?
            val uriMimeType: String? = cr.getType(it)
    

    Java

        // If the clipboard contains a URI reference...
        if (pasteUri != null) {
    
            // ...is this a content URI?
            String uriMimeType = cr.getType(pasteUri);
    
  5. Testen, ob der Contentanbieter einen MIME-Typ unterstützt, den die Anwendung versteht. Ist dies der Fall, rufen Sie ContentResolver.query() auf, um die Daten abzurufen. Der Rückgabewert ist Cursor.

    Kotlin

            // If the return value isn't null, the Uri is a content Uri.
            uriMimeType?.takeIf {
    
                // Does the content provider offer a MIME type that the current
                // application can use?
                it == MIME_TYPE_CONTACT
            }?.apply {
    
                // Get the data from the content provider.
                cr.query(pasteUri, null, null, null, null)?.use { pasteCursor ->
    
                    // If the Cursor contains data, move to the first record.
                    if (pasteCursor.moveToFirst()) {
    
                        // Get the data from the Cursor here.
                        // The code varies according to the format of the data model.
                    }
    
                    // Kotlin `use` automatically closes the Cursor.
                }
            }
        }
    }
    

    Java

            // If the return value isn't null, the Uri is a content Uri.
            if (uriMimeType != null) {
    
                // Does the content provider offer a MIME type that the current
                // application can use?
                if (uriMimeType.equals(MIME_TYPE_CONTACT)) {
    
                    // Get the data from the content provider.
                    Cursor pasteCursor = cr.query(uri, null, null, null, null);
    
                    // If the Cursor contains data, move to the first record.
                    if (pasteCursor != null) {
                        if (pasteCursor.moveToFirst()) {
    
                        // Get the data from the Cursor here.
                        // The code varies according to the format of the data model.
                        }
                    }
    
                    // Close the Cursor.
                    pasteCursor.close();
                 }
             }
         }
    }
    

Intent einfügen

Rufen Sie die globale Zwischenablage ab, um einen Intent einzufügen. Sehen Sie sich das Objekt ClipData.Item an. Es enthält ein Intent-Objekt. Rufen Sie dann getIntent() auf, um den Intent in Ihren eigenen Speicher zu kopieren. Das folgende Snippet veranschaulicht dies:

Kotlin

// Gets a handle to the Clipboard Manager.
val clipboard = getSystemService(Context.CLIPBOARD_SERVICE) as ClipboardManager

// Checks whether the clip item contains an Intent by testing whether
// getIntent() returns null.
val pasteIntent: Intent? = clipboard.primaryClip?.getItemAt(0)?.intent

if (pasteIntent != null) {

    // Handle the Intent.

} else {

    // Ignore the clipboard, or issue an error if
    // you expect an Intent to be on the clipboard.
}

Java

// Gets a handle to the Clipboard Manager.
ClipboardManager clipboard = (ClipboardManager) getSystemService(Context.CLIPBOARD_SERVICE);

// Checks whether the clip item contains an Intent, by testing whether
// getIntent() returns null.
Intent pasteIntent = clipboard.getPrimaryClip().getItemAt(0).getIntent();

if (pasteIntent != null) {

    // Handle the Intent.

} else {

    // Ignore the clipboard, or issue an error if
    // you expect an Intent to be on the clipboard.
}

Systembenachrichtigung, die angezeigt wird, wenn deine App auf Daten in der Zwischenablage zugreift

Unter Android 12 (API-Level 31) und höher zeigt das System normalerweise eine Toast-Nachricht an, wenn deine App getPrimaryClip() aufruft. Der Text in der Nachricht hat das folgende Format:

APP pasted from your clipboard

Das System zeigt keine Toast-Meldung an, wenn in Ihrer App eine der folgenden Aktionen ausgeführt wird:

  • Greift über Ihre eigene Anwendung auf ClipData zu.
  • Ruft wiederholt ClipData von einer bestimmten App aus auf. Der Toast wird nur angezeigt, wenn die App zum ersten Mal auf die Daten von dieser App zugreift.
  • Ruft Metadaten für das Clipobjekt ab, z. B. durch Aufrufen von getPrimaryClipDescription() anstelle von getPrimaryClip().

Contentanbieter verwenden, um komplexe Daten zu kopieren

Contentanbieter unterstützen das Kopieren komplexer Daten wie Datenbankeinträge oder Dateistreams. Fügen Sie zum Kopieren der Daten einen Inhalts-URI in die Zwischenablage ein. Beim Einfügen von Anwendungen wird dieser URI aus der Zwischenablage abgerufen und zum Abrufen von Datenbankdaten oder Dateistreamdeskriptoren verwendet.

Da die Paste zum Einfügen nur den Inhalts-URI für Ihre Daten enthält, muss sie wissen, welche Daten abgerufen werden sollen. Sie können diese Informationen angeben, indem Sie eine Kennung für die Daten im URI selbst codieren oder einen eindeutigen URI angeben, der die zu kopierenden Daten zurückgibt. Welche Methode Sie wählen, hängt von der Organisation Ihrer Daten ab.

In den folgenden Abschnitten wird beschrieben, wie Sie URIs einrichten sowie komplexe Daten und Dateistreams bereitstellen. Bei den Beschreibungen wird davon ausgegangen, dass Sie mit den allgemeinen Grundsätzen für das Design von Contentanbietern vertraut sind.

Kennung im URI codieren

Eine nützliche Technik zum Kopieren von Daten in die Zwischenablage mit einem URI besteht darin, eine Kennung für die Daten im URI selbst zu codieren. Der Contentanbieter kann die ID dann aus dem URI abrufen und damit die Daten abrufen. Die Einfügeanwendung muss nicht wissen, dass die Kennung existiert. Sie müssen nur Ihre „Referenz“ – den URI und die ID – aus der Zwischenablage abrufen, Ihrem Contentanbieter übergeben und die Daten zurückerhalten.

Normalerweise codieren Sie eine Kennung in einem Inhalts-URI, indem Sie sie am Ende des URI verketten. Angenommen, Sie definieren den Anbieter-URI als folgenden String:

"content://com.example.contacts"

Wenn Sie einen Namen für diesen URI codieren möchten, verwenden Sie das folgende Code-Snippet:

Kotlin

val uriString = "content://com.example.contacts/Smith"

// uriString now contains content://com.example.contacts/Smith.

// Generates a uri object from the string representation.
val copyUri = Uri.parse(uriString)

Java

String uriString = "content://com.example.contacts" + "/" + "Smith";

// uriString now contains content://com.example.contacts/Smith.

// Generates a uri object from the string representation.
Uri copyUri = Uri.parse(uriString);

Wenn Sie bereits einen Contentanbieter verwenden, können Sie einen neuen URI-Pfad hinzufügen, der angibt, dass der URI kopiert werden soll. Angenommen, Sie haben bereits die folgenden URI-Pfade:

"content://com.example.contacts/people"
"content://com.example.contacts/people/detail"
"content://com.example.contacts/people/images"

Sie können einen weiteren Pfad zum Kopieren von URIs hinzufügen:

"content://com.example.contacts/copying"

Sie können dann einen Kopier-URI durch einen Musterabgleich erkennen und mit Code verarbeiten, der für das Kopieren und Einfügen spezifisch ist.

Normalerweise verwenden Sie die Codierungstechnik, wenn Sie Ihre Daten bereits mit einem Contentanbieter, einer internen Datenbank oder einer internen Tabelle organisieren. In diesen Fällen müssen mehrere Daten kopiert werden, wobei vermutlich jedes Datenelement eine eindeutige Kennung hat. Als Antwort auf eine Abfrage aus der eingefügten Anwendung können Sie die Daten anhand ihrer ID abrufen und zurückgeben.

Wenn Sie nicht mehrere Daten haben, müssen Sie wahrscheinlich keine Kennung codieren. Sie können einen eindeutigen URI für Ihren Anbieter verwenden. Auf eine Abfrage gibt Ihr Anbieter die derzeit enthaltenen Daten zurück.

Datenstrukturen kopieren

Richten Sie einen Contentanbieter zum Kopieren und Einfügen komplexer Daten als abgeleitete Klasse der ContentProvider-Komponente ein. Codieren Sie den URI, den Sie in die Zwischenablage einfügen, so, dass er auf den genauen Eintrag verweist, den Sie angeben möchten. Prüfen Sie außerdem den aktuellen Status Ihrer Anwendung:

  • Wenn Sie bereits einen Contentanbieter haben, können Sie dessen Funktionen ergänzen. Möglicherweise müssen Sie nur die Methode query() ändern, um URIs von Anwendungen zu verarbeiten, in die Daten eingefügt werden sollen. Sie sollten die Methode so ändern, dass ein „Kopie“-URI-Muster verarbeitet wird.
  • Wenn Ihre Anwendung eine interne Datenbank verwaltet, sollten Sie diese Datenbank zu einem Contentanbieter verschieben, um das Kopieren daraus zu erleichtern.
  • Wenn Sie keine Datenbank verwenden, können Sie einen einfachen Contentanbieter implementieren, der nur den Anwendungen Daten zur Verfügung stellt, die aus der Zwischenablage eingefügt werden.

Überschreiben Sie beim Contentanbieter mindestens die folgenden Methoden:

query()
Beim Einfügen wird davon ausgegangen, dass die Anwendungen mit dieser Methode und dem URI, den Sie in die Zwischenablage eingetragen haben, Ihre Daten abrufen können. Damit das Kopieren unterstützt wird, sollten Sie mit dieser Methode URIs erkennen, die einen speziellen Kopierpfad enthalten. Ihre Anwendung kann dann einen Kopier-URI erstellen, der in die Zwischenablage eingefügt wird, der den Kopierpfad und einen Zeiger auf den genauen Eintrag enthält, den Sie kopieren möchten.
getType()
Diese Methode muss die MIME-Typen für die Daten zurückgeben, die Sie kopieren möchten. Die Methode newUri() ruft getType() auf, um die MIME-Typen in das neue ClipData-Objekt aufzunehmen.

MIME-Typen für komplexe Daten werden unter Contentanbieter beschrieben.

Andere Contentanbieter-Methoden wie insert() oder update() sind nicht erforderlich. Eine Anwendung zum Einfügen benötigt nur die unterstützten MIME-Typen und kopiert Daten von Ihrem Anbieter. Wenn Sie diese Methoden bereits haben, beeinträchtigen sie nicht die Kopiervorgänge.

Die folgenden Snippets veranschaulichen, wie Sie Ihre Anwendung zum Kopieren komplexer Daten einrichten:

  1. Deklarieren Sie in den globalen Konstanten für Ihre Anwendung einen Basis-URI-String und einen Pfad, der URI-Strings identifiziert, die Sie zum Kopieren von Daten verwenden. Deklarieren Sie außerdem einen MIME-Typ für die kopierten Daten.

    Kotlin

    // Declares the base URI string.
    private const val CONTACTS = "content://com.example.contacts"
    
    // Declares a path string for URIs that you use to copy data.
    private const val COPY_PATH = "/copy"
    
    // Declares a MIME type for the copied data.
    const val MIME_TYPE_CONTACT = "vnd.android.cursor.item/vnd.example.contact"
    

    Java

    // Declares the base URI string.
    private static final String CONTACTS = "content://com.example.contacts";
    
    // Declares a path string for URIs that you use to copy data.
    private static final String COPY_PATH = "/copy";
    
    // Declares a MIME type for the copied data.
    public static final String MIME_TYPE_CONTACT = "vnd.android.cursor.item/vnd.example.contact";
    
  2. Richten Sie in der Aktivität, aus der Nutzer Daten kopieren, den Code zum Kopieren von Daten in die Zwischenablage ein. Legen Sie als Antwort auf eine Kopieranfrage den URI in die Zwischenablage ab.

    Kotlin

    class MyCopyActivity : Activity() {
        ...
    when(item.itemId) {
        R.id.menu_copy -> { // The user has selected a name and is requesting a copy.
            // Appends the last name to the base URI.
            // The name is stored in "lastName".
            uriString = "$CONTACTS$COPY_PATH/$lastName"
    
            // Parses the string into a URI.
            val copyUri: Uri? = Uri.parse(uriString)
    
            // Gets a handle to the clipboard service.
            val clipboard = getSystemService(Context.CLIPBOARD_SERVICE) as ClipboardManager
    
            val clip: ClipData = ClipData.newUri(contentResolver, "URI", copyUri)
    
            // Sets the clipboard's primary clip.
            clipboard.setPrimaryClip(clip)
        }
    }
    

    Java

    public class MyCopyActivity extends Activity {
        ...
    // The user has selected a name and is requesting a copy.
    case R.id.menu_copy:
    
        // Appends the last name to the base URI.
        // The name is stored in "lastName".
        uriString = CONTACTS + COPY_PATH + "/" + lastName;
    
        // Parses the string into a URI.
        Uri copyUri = Uri.parse(uriString);
    
        // Gets a handle to the clipboard service.
        ClipboardManager clipboard = (ClipboardManager)
            getSystemService(Context.CLIPBOARD_SERVICE);
    
        ClipData clip = ClipData.newUri(getContentResolver(), "URI", copyUri);
    
        // Sets the clipboard's primary clip.
        clipboard.setPrimaryClip(clip);
    
  3. Erstellen Sie im globalen Bereich Ihres Contentanbieters einen URI-Matcher und fügen Sie ein URI-Muster hinzu, das mit den URIs übereinstimmt, die Sie in der Zwischenablage gespeichert haben.

    Kotlin

    // A Uri Match object that simplifies matching content URIs to patterns.
    private val sUriMatcher = UriMatcher(UriMatcher.NO_MATCH).apply {
    
        // Adds a matcher for the content URI. It matches.
        // "content://com.example.contacts/copy/*"
        addURI(CONTACTS, "names/*", GET_SINGLE_CONTACT)
    }
    
    // An integer to use in switching based on the incoming URI pattern.
    private const val GET_SINGLE_CONTACT = 0
    ...
    class MyCopyProvider : ContentProvider() {
        ...
    }
    

    Java

    public class MyCopyProvider extends ContentProvider {
        ...
    // A Uri Match object that simplifies matching content URIs to patterns.
    private static final UriMatcher sURIMatcher = new UriMatcher(UriMatcher.NO_MATCH);
    
    // An integer to use in switching based on the incoming URI pattern.
    private static final int GET_SINGLE_CONTACT = 0;
    ...
    // Adds a matcher for the content URI. It matches
    // "content://com.example.contacts/copy/*"
    sUriMatcher.addURI(CONTACTS, "names/*", GET_SINGLE_CONTACT);
    
  4. Richten Sie die Methode query() ein. Diese Methode kann je nach Codierung unterschiedliche URI-Muster verarbeiten. Es wird jedoch nur das Muster für den Kopiervorgang in der Zwischenablage angezeigt.

    Kotlin

    // Sets up your provider's query() method.
    override fun query(
            uri: Uri,
            projection: Array<out String>?,
            selection: String?,
            selectionArgs: Array<out String>?,
            sortOrder: String?
    ): Cursor? {
        ...
        // When based on the incoming content URI:
        when(sUriMatcher.match(uri)) {
    
            GET_SINGLE_CONTACT -> {
    
                // Queries and returns the contact for the requested name. Decodes
                // the incoming URI, queries the data model based on the last name,
                // and returns the result as a Cursor.
            }
        }
        ...
    }
    

    Java

    // Sets up your provider's query() method.
    public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs,
        String sortOrder) {
        ...
        // Switch based on the incoming content URI.
        switch (sUriMatcher.match(uri)) {
    
        case GET_SINGLE_CONTACT:
    
            // Queries and returns the contact for the requested name. Decodes the
            // incoming URI, queries the data model based on the last name, and
            // returns the result as a Cursor.
        ...
    }
    
  5. Richten Sie die Methode getType() so ein, dass ein geeigneter MIME-Typ für kopierte Daten zurückgegeben wird:

    Kotlin

    // Sets up your provider's getType() method.
    override fun getType(uri: Uri): String? {
        ...
        return when(sUriMatcher.match(uri)) {
            GET_SINGLE_CONTACT -> MIME_TYPE_CONTACT
            ...
        }
    }
    

    Java

    // Sets up your provider's getType() method.
    public String getType(Uri uri) {
        ...
        switch (sUriMatcher.match(uri)) {
        case GET_SINGLE_CONTACT:
            return (MIME_TYPE_CONTACT);
        ...
        }
    }
    

Im Abschnitt Daten aus einem Inhalts-URI einfügen wird beschrieben, wie Sie einen Inhalts-URI aus der Zwischenablage abrufen und damit Daten abrufen und einfügen.

Datenstreams kopieren

Sie können große Mengen an Text und Binärdaten als Streams kopieren und einfügen. Die Daten können folgende Formen haben:

  • Auf dem Gerät gespeicherte Dateien
  • Streams von Sockets
  • Große Datenmengen, die im Datenbanksystem eines Anbieters gespeichert sind

Ein Inhaltsanbieter für Datenstreams bietet den Zugriff auf seine Daten mit einem Dateideskriptorobjekt wie AssetFileDescriptor anstelle eines Cursor-Objekts. Die Einfügeanwendung liest den Datenstream mit diesem Dateideskriptor.

So richten Sie Ihre Anwendung zum Kopieren eines Datenstreams bei einem Anbieter ein:

  1. Legen Sie einen Inhalts-URI für den Datenstream fest, den Sie in die Zwischenablage einfügen möchten. Dafür gibt es unter anderem folgende Optionen:
    • Codieren Sie eine Kennung für den Datenstream im URI, wie im Abschnitt Eine Kennung im URI codieren beschrieben, und verwalten Sie dann eine Tabelle in Ihrem Anbieter, die Kennungen und den entsprechenden Streamnamen enthält.
    • Codieren Sie den Streamnamen direkt im URI.
    • Verwende einen eindeutigen URI, der immer den aktuellen Stream des Anbieters zurückgibt. Wenn Sie diese Option verwenden, müssen Sie Ihren Anbieter so aktualisieren, dass er auf einen anderen Stream verweist, wenn Sie den Stream mithilfe des URI in die Zwischenablage kopieren.
  2. Geben Sie für jeden Datenstream-Typ, den Sie anbieten möchten, einen MIME-Typ an. Beim Einfügen von Anwendungen werden diese Informationen benötigt, um festzustellen, ob die Daten in die Zwischenablage eingefügt werden können.
  3. Implementieren Sie eine der ContentProvider-Methoden, die einen Dateideskriptor für einen Stream zurückgibt. Wenn Sie Kennungen im Inhalts-URI codieren, können Sie mit dieser Methode bestimmen, welcher Stream geöffnet werden soll.
  4. Erstellen Sie den Inhalts-URI und fügen Sie ihn in die Zwischenablage ein, um den Datenstream in die Zwischenablage zu kopieren.

Zum Einfügen eines Datenstreams ruft eine Anwendung den Clip aus der Zwischenablage ab, ruft den URI ab und verwendet ihn in einem Aufruf der Dateideskriptor-Methode ContentResolver, mit der der Stream geöffnet wird. Die Methode ContentResolver ruft die entsprechende ContentProvider-Methode auf und übergibt ihr den Inhalts-URI. Der Anbieter gibt den Dateideskriptor an die Methode ContentResolver zurück. Die Pasteing-Anwendung ist dann dafür verantwortlich, die Daten aus dem Stream zu lesen.

Die folgende Liste enthält die wichtigsten Dateideskriptormethoden für einen Inhaltsanbieter. Für jedes dieser Tools ist eine entsprechende ContentResolver-Methode vorhanden, an die der String „Deskriptor“ an den Methodennamen angehängt ist. Das ContentResolver-Analog von openAssetFile() ist beispielsweise openAssetFileDescriptor().

openTypedAssetFile()

Diese Methode gibt einen Asset-Dateideskriptor zurück, jedoch nur, wenn der angegebene MIME-Typ vom Anbieter unterstützt wird. Der Aufrufer – die Anwendung, die das Einfügen ausführt – gibt ein MIME-Typ-Muster an. Der Contentanbieter der Anwendung, der einen URI in die Zwischenablage kopiert, gibt einen AssetFileDescriptor-Datei-Handle zurück, wenn er diesen MIME-Typ bereitstellen kann, und gibt eine Ausnahme aus, wenn dies nicht möglich ist.

Diese Methode verarbeitet Unterabschnitte von Dateien. Damit können Sie Assets lesen, die der Contentanbieter in die Zwischenablage kopiert hat.

openAssetFile()
Diese Methode ist eine allgemeinere Form von openTypedAssetFile(). Es filtert nicht nach zulässigen MIME-Typen, kann aber Unterabschnitte von Dateien lesen.
openFile()
Dies ist eine allgemeinere Form von openAssetFile(). Sie kann keine Unterabschnitte von Dateien lesen.

Sie können optional die Methode openPipeHelper() mit Ihrer Dateideskriptormethode verwenden. Dadurch kann die Pasteing-Anwendung die Streamdaten mithilfe einer Pipe in einem Hintergrundthread lesen. Implementieren Sie die ContentProvider.PipeDataWriter-Schnittstelle, um diese Methode zu verwenden.

Effektive Funktionen zum Kopieren und Einfügen entwerfen

Beachten Sie die folgenden Punkte, um effektive Funktionen zum Kopieren und Einfügen für Ihre Anwendung zu entwerfen:

  • Es befindet sich immer nur ein Clip in der Zwischenablage. Durch einen neuen Kopiervorgang von einer beliebigen Anwendung im System wird der vorherige Clip überschrieben. Da der Nutzer möglicherweise Ihre Anwendung verlässt und vor der Rückkehr kopiert, können Sie nicht davon ausgehen, dass die Zwischenablage den Clip enthält, den der Nutzer zuvor in Ihrer Anwendung kopiert hat.
  • Mehrere ClipData.Item-Objekte pro Clip sollen das Kopieren und Einfügen von Mehrfachauswahlen anstelle unterschiedlicher Verweise auf eine einzelne Auswahl unterstützen. Normalerweise möchten Sie, dass alle ClipData.Item-Objekte in einem Clip die gleiche Form haben. Das heißt, sie müssen alle aus einfachem Text, Inhalts-URI oder Intent bestehen und dürfen nicht gemischt sein.
  • Wenn Sie Daten bereitstellen, können Sie verschiedene MIME-Darstellungen angeben. Fügen Sie die unterstützten MIME-Typen dem ClipDescription hinzu und implementieren Sie sie dann in Ihrem Contentanbieter.
  • Wenn Sie Daten aus der Zwischenablage abrufen, muss Ihre Anwendung die verfügbaren MIME-Typen prüfen und dann entscheiden, welchen Typ verwendet werden soll. Selbst wenn sich ein Clip in der Zwischenablage befindet und der Nutzer das Einfügen anfordert, muss Ihre Anwendung diesen Vorgang nicht ausführen. Fügen Sie ihn ein, wenn der MIME-Typ kompatibel ist. Sie können die Daten in der Zwischenablage mit coerceToText() in Text umwandeln. Wenn Ihre Anwendung mehr als einen der verfügbaren MIME-Typen unterstützt, können Sie dem Nutzer die Entscheidung überlassen, welchen Typ er verwenden möchte.