Kopieren und einfügen

Compose ausprobieren
Jetpack Compose ist das empfohlene UI-Toolkit für Android. Informationen zum Kopieren und Einfügen in Compose

Android bietet ein leistungsstarkes Framework für die Zwischenablage, mit dem Inhalte kopiert und eingefügt werden können. Es unterstützt einfache und komplexe Datentypen, einschließlich Textstrings, komplexer Datenstrukturen, Text- und Binärstreamdaten sowie Anwendungs-Assets. Einfache Textdaten werden direkt in der Zwischenablage gespeichert, während komplexe Daten als Referenz gespeichert werden, die die einfügende Anwendung mit einem Contentanbieter auflöst. 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 Feedback, wenn sie Inhalte in die Zwischenablage kopieren. Daher zeigt Android unter Android 13 (API-Level 33) und höher beim Kopieren zusätzlich zum Framework, das für das Kopieren und Einfügen zuständig ist, eine Standard-UI an. Aufgrund dieser Funktion besteht die Gefahr, dass Benachrichtigungen doppelt gesendet werden. Weitere Informationen zu diesem Grenzfall finden Sie im Abschnitt Doppelte Benachrichtigungen vermeiden.

Eine Animation, die die Benachrichtigung zur Zwischenablage in Android 13 zeigt
Abbildung 1. Benutzeroberfläche, die angezeigt wird, wenn Inhalte in Android 13 und höher in die Zwischenablage kopiert werden.

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

Das Clipboard-Framework

Wenn Sie das Clipboard-Framework verwenden, fügen Sie Daten in ein Clip-Objekt ein und legen das Clip-Objekt dann in der systemweiten Zwischenablage ab. Das Clip-Objekt kann eine von drei Formen annehmen:

Text
Ein Textstring. Füge den String direkt in das Clip-Objekt ein, das du dann in die Zwischenablage legst. Wenn Sie den String einfügen möchten, rufen Sie 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 dem Kopieren komplexer Daten von einem Contentanbieter. Wenn Sie Daten kopieren möchten, fügen Sie ein Uri-Objekt in ein Clip-Objekt ein und legen Sie das Clip-Objekt in der Zwischenablage ab. Wenn du die Daten einfügen möchtest, rufe das Clip-Objekt und das Uri-Objekt ab, löse es in eine Datenquelle wie einen Contentanbieter auf und kopiere die Daten aus der Quelle in den Speicher deiner Anwendung.
Absicht
Ein Intent. Dies unterstützt das Kopieren von Anwendungsverknüpfungen. Wenn Sie Daten kopieren möchten, erstellen Sie ein Intent, fügen Sie es in ein Clip-Objekt ein und legen Sie das Clip-Objekt in der Zwischenablage ab. Wenn Sie die Daten einfügen möchten, rufen Sie das Clip-Objekt ab und kopieren Sie dann das Intent-Objekt in den Speicherbereich Ihrer Anwendung.

In der Zwischenablage kann jeweils nur ein Clipobjekt gespeichert werden. Wenn eine Anwendung ein Clip-Objekt in die Zwischenablage legt, verschwindet das vorherige Clip-Objekt.

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 Möglichkeit geben, sie einzufügen. Das Clip-Objekt hat nicht nur eine bestimmte Datenform, sondern enthält auch Metadaten, die angeben, welche MIME-Typen verfügbar sind. Anhand dieser Metadaten können Sie entscheiden, ob Ihre Anwendung etwas Nützliches mit den Daten in der Zwischenablage tun kann. Wenn Sie beispielsweise eine Anwendung haben, die hauptsächlich Text verarbeitet, können Sie Clip-Objekte ignorieren, die einen URI oder Intent enthalten.

Sie können Nutzern auch erlauben, Text unabhängig von der Form der Daten in der Zwischenablage einzufügen. Erzwingen Sie dazu eine Textdarstellung der Daten in der Zwischenablage und fügen Sie diesen Text dann ein. Dies wird im Abschnitt Zwischenablage in Text umwandeln beschrieben.

Zwischenablageklassen

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

ClipboardManager

Die Android-Systemzwischenablage wird durch die globale Klasse ClipboardManager dargestellt. Instanziieren Sie diese Klasse nicht direkt. Rufen Sie stattdessen getSystemService(CLIPBOARD_SERVICE) auf, um einen Verweis darauf zu erhalten.

ClipData, ClipData.Item und ClipDescription

Wenn Sie Daten in die Zwischenablage einfügen möchten, erstellen Sie ein ClipData-Objekt, das eine Beschreibung der Daten und die Daten selbst enthält. In der Zwischenablage kann jeweils nur ein ClipData gespeichert werden. Ein ClipData enthält ein ClipDescription-Objekt und ein oder mehrere ClipData.Item-Objekte.

Ein ClipDescription-Objekt enthält Metadaten zum Clip. Insbesondere enthält es ein Array der verfügbaren 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 einfügen, sind diese Informationen für Anwendungen verfügbar, die den Clip einfügen können. Diese Anwendungen können prüfen, ob sie die Clipdaten verarbeiten können.

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

Text
CharSequence.
URI
Uri. Dieser 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 verwenden ihn, um auf den Contentanbieter oder eine andere Datenquelle zuzugreifen und die Daten abzurufen.
Absicht
Ein Intent. Mit diesem Datentyp können Sie eine Anwendungsverknüpfung in die Zwischenablage kopieren. Nutzer können die Verknüpfung dann in ihre Anwendungen einfügen, um sie später zu verwenden.

Du kannst einem Clip mehr als ein ClipData.Item-Objekt hinzufügen. So können Nutzer mehrere Auswahlen als einen einzigen Clip kopieren und einfügen. Wenn Sie beispielsweise ein Listen-Widget haben, mit dem der Nutzer mehrere Elemente gleichzeitig auswählen kann, können Sie alle Elemente gleichzeitig in die Zwischenablage kopieren. Erstellen Sie dazu für jedes Listenelement ein separates ClipData.Item-Objekt und fügen Sie die ClipData.Item-Objekte dem ClipData-Objekt hinzu.

ClipData-Komfortmethoden

Die Klasse ClipData bietet statische Komfortmethoden 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 einzige MIME-Typ in ClipDescription ist MIMETYPE_TEXT_PLAIN.

Verwenden Sie newPlainText(), um einen Clip aus einem Textstring zu 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, d. h. wenn Uri.getScheme() den Wert content: zurückgibt, verwendet die Methode das in resolver bereitgestellte ContentResolver-Objekt, um die verfügbaren MIME-Typen vom Contentanbieter abzurufen. Anschließend werden sie in ClipDescription gespeichert. Bei einem 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 einem content:-URI.

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

Verwenden Sie newIntent(), um einen Clip aus einem Intent-Objekt zu erstellen.

Daten in 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 einen 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, also 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 Content-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 mit der von Uri.toString() zurückgegebenen Darstellung identisch.
  • Wenn der URI kein Inhalts-URI ist, gibt coerceToText() eine Darstellung des URI zurück. Die Darstellung ist mit der von Uri.toString() zurückgegebenen Darstellung identisch.
Absicht
Wenn ClipData.Item ein Intent ist, also wenn getIntent() nicht null ist, konvertiert coerceToText() ihn in einen Intent-URI und gibt ihn zurück. Die Darstellung ist mit der von Intent.toUri(URI_INTENT_SCHEME) zurückgegebenen Darstellung identisch.

Das Clipboard-Framework ist in Abbildung 2 zusammengefasst. Zum Kopieren von Daten legt eine Anwendung ein ClipData-Objekt in der globalen Zwischenablage ClipboardManager ab. ClipData enthält ein oder mehrere ClipData.Item-Objekte und ein ClipDescription-Objekt. Zum Einfügen von Daten ruft eine Anwendung das ClipData ab, ruft den MIME-Typ aus dem ClipDescription ab und ruft die Daten aus dem ClipData.Item oder aus dem Contentanbieter ab, auf den ClipData.Item verweist.

Ein Bild mit einem Blockdiagramm des Frameworks zum Kopieren und Einfügen
Abbildung 2. Das Android-Framework für die Zwischenablage.

In die Zwischenablage kopieren

Wenn Sie Daten in die Zwischenablage kopieren möchten, rufen Sie ein Handle für das globale ClipboardManager-Objekt ab, erstellen Sie ein ClipData-Objekt und fügen Sie ihm ein ClipDescription-Objekt und ein oder mehrere ClipData.Item-Objekte hinzu. Fügen Sie dann das fertige ClipData-Objekt dem ClipboardManager-Objekt hinzu. Dies wird im folgenden Verfahren näher beschrieben:

  1. Wenn Sie Daten mit einem Inhalts-URI kopieren, richten Sie einen Contentanbieter ein.
  2. Rufen Sie die Zwischenablage des Systems ab:

    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

      In diesem Snippet wird ein URI erstellt, indem eine Datensatz-ID in den Inhalts-URI für den Anbieter codiert wird. Diese Technik wird im Abschnitt ID im URI codieren ausführlicher beschrieben.

      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 eine Intent

      In diesem Snippet wird ein Intent für eine Anwendung erstellt und dann im Clip-Objekt platziert:

      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. Fügen Sie das neue Clip-Objekt in die Zwischenablage ein:

    Kotlin

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

    Java

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

Feedback beim Kopieren in die Zwischenablage geben

Nutzer erwarten ein visuelles Feedback, wenn eine App Inhalte in die Zwischenablage kopiert. Bei Nutzern mit Android 13 und höher geschieht dies automatisch, in früheren Versionen muss es jedoch manuell implementiert werden.

Ab Android 13 zeigt das System eine visuelle Standardbestätigung an, wenn Inhalte in die Zwischenablage kopiert werden. Die neue Bestätigung hat folgende Auswirkungen:

  • Bestätigt, dass der Inhalt erfolgreich kopiert wurde.
  • Zeigt eine Vorschau des kopierten Inhalts an.

Eine Animation, die die Benachrichtigung zur Zwischenablage in Android 13 zeigt
Abbildung 3. Benutzeroberfläche, die angezeigt wird, wenn Inhalte in Android 13 und höher in die Zwischenablage kopiert werden.

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

Doppelte Benachrichtigungen vermeiden

Unter Android 12L (API-Level 32) und niedriger empfehlen wir, Nutzer nach dem Kopieren durch ein visuelles In-App-Feedback zu benachrichtigen, z. B. mit einem Widget wie Toast oder Snackbar.

Um doppelte Anzeigen von Informationen zu vermeiden, empfehlen wir dringend, Toasts oder Snackbars zu entfernen, die nach einem In-App-Kopiervorgang für Android 13 und höher angezeigt werden.

Snackbar nach dem Kopieren in der App posten.
Abbildung 4. Wenn Sie in Android 13 eine Snackbar zur Bestätigung des Kopiervorgangs anzeigen, sieht der Nutzer doppelte Nachrichten.
Toast-Benachrichtigung nach dem Kopieren in der App posten.
Abbildung 5. Wenn du in Android 13 eine Toast-Benachrichtigung zur Bestätigung des Kopiervorgangs anzeigst, sieht der Nutzer doppelte Nachrichten.

Hier 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()
}

Vertrauliche Inhalte in die Zwischenablage kopieren

Wenn Nutzer in Ihrer App 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. Wenn Sie dieses Flag hinzufügen, wird verhindert, dass sensible Inhalte in der visuellen Bestätigung von kopierten Inhalten in Android 13 und höher angezeigt werden.

Vorschau des kopierten Textes ohne Kennzeichnung sensibler Inhalte
Abbildung 6. Vorschau des kopierten Textes ohne Kennzeichnung für sensible Inhalte.
Vorschau des kopierten Textes, in der sensible Inhalte gekennzeichnet sind.
Abbildung 7. Vorschau des kopierten Textes mit einer Kennzeichnung für sensible Inhalte.

Wenn Sie sensible Inhalte kennzeichnen möchten, fügen Sie dem ClipDescription ein boolesches Extra hinzu. Dies ist für alle Apps erforderlich, 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, fügen Sie Daten aus der Zwischenablage ein, indem Sie das globale Zwischenablageobjekt abrufen, das Clip-Objekt abrufen, die Daten prüfen und die Daten nach Möglichkeit aus dem Clip-Objekt in Ihren eigenen Speicher kopieren. In diesem Abschnitt wird ausführlich erläutert, wie Sie die drei Arten von Zwischenablagedaten einfügen.

Nur-Text einfügen

Wenn Sie Nur-Text einfügen möchten, rufen Sie die globale Zwischenablage ab und prüfen Sie, ob sie Nur-Text zurückgeben kann. Rufen Sie dann das Clip-Objekt ab und kopieren Sie den Text mit getText() in Ihren eigenen Speicher, wie im folgenden Verfahren beschrieben:

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

    Kotlin

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

    Java

    ClipboardManager clipboard = (ClipboardManager) getSystemService(Context.CLIPBOARD_SERVICE);
    String pasteData = "";
  2. Bestimmen 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 des Clips verarbeiten können:

    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. Sie können also davon ausgehen, dass die Zwischenablage Nur-Text enthält. Sie wissen noch nicht, ob es einen Textstring oder einen URI enthält, der auf Nur-Text verweist. Das folgende Code-Snippet testet dies, zeigt aber nur den Code für die Verarbeitung von Nur-Text:

    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 ClipData.Item-Objekt einen Inhalts-URI enthält und Sie feststellen, dass Sie einen der MIME-Typen verarbeiten können, erstellen Sie einen ContentResolver und rufen Sie die entsprechende Contentanbieter-Methode auf, um die Daten abzurufen.

Im Folgenden wird beschrieben, wie Sie Daten von einem Contentanbieter basierend auf einem Content-URI in der Zwischenablage abrufen. Es wird geprüft, ob ein MIME-Typ, den die Anwendung verwenden kann, vom Anbieter verfügbar ist.

  1. Deklarieren Sie eine globale Variable, die den MIME-Typ enthält:

    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. Rufen Sie die globale Zwischenablage ab. Außerdem benötigst du einen ContentResolver, um auf den Contentanbieter zuzugreifen:

    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 und 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. Prüfen Sie mit getType(Uri), 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. Prüfen, ob der Contentanbieter einen MIME-Typ unterstützt, den die Anwendung versteht. Wenn ja, rufen Sie ContentResolver.query() auf, um die Daten abzurufen. Der Rückgabewert ist ein 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

Wenn Sie einen Intent einfügen möchten, rufen Sie zuerst die globale Zwischenablage ab. Prüfen Sie, ob das Objekt ClipData.Item eine Intent enthält. 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 Ihre App auf Daten in der Zwischenablage zugreift

Unter Android 12 (API-Level 31) und höher wird in der Regel eine Toast-Nachricht angezeigt, wenn Ihre App getPrimaryClip() aufruft. Der Text in der Nachricht hat das folgende Format:

APP pasted from your clipboard

In den folgenden Fällen wird keine Toast-Benachrichtigung angezeigt:

  • Greift über Ihre eigene App auf ClipData zu.
  • Greift wiederholt über eine bestimmte App auf ClipData zu. Die Toast-Benachrichtigung wird nur angezeigt, wenn deine App zum ersten Mal auf die Daten dieser App zugreift.
  • Ruft Metadaten für das Clip-Objekt ab, z. B. durch Aufrufen von getPrimaryClipDescription() anstelle von getPrimaryClip().

Contentanbieter zum Kopieren komplexer Daten verwenden

Contentanbieter unterstützen das Kopieren komplexer Daten wie Datenbankeinträge oder Dateistreams. Wenn Sie die Daten kopieren möchten, fügen Sie einen Inhalts-URI in die Zwischenablage ein. Anwendungen, in die eingefügt wird, rufen diesen URI dann aus der Zwischenablage ab und verwenden ihn, um Datenbankdaten oder Dateistream-Deskriptoren abzurufen.

Da die einfügende Anwendung nur den Inhalts-URI für Ihre Daten hat, 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 Sie können einen eindeutigen URI angeben, der die Daten zurückgibt, die Sie kopieren möchten. Welche Technik Sie wählen, hängt von der Organisation Ihrer Daten ab.

In den folgenden Abschnitten wird beschrieben, wie Sie URIs einrichten, komplexe Daten bereitstellen und Dateistreams bereitstellen. In den Beschreibungen wird davon ausgegangen, dass Sie mit den allgemeinen Prinzipien des Contentanbieter-Designs vertraut sind.

Kennung im URI codieren

Eine nützliche Methode 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 dann die Kennung aus dem URI abrufen und damit die Daten abrufen. Die Anwendung, in die eingefügt wird, muss nicht wissen, dass die Kennzeichnung existiert. Sie muss nur Ihre „Referenz“ – den URI und die Kennung – aus der Zwischenablage abrufen, an Ihren Contentanbieter übergeben und die Daten zurückerhalten.

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

"content://com.example.contacts"

Wenn Sie einen Namen in 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 zum Kopieren dient. 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"

Anschließend können Sie einen „Kopier-URI“ per Musterabgleich erkennen und mit Code verarbeiten, der speziell für das Kopieren und Einfügen vorgesehen ist.

Normalerweise verwenden Sie die Codierungstechnik, wenn Sie bereits einen Contentanbieter, eine interne Datenbank oder eine interne Tabelle zum Organisieren Ihrer Daten verwenden. In diesen Fällen haben Sie mehrere Daten, die Sie kopieren möchten, und vermutlich eine eindeutige Kennung für jedes Datenelement. Als Antwort auf eine Anfrage der einfügenden Anwendung können Sie die Daten anhand ihrer Kennung suchen und zurückgeben.

Wenn Sie nicht mehrere Daten haben, müssen Sie wahrscheinlich keine Kennzeichnung codieren. Sie können einen URI verwenden, der für Ihren Anbieter eindeutig ist. Als Antwort auf eine Abfrage gibt Ihr Anbieter die Daten zurück, die er derzeit enthält.

Datenstrukturen kopieren

Richte einen Contentanbieter zum Kopieren und Einfügen komplexer Daten als Unterklasse der Komponente ContentProvider ein. Codieren Sie den URI, den Sie in die Zwischenablage kopiert haben, sodass er auf den genauen Eintrag verweist, den Sie bereitstellen möchten. Berücksichtigen Sie außerdem den aktuellen Status Ihrer Anwendung:

  • Wenn Sie bereits einen Contentanbieter haben, können Sie dessen Funktionalität erweitern. Möglicherweise musst du nur die Methode query() ändern, um URIs von Anwendungen zu verarbeiten, die Daten einfügen möchten. Du solltest die Methode wahrscheinlich so ändern, dass sie ein „copy“-URI-Muster verarbeitet.
  • Wenn deine Anwendung eine interne Datenbank verwaltet, kannst du diese Datenbank in einen Contentanbieter verschieben, um das Kopieren zu erleichtern.
  • Wenn du keine Datenbank verwendest, kannst du einen einfachen Contentanbieter implementieren, dessen einziger Zweck darin besteht, Daten für Anwendungen bereitzustellen, die aus der Zwischenablage einfügen.

Überschreiben Sie im Contentanbieter mindestens die folgenden Methoden:

query()
Anwendungen, die Daten einfügen, gehen davon aus, dass sie Ihre Daten mit dieser Methode und dem URI abrufen können, den Sie in die Zwischenablage eingefügt haben. Damit das Kopieren unterstützt wird, muss diese Methode URIs erkennen, die einen speziellen „copy“-Pfad enthalten. Ihre Anwendung kann dann einen „Kopier-URI“ erstellen, der in die Zwischenablage eingefügt wird. Dieser enthält den Kopierpfad und einen Verweis auf den genauen Datensatz, 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 einzufügen.

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

Andere Contentanbieter-Methoden wie insert() oder update() sind nicht erforderlich. Eine Anwendung, in die eingefügt wird, muss nur die unterstützten MIME-Typen abrufen und Daten von Ihrem Anbieter kopieren. Wenn Sie diese Methoden bereits haben, beeinträchtigen sie Kopiervorgänge nicht.

Die folgenden Snippets zeigen, wie Sie Ihre Anwendung so einrichten, dass komplexe Daten kopiert werden:

  1. Deklarieren Sie in den globalen Konstanten für Ihre Anwendung einen Basis-URI-String und einen Pfad, der die 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 so ein, dass Daten in die Zwischenablage kopiert werden. Als Antwort auf eine Kopieranfrage wird der URI in die Zwischenablage kopiert.

    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. Erstelle im globalen Bereich deines Contentanbieters einen URI-Matcher und füge ein URI-Muster hinzu, das mit den URIs übereinstimmt, die du in die Zwischenablage kopierst.

    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 verschiedene URI-Muster verarbeiten. Es wird jedoch nur das Muster für den Kopiervorgang in die 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 sie einen geeigneten MIME-Typ für kopierte Daten zurückgibt:

    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 zugrunde liegenden Datenbanksystem eines Anbieters gespeichert sind

Ein Contentanbieter für Datenstreams ermöglicht den Zugriff auf seine Daten über ein Dateideskriptorobjekt wie AssetFileDescriptor anstelle eines Cursor-Objekts. Die Anwendung, in die eingefügt wird, liest den Datenstream mithilfe dieses Dateideskriptors.

So richten Sie Ihre Anwendung ein, um einen Datenstream mit einem Anbieter zu kopieren:

  1. Richte einen Inhalts-URI für den Datenstream ein, den du in die Zwischenablage kopierst. Dafür gibt es unter anderem folgende Optionen:
    • Codieren Sie eine Kennung für den Datenstream im URI, wie im Abschnitt Kennung im URI codieren beschrieben. Führen 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 vom Anbieter 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 Typ von Datenstream, den Sie anbieten möchten, einen MIME-Typ an. Anwendungen, die Daten einfügen, benötigen diese Informationen, um festzustellen, ob sie die Daten in der Zwischenablage einfügen können.
  3. Implementiere eine der ContentProvider-Methoden, die einen Dateideskriptor für einen Stream zurückgibt. Wenn Sie Kennungen im Content-URI codieren, können Sie mit dieser Methode bestimmen, welcher Stream geöffnet werden soll.
  4. Wenn Sie den Datenstream in die Zwischenablage kopieren möchten, erstellen Sie den Inhalts-URI und fügen Sie ihn in die Zwischenablage ein.

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

In der folgenden Liste sind die wichtigsten Dateideskriptormethoden für einen Contentanbieter aufgeführt. Jede dieser Methoden hat eine entsprechende ContentResolver-Methode, bei der der String „Descriptor“ an den Methodennamen angehängt wird. Das ContentResolver-Analogon von openAssetFile() ist beispielsweise openAssetFileDescriptor().

openTypedAssetFile()

Diese Methode gibt einen Asset-Dateideskriptor zurück, aber nur, wenn der angegebene MIME-Typ vom Anbieter unterstützt wird. Der Aufrufer, also die Anwendung, die den Inhalt einfügt, stellt ein MIME-Typ-Muster bereit. Der Contentanbieter der Anwendung, die einen URI in die Zwischenablage kopiert, gibt ein AssetFileDescriptor-Dateihandle zurück, wenn er diesen MIME-Typ bereitstellen kann. Andernfalls wird eine Ausnahme ausgelöst.

Diese Methode verarbeitet Unterabschnitte von Dateien. Damit kannst du Assets lesen, die der Contentanbieter in die Zwischenablage kopiert hat.

openAssetFile()
Diese Methode ist eine allgemeinere Form von openTypedAssetFile(). Es wird nicht nach zulässigen MIME-Typen gefiltert, aber es können Unterabschnitte von Dateien gelesen werden.
openFile()
Dies ist eine allgemeinere Form von openAssetFile(). Es kann keine Unterabschnitte von Dateien lesen.

Sie können die Methode openPipeHelper() optional mit Ihrer Dateideskriptormethode verwenden. So kann die Anwendung, in die eingefügt wird, die Streamdaten in einem Hintergrundthread über eine Pipe lesen. Implementieren Sie die Schnittstelle ContentProvider.PipeDataWriter, um diese Methode zu verwenden.

Effektive Kopier- und Einfügefunktionen entwerfen

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

  • Es befindet sich immer nur ein Clip in der Zwischenablage. Ein neuer Kopiervorgang durch eine beliebige Anwendung im System überschreibt den vorherigen Clip. Da der Nutzer möglicherweise Ihre Anwendung verlässt und etwas kopiert, bevor er zurückkehrt, können Sie nicht davon ausgehen, dass die Zwischenablage den Clip enthält, den der Nutzer zuvor in Ihrer Anwendung kopiert hat.
  • Der Zweck mehrerer ClipData.Item-Objekte pro Clip besteht darin, das Kopieren und Einfügen mehrerer Auswahlen zu unterstützen, anstatt verschiedene Formen von Verweisen auf eine einzelne Auswahl zu ermöglichen. Normalerweise sollten alle ClipData.Item-Objekte in einem Clip dieselbe Form haben. Das bedeutet, dass sie alle einfacher Text, ein Inhalts-URI oder Intent sein müssen und nicht gemischt werden dürfen.
  • Wenn Sie Daten bereitstellen, können Sie verschiedene MIME-Darstellungen anbieten. Füge die von dir unterstützten MIME-Typen dem ClipDescription hinzu und implementiere die MIME-Typen dann in deinem Contentanbieter.
  • Wenn Sie Daten aus der Zwischenablage abrufen, ist Ihre Anwendung dafür verantwortlich, die verfügbaren MIME-Typen zu prüfen und dann zu entscheiden, welcher davon verwendet werden soll. Auch wenn sich ein Clip in der Zwischenablage befindet und der Nutzer ein Einfügen anfordert, muss deine Anwendung das Einfügen nicht ausführen. Führen Sie das Einfügen aus, 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 den Nutzer auswählen lassen, welcher verwendet werden soll.