Kopyala ve yapıştır

Android, kopyalama ve yapıştırma için güçlü bir pano tabanlı çerçeve sağlar. Metin dizeleri, karmaşık veri yapıları, metin ve ikili akış verileri ve uygulama öğeleri gibi basit ve karmaşık veri türlerini destekler. Basit metin verileri doğrudan panoda saklanırken, karmaşık veriler de yapıştırma uygulamasının içerik sağlayıcıyla çözdüğü bir referans olarak saklanır. Kopyalama ve yapıştırma hem uygulama içinde hem de çerçeveyi uygulayan uygulamalar arasında çalışır.

Çerçevenin bir kısmı içerik sağlayıcıları kullandığından bu belgede, İçerik sağlayıcılar bölümünde açıklanan Android Content Provider API hakkında biraz bilgi sahibi olduğunuz varsayılmaktadır.

Kullanıcılar panoya içerik kopyalarken geri bildirim bekler. Bu nedenle, kopyalama ve yapıştırma işlevine güç veren çerçeveye ek olarak Android, Android 13 (API düzeyi 33) ve sonraki sürümlerde kopyalama yaparken kullanıcılara varsayılan bir kullanıcı arayüzü gösterir. Bu özellik nedeniyle, yinelenen bildirimler riski vardır. Bu uç durum hakkında daha fazla bilgiyi Yinelenen bildirimlerden kaçınma bölümünden edinebilirsiniz.

Android 13 pano bildirimini gösteren animasyon
Şekil 1. Android 13 ve sonraki sürümlerde içerik panoya girdiğinde gösterilen kullanıcı arayüzü.

Android 12L (API düzeyi 32) ve önceki sürümlerde kopyalama yaparken kullanıcılara manuel olarak geri bildirim sağlayın. Bu dokümanda bununla ilgili önerilere göz atın.

Pano çerçevesi

Pano çerçevesini kullandığınızda, verileri bir klip nesnesine yerleştirin ve ardından klip nesnesini sistem genelindeki panoya yerleştirin. Klip nesnesi şu üç biçimden birinde olabilir:

Text
Metin dizesi. Dizeyi doğrudan klip nesnesine, daha sonra da panoya yerleştirin. Dizeyi yapıştırmak için klip nesnesini panodan alın ve dizeyi uygulamanızın depolama alanına kopyalayın.
URI
Herhangi bir URI biçimini temsil eden Uri nesnesi. Bu öncelikle bir içerik sağlayıcıdan karmaşık verilerin kopyalanması içindir. Verileri kopyalamak için klip nesnesine Uri nesnesi, klip nesnesini ise panoya yerleştirin. Verileri yapıştırmak için klip nesnesini alın, Uri nesnesini alın, içerik sağlayıcı gibi bir veri kaynağına çözümleyin ve kaynaktaki verileri uygulamanızın depolama alanına kopyalayın.
Amaç
Intent. Bu özellik, uygulama kısayollarının kopyalanmasını destekler. Verileri kopyalamak için bir Intent oluşturun, bunu bir klip nesnesine yerleştirin ve klip nesnesini panoya yerleştirin. Verileri yapıştırmak için klip nesnesini alın ve ardından Intent nesnesini uygulamanızın bellek alanına kopyalayın.

Pano aynı anda yalnızca bir klip nesnesi tutar. Bir uygulama panoya bir klip nesnesi yerleştirdiğinde, önceki klip nesnesi kaybolur.

Kullanıcıların uygulamanıza veri yapıştırmasına izin vermek istiyorsanız tüm veri türlerini işlemeniz gerekmez. Kullanıcılara yapıştırma seçeneği sunmadan önce panodaki verileri inceleyebilirsiniz. Klip nesnesi, belirli bir veri biçimine sahip olmanın yanı sıra, hangi MIME türlerinin mevcut olduğunu bildiren meta veriler de içerir. Bu meta veriler, uygulamanızın pano verileriyle faydalı bir şeyler yapıp yapamayacağına karar vermenize yardımcı olur. Örneğin, öncelikli olarak metin işleyen bir uygulamanız varsa URI veya amaç içeren klip nesnelerini göz ardı etmek isteyebilirsiniz.

Ayrıca, panodaki veri biçiminden bağımsız olarak kullanıcıların metin yapıştırmasına da izin verebilirsiniz. Bunu yapmak için pano verilerini metin gösterimine zorlayın, ardından bu metni yapıştırın. Bu, Panoyu metne yönlendirme bölümünde açıklanmaktadır.

Pano dersleri

Bu bölümde, pano çerçevesi tarafından kullanılan sınıflar açıklanmaktadır.

Pano Yöneticisi

Android sistem panosu, genel ClipboardManager sınıfıyla gösterilir. Bu sınıfı doğrudan somutlaştırmayın. Bunun yerine, getSystemService(CLIPBOARD_SERVICE) komutunu çağırarak referans alabilirsiniz.

ClipData, ClipData.Item ve ClipDescription

Panoya veri eklemek için verilerin ve verilerin açıklamasını içeren bir ClipData nesnesi oluşturun. Panoda her defasında bir ClipData tutulur. Bir ClipData, bir ClipDescription nesnesi ve bir veya daha fazla ClipData.Item nesne içerir.

ClipDescription nesnesi, kliple ilgili meta verileri içerir. Özellikle, klibin verileri için bir dizi kullanılabilir MIME türü içerir. Buna ek olarak, Android 12 (API düzeyi 31) ve sonraki sürümlerde meta veriler nesnenin stilize edilmiş metin içerip içermediği ve nesnedeki metin türü hakkında bilgiler içerir. Panoya bir klip yerleştirdiğinizde, bu bilgiler uygulamalara yapıştırılarak kullanılabilir. Bu bilgiler, uygulamaların klip verilerini işleyip işleyemediğini inceleyebilir.

Bir ClipData.Item nesnesi metin, URI veya amaç verilerini içerir:

Text
CharSequence.
URI
Uri. Bu genellikle bir içerik sağlayıcı URI'sı içerir ancak herhangi bir URI'ye izin verilir. Verileri sağlayan uygulama, URI'yı panoya yerleştirir. Verileri yapıştırmak isteyen uygulamalar panodan URI'yı alır ve içerik sağlayıcıya ya da başka bir veri kaynağına erişmek ve verileri almak için kullanır.
Amaç
Intent. Bu veri türü, uygulama kısayolunu panoya kopyalamanıza olanak tanır. Böylece kullanıcılar, kısayolu daha sonra kullanmak üzere uygulamalarına yapıştırabilir.

Bir klibe birden fazla ClipData.Item nesnesi ekleyebilirsiniz. Bu, kullanıcıların birden fazla seçimi kopyalayıp tek bir klip olarak yapıştırmasına olanak tanır. Örneğin, kullanıcının aynı anda birden fazla öğe seçmesine olanak tanıyan bir liste widget'ınız varsa tüm öğeleri aynı anda panoya kopyalayabilirsiniz. Bunu yapmak için her liste öğesi için ayrı bir ClipData.Item oluşturun ve daha sonra ClipData.Item nesnelerini ClipData nesnesine ekleyin.

ClipData kolaylık yöntemleri

ClipData sınıfı, tek bir ClipData.Item nesnesi ve basit bir ClipDescription nesnesiyle ClipData nesnesi oluşturmak için statik kolaylık yöntemleri sağlar:

newPlainText(label, text)
Tek ClipData.Item nesnesinin metin dizesi içeren bir ClipData nesnesi döndürür. ClipDescription nesnesinin etiketi label olarak ayarlandı. ClipDescription içindeki tek MIME türü MIMETYPE_TEXT_PLAIN.

Metin dizesinden klip oluşturmak için newPlainText() komutunu kullanın.

newUri(resolver, label, URI)
Tek ClipData.Item nesnesinin URI içeren bir ClipData nesnesi döndürür. ClipDescription nesnesinin etiketi label olarak ayarlandı. URI bir içerik URI'siyse (Uri.getScheme(), content: değerini döndürürse) yöntem, kullanılabilir MIME türlerini içerik sağlayıcıdan almak için resolver içinde sağlanan ContentResolver nesnesini kullanır. Daha sonra bunları ClipDescription içinde depolar. content: URI'sı olmayan bir URI için yöntem, MIME türünü MIMETYPE_TEXT_URILIST olarak ayarlar.

Bir URI'den, özellikle de content: URI'sından klip oluşturmak için newUri() öğesini kullanın.

newIntent(label, intent)
Tek ClipData.Item nesnesi Intent içeren bir ClipData nesnesi döndürür. ClipDescription nesnesinin etiketi label olarak ayarlandı. MIME türü MIMETYPE_TEXT_INTENT olarak ayarlandı.

Intent nesnesinden klip oluşturmak için newIntent() komutunu kullanın.

Pano verilerini metne dönüştürme

Uygulamanız yalnızca metin işliyor olsa bile metin olmayan verileri ClipData.Item.coerceToText() yöntemiyle dönüştürerek panodan kopyalayabilirsiniz.

Bu yöntem, ClipData.Item içindeki verileri metne dönüştürür ve CharSequence döndürür. ClipData.Item.coerceToText() işlevinin döndürdüğü değer, ClipData.Item öğesindeki veri biçimine bağlıdır:

Text
ClipData.Item metinse (getText() null değilse) coerceToText() metni döndürür.
URI
ClipData.Item bir URI ise (yani getUri() null değilse) coerceToText() bunu içerik URI'si olarak kullanmaya çalışır.
  • URI bir içerik URI'sı ise ve sağlayıcı bir metin akışı döndürebiliyorsa coerceToText() bir metin akışı döndürür.
  • URI bir içerik URI'sı olmasına rağmen sağlayıcı bir metin akışı sunmuyorsa coerceToText(), URI'nın bir temsilini döndürür. Temsil, Uri.toString() tarafından döndürülenle aynıdır.
  • URI bir içerik URI'si değilse coerceToText(), URI'nın bir gösterimini döndürür. Temsil, Uri.toString() tarafından döndürülenle aynıdır.
Amaç
ClipData.Item bir Intent ise (yani getIntent() null değilse) coerceToText() bunu bir Intent URI'sına dönüştürür ve döndürür. Temsil, Intent.toUri(URI_INTENT_SCHEME) tarafından döndürülenle aynıdır.

Pano çerçevesi, Şekil 2'de özetlenmiştir. Bir uygulama, verileri kopyalamak için ClipboardManager genel panosuna ClipData nesnesi yerleştirir. ClipData, bir veya daha fazla ClipData.Item nesnesi ve bir ClipDescription nesnesi içerir. Uygulama, verileri yapıştırmak için ClipData bilgisini alır, MIME türünü ClipDescription'dan ve verileri ClipData.Item veya ClipData.Item tarafından başvurulan içerik sağlayıcıdan alır.

Kopyala ve yapıştır çerçevesinin blok diyagramını gösteren resim
Şekil 2. Android pano çerçevesi.

Panoya kopyala

Verileri panoya kopyalamak için genel ClipboardManager nesnesini tutun, bir ClipData nesnesi oluşturun ve buna ClipDescription ile bir veya daha fazla ClipData.Item nesnesi ekleyin. Ardından, biten ClipData nesnesini ClipboardManager nesnesine ekleyin. Bu, aşağıdaki prosedürde daha ayrıntılı bir şekilde açıklanmaktadır:

  1. İçerik URI'sı kullanarak veri kopyalıyorsanız bir içerik sağlayıcı ayarlayın.
  2. Sistem panosunu alın:

    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. Verileri yeni bir ClipData nesnesine kopyalayın:

    • Metin için

      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!");
      
    • URI için

      Bu snippet, sağlayıcının içerik URI'sına bir kayıt kimliği kodlayarak bir URI oluşturur. Bu teknik, URI'de bir tanımlayıcıyı kodlama bölümünde daha ayrıntılı olarak ele alınmıştır.

      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);
      
    • Amacınız için

      Bu snippet, bir uygulama için Intent oluşturur ve daha sonra bunu klip nesnesine yerleştirir:

      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. Yeni klip nesnesini panoya yerleştirin:

    Kotlin

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

    Java

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

Panoya kopyalarken geri bildirim sağla

Kullanıcılar, uygulamalar panoya içerik kopyaladığında görsel geri bildirim bekler. Bu işlem, Android 13 ve sonraki sürümlerdeki kullanıcılar için otomatik olarak gerçekleştirilir ancak önceki sürümlerde manuel olarak uygulanması gerekir.

Android 13'ten itibaren, içerik panoya eklendiğinde sistem standart bir görsel onay gösterir. Yeni onay aşağıdaki işlemleri gerçekleştirir:

  • İçeriğin başarıyla kopyalandığını onaylar.
  • Kopyalanan içeriğin önizlemesini sağlar.

Android 13 pano bildirimini gösteren animasyon
Şekil 3. Android 13 ve sonraki sürümlerde içerik panoya girdiğinde gösterilen kullanıcı arayüzü.

Android 12L (API düzeyi 32) ve önceki sürümlerde kullanıcılar içeriği başarılı bir şekilde mi yoksa neleri kopyaladıklarından emin olamayabilir. Bu özellik, kopyalama işleminden sonra uygulamalar tarafından gösterilen çeşitli bildirimleri standart hale getirir ve kullanıcılara pano üzerinde daha fazla kontrol sunar.

Yinelenen bildirimlerden kaçının

Android 12L (API düzeyi 32) ve önceki sürümlerde, kopyalama işleminden sonra Toast veya Snackbar gibi bir widget kullanarak görsel, uygulama içi geri bildirim göndererek kullanıcıları başarılı bir şekilde kopyalama işlemi yaptıklarında uyarmanızı öneririz.

Android 13 ve sonraki sürümlerde, bilgilerin yinelenen şekilde gösterilmesini önlemek için uygulama içi kopyadan sonra gösterilen durum bildirimlerini veya atıştırmalık çubuklarını kaldırmanızı kesinlikle öneririz.

Uygulama içi kopyadan sonra Snackbar yayınla.
Şekil 4. Android 13'te kopya onayı atıştırmalık çubuğunu gösterirseniz kullanıcıya yinelenen mesajlar gösterilir.
Uygulama içi kopyadan sonra kısa mesaj yayınlayın.
Şekil 5. Android 13'te bir kopyalama onayı onay mesajı gösterirseniz kullanıcı yinelenen mesajlar görür.

Aşağıda, bunun nasıl uygulanacağına ilişkin bir örnek verilmiştir:

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

Panoya hassas içerik ekleme

Uygulamanız, kullanıcıların şifreler veya kredi kartı bilgileri gibi hassas içerikleri panoya kopyalamalarına izin veriyorsa ClipboardManager.setPrimaryClip() işlevini çağırmadan önce ClipData içinde ClipDescription için bayrak eklemeniz gerekir. Bu işaretin eklenmesi, Android 13 ve sonraki sürümlerde kopyalanan içeriğin görsel onayında hassas içeriğin görünmesini engeller.

Metin önizlemesi, hassas içerik işaretlenmeden kopyalandı
Şekil 6. Metin önizlemesi, hassas içerik işareti olmadan kopyalandı.
Hassas içerikleri işaretleyen metin önizlemesi kopyalandı.
Şekil 7. Hassas içerik işareti içeren metin önizlemesi kopyalandı.

Hassas içerikleri işaretlemek için ClipDescription öğesine fazladan bir boole ekleyin. Hedeflenen API düzeyi ne olursa olsun tüm uygulamalar bunu yapmalıdır.

// 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)
    }
}

Panodan yapıştır

Daha önce açıklandığı gibi, genel pano nesnesini alarak, klip nesnesini alarak, verilerine bakarak ve mümkünse verileri klip nesnesinden kendi depolama alanınıza kopyalayarak panodan veri yapıştırın. Bu bölümde, üç pano verisi biçiminin nasıl yapıştırılacağı ayrıntılı olarak açıklanmaktadır.

Düz metin yapıştır

Düz metni yapıştırmak için genel panoyu alın ve düz metin döndürebildiğini doğrulayın. Ardından klip nesnesini alın ve aşağıdaki prosedürde açıklandığı gibi getText() öğesini kullanarak metnini kendi depolama alanınıza kopyalayın:

  1. getSystemService(CLIPBOARD_SERVICE) kullanarak genel ClipboardManager nesnesini alın. Ayrıca, yapıştırılan metni içerecek bir genel değişken bildirin:

    Kotlin

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

    Java

    ClipboardManager clipboard = (ClipboardManager) getSystemService(Context.CLIPBOARD_SERVICE);
    String pasteData = "";
    
  2. Geçerli etkinlikte "Yapıştır" seçeneğini etkinleştirmeniz mi yoksa devre dışı bırakmanız mı gerektiğini belirleyin. Panonun bir klip içerdiğini ve klibin temsil ettiği veri türünü işleyebileceğinizi doğrulayın:

    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. Panodaki verileri kopyalayın. Koddaki bu noktaya yalnızca "yapıştır" menü öğesi etkinse erişilebilir. Dolayısıyla, panonun düz metin içerdiğini varsayabilirsiniz. Bir metin dizesi veya düz metne işaret eden bir URI içerip içermediğinden emin olamazsınız. Aşağıdaki kod snippet'i bunu test eder, ancak yalnızca düz metin işleme kodunu gösterir:

    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;
        }
    }
    

İçerik URI'sından veri yapıştırma

ClipData.Item nesnesi bir içerik URI'si içeriyorsa ve MIME türlerinden birini işleyebileceğinizi belirlerseniz bir ContentResolver oluşturun ve verileri almak için uygun içerik sağlayıcı yöntemini çağırın.

Aşağıdaki prosedürde, panodaki içerik URI'sına dayanarak içerik sağlayıcıdan nasıl veri alınacağı açıklanmaktadır. Uygulamanın kullanabileceği bir MIME türünün sağlayıcıdan sunulup sunulmadığını kontrol eder.

  1. Genel değişkeni, MIME türünü içerecek şekilde bildirin:

    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. Genel panoyu al. Ayrıca içerik sağlayıcıya erişebilmek için bir içerik çözümleyici edinin:

    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. Panodan birincil klibi alın ve içeriğini URI olarak alın:

    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. getType(Uri) yöntemini çağırarak URI'nın bir içerik URI'si olup olmadığını test edin. Uri geçerli bir içerik sağlayıcıya işaret etmiyorsa bu yöntem null değerini döndürür.

    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. İçerik sağlayıcının, uygulamanın anladığı bir MIME türünü destekleyip desteklemediğini test edin. İçeriyorsa verileri almak için ContentResolver.query() yöntemini çağırın. Döndürülen değer Cursor olur.

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

İntent Yapıştır

Niyeti yapıştırmak için önce genel panoyu alın. Intent içerip içermediğini görmek için ClipData.Item nesnesini inceleyin. Ardından, amacı kendi depolama alanınıza kopyalamak için getIntent() numaralı telefonu arayın. Aşağıdaki snippet bunu gösterir:

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.
}

Uygulamanız pano verilerine eriştiğinde gösterilen sistem bildirimi

Android 12 (API düzeyi 31) ve sonraki sürümlerde, uygulamanız getPrimaryClip() araması yaptığında sistem genellikle bir durum mesajı gösterir. İletinin içindeki metin şu biçimdedir:

APP pasted from your clipboard

Uygulamanız aşağıdakilerden birini yaptığında sistem bir durum mesajı mesajı göstermez:

  • ClipData uygulamasına kendi uygulamanızdan erişir.
  • Belirli bir uygulama üzerinden ClipData uygulamasına sürekli olarak erişiyor. Durum mesajı, yalnızca uygulamanız söz konusu uygulamadaki verilere ilk kez eriştiğinde görünür.
  • Klip nesnesinin meta verilerini alır (örneğin, getPrimaryClip() yerine getPrimaryClipDescription() yöntemini çağırarak).

Karmaşık verileri kopyalamak için içerik sağlayıcıları kullanma

İçerik sağlayıcılar, veritabanı kayıtları veya dosya akışları gibi karmaşık verilerin kopyalanmasını destekler. Verileri kopyalamak için panoya bir içerik URI'si yerleştirin. Uygulamalar daha sonra panodan bu URI'yı alır ve veritabanı verilerini veya dosya akışı açıklayıcılarını almak için kullanır.

Yapıştırma uygulaması, verileriniz için yalnızca içerik URI'sına sahip olduğundan hangi veri parçasının alınacağını bilmesi gerekir. Bu bilgileri, URI'nın kendisinde veriler için bir tanımlayıcı kodlayarak veya kopyalamak istediğiniz verileri döndüren benzersiz bir URI sağlayabilirsiniz. Hangi teknik verilerin düzenleneceğine bağlıdır.

Aşağıdaki bölümlerde URI'lerin nasıl oluşturulacağı, karmaşık verilerin nasıl sağlanacağı ve dosya akışlarının nasıl sağlanacağı açıklanmaktadır. Açıklamalarda, içerik sağlayıcı tasarımının genel ilkeleri hakkında bilgi sahibi olduğunuz varsayılır.

Bir tanımlayıcıyı URI'da kodlama

Verileri bir URI ile panoya kopyalamak için yararlı bir teknik, URI'nın kendisinde veriler için bir tanımlayıcı kodlamaktır. Daha sonra içerik sağlayıcınız tanımlayıcıyı URI'dan alabilir ve verileri almak için kullanabilir. Yapıştırma uygulamasının, tanımlayıcının var olduğunu bilmesi gerekmez. Bunun için panodan "referansı" (URI ile tanımlayıcı) almanız, içerik sağlayıcınıza vermeniz ve verileri geri almanız yeterlidir.

Bir tanımlayıcıyı genellikle URI'nın sonuyla birleştirerek içerik URI'sına kodlarsınız. Örneğin, sağlayıcı URI'nızı aşağıdaki dize olarak tanımladığınızı varsayalım:

"content://com.example.contacts"

Bu URI üzerine bir ad kodlamak istiyorsanız şu kod snippet'ini kullanın:

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);

Zaten bir içerik sağlayıcı kullanıyorsanız URI'nın kopyalama için olduğunu belirten yeni bir URI yolu eklemek isteyebilirsiniz. Örneğin, zaten aşağıdaki URI yollarına sahip olduğunuzu varsayalım:

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

URI'leri kopyalamak için başka bir yol ekleyebilirsiniz:

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

Daha sonra, kalıp eşleştirmeyle bir "kopya" URI'sını algılayabilir ve bunu, kopyalama ve yapıştırma için özel kodla işleyebilirsiniz.

Kodlama tekniğini, verilerinizi düzenlemek için zaten bir içerik sağlayıcı, dahili veritabanı veya dahili tablo kullanıyorsanız normal şekilde kullanırsınız. Bu gibi durumlarda, kopyalamak istediğiniz birden fazla veri parçası ve muhtemelen her bir parça için benzersiz bir tanımlayıcınız olur. Yapıştırma uygulamasından yapılan bir sorguya yanıt olarak, verileri tanımlayıcısına göre arayıp döndürebilirsiniz.

Birden çok veri parçanız yoksa muhtemelen bir tanımlayıcı kodlamanız gerekmez. Sağlayıcınıza özgü bir URI kullanabilirsiniz. Bir sorguya yanıt olarak, sağlayıcınız şu anda içerdiği verileri döndürür.

Veri yapılarını kopyalama

ContentProvider bileşeninin bir alt sınıfı olarak karmaşık verileri kopyalayıp yapıştırmak için bir içerik sağlayıcı ayarlayın. Panoya yerleştirdiğiniz URI'yı, tam olarak sağlamak istediğiniz kaydı işaret edecek şekilde kodlayın. Ayrıca başvurunuzun mevcut durumunu da göz önünde bulundurun:

  • Halihazırda bir içerik sağlayıcınız varsa işlevselliğini ekleyebilirsiniz. Veri yapıştırmak isteyen uygulamalardan gelen URI'leri işlemek için query() yöntemini değiştirmeniz gerekebilir. Muhtemelen yöntemi bir "kopya" URI kalıbını işleyecek şekilde değiştirmek istersiniz.
  • Uygulamanız dahili bir veritabanına sahipse bu veritabanından kopyalamayı kolaylaştırmak için veritabanını bir içerik sağlayıcısına taşımak isteyebilirsiniz.
  • Veritabanı kullanmıyorsanız tek amacı panodan yapıştırma yapan uygulamalara veri sunmak olan basit bir içerik sağlayıcı uygulayabilirsiniz.

İçerik sağlayıcıda, en azından aşağıdaki yöntemleri geçersiz kılın:

query()
Yapıştırılan uygulamalar, bu yöntemi panoya yerleştirdiğiniz URI ile kullanarak verilerinizi alabildiğini varsayar. Kopyalamayı desteklemek için bu yöntemin, özel bir "kopya" yolu içeren URI'leri algılamasını sağlayın. Uygulamanız bunun ardından panoya yerleştirmek üzere kopyalama yolunu ve kopyalamak istediğiniz tam kaydın işaretçisini içeren bir "kopya" URI'sı oluşturabilir.
getType()
Bu yöntem, kopyalamak istediğiniz veriler için MIME türlerini döndürmelidir. newUri() yöntemi, MIME türlerini yeni ClipData nesnesine yerleştirmek için getType() yöntemini çağırır.

Karmaşık verilere yönelik MIME türleri, İçerik sağlayıcılarda açıklanmıştır.

Diğer içerik sağlayıcı yöntemlerinden (ör. insert() veya update()) birini kullanmanız gerekmez. Yapıştırma uygulamalarının yalnızca desteklenen MIME türlerinizi alması ve sağlayıcınızdan veri kopyalaması yeterlidir. Bu yöntemleri zaten kullanıyorsanız kopyalama işlemlerini etkilemezler.

Aşağıdaki snippet'lerde karmaşık verileri kopyalamak için uygulamanızı nasıl ayarlayacağınız gösterilmektedir:

  1. Uygulamanızın genel sabit değerlerinde, bir temel URI dizesi ve verileri kopyalamak için kullandığınız URI dizelerini tanımlayan bir yol bildirin. Kopyalanan veriler için de bir MIME türü bildirin.

    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. Kullanıcıların veri kopyaladığı etkinlik bölümünde, verileri panoya kopyalamak için kodu ayarlayın. Kopyalama isteğine yanıt olarak URI'yi panoya yerleştirin.

    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. İçerik sağlayıcınızın genel kapsamında, bir URI eşleştirici oluşturun ve panoya yerleştirdiğiniz URI'lerle eşleşen bir URI kalıbı ekleyin.

    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. query() yöntemini ayarlayın. Bu yöntem, kodlama şeklinize bağlı olarak farklı URI kalıplarını işleyebilir ancak yalnızca pano kopyalama işleminin kalıbı gösterilir.

    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. Kopyalanan veriler için uygun bir MIME türü döndürecek getType() yöntemini ayarlayın:

    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);
        ...
        }
    }
    

İçerik URI'sinden veri yapıştırma bölümünde, panodan içerik URI'sinin nasıl alınacağı ve verileri almak ve yapıştırmak için nasıl kullanılacağı açıklanmaktadır.

Veri akışlarını kopyala

Büyük miktarlarda metin ve ikili verileri akış olarak kopyalayıp yapıştırabilirsiniz. Veriler aşağıdaki gibi formlara sahip olabilir:

  • Asıl cihazda depolanan dosyalar
  • Yuvalardan akışlar
  • Bir sağlayıcının temel veritabanı sisteminde depolanan büyük miktarda veri

Veri akışları için bir içerik sağlayıcı, verilerine Cursor nesnesi yerine AssetFileDescriptor gibi bir dosya tanımlayıcı nesne ile erişim sağlar. Yapıştırma uygulaması, veri akışını bu dosya açıklayıcıyı kullanarak okur.

Uygulamanızı bir veri akışını sağlayıcıyla kopyalayacak şekilde ayarlamak için aşağıdaki adımları uygulayın:

  1. Panoya koyduğunuz veri akışı için bir içerik URI'si oluşturun. Bunun için kullanabileceğiniz seçenekler şunlardır:
    • URI'de tanımlayıcı kodlama bölümünde açıklandığı gibi, URI'ye veri akışı tanımlayıcısı kodlayın ve ardından sağlayıcınızda tanımlayıcılar ile ilgili akış adını içeren bir tabloyu saklayın.
    • Akış adını doğrudan URI üzerinde kodlayın.
    • Her zaman sağlayıcıdan geçerli akışı döndüren benzersiz bir URI kullanın. Bu seçeneği kullanırsanız, URI'yı kullanarak akışı panoya her kopyaladığınızda sağlayıcınızı farklı bir akışı işaret edecek şekilde güncellemeyi unutmayın.
  2. Sunmayı planladığınız her veri akışı türü için bir MIME türü sağlayın. Yapıştırılan uygulamalar, verileri panoya yapıştırıp yapıştıramayacaklarını belirlemek için bu bilgilere ihtiyaç duyar.
  3. Akış için dosya tanımlayıcısı döndüren ContentProvider yöntemlerinden birini uygulayın. Tanımlayıcıları içerik URI'sinde kodluyorsanız hangi akışın açılacağını belirlemek için bu yöntemi kullanın.
  4. Veri akışını panoya kopyalamak için içerik URI'sini oluşturun ve panoya yerleştirin.

Bir uygulama, veri akışını yapıştırmak için klibi panodan alır, URI'yı alır ve akışı açan bir ContentResolver dosya açıklayıcı yöntemine yapılan çağrıda bunu kullanır. ContentResolver yöntemi, ilgili ContentProvider yöntemini içerik URI'sına iletir. Sağlayıcınız, dosya açıklayıcıyı ContentResolver yöntemine döndürür. Yapıştırma uygulaması, verileri akıştan okuma sorumluluğuna sahiptir.

Aşağıdaki listede, içerik sağlayıcı için en önemli dosya tanımlayıcı yöntemleri gösterilmektedir. Bunların her biri, yöntem adına "Descriptor" dizesi eklenmiş olan karşılık gelen bir ContentResolver yöntemine sahiptir. Örneğin, openAssetFile() analogunun ContentResolver analogu openAssetFileDescriptor() olur.

openTypedAssetFile()

Bu yöntem yalnızca sağlanan MIME türünün sağlayıcı tarafından desteklenmesi durumunda bir öğe dosyası açıklayıcısı döndürür. Arayan (yapıştırma işlemini yapan uygulama) MIME türü kalıbı sağlar. URI'yı panoya kopyalayan uygulamanın içerik sağlayıcısı, söz konusu MIME türünü sağlayabiliyorsa bir AssetFileDescriptor dosya tanıtıcısı döndürür, sağlayamadığında ise bir istisna oluşturur.

Bu yöntem dosyaların alt bölümlerini işler. İçerik sağlayıcının panoya kopyaladığı öğeleri okumak için bu özelliği kullanabilirsiniz.

openAssetFile()
Bu yöntem, openTypedAssetFile() işleminin daha genel bir biçimidir. İzin verilen MIME türlerini filtrelemez ancak dosyaların alt bölümlerini okuyabilir.
openFile()
Bu, openAssetFile() için daha genel bir biçimdir. Dosyaların alt bölümlerini okuyamaz.

İsteğe bağlı olarak openPipeHelper() yöntemini dosya açıklayıcı yönteminizle kullanabilirsiniz. Bu, yapıştırma uygulamasının bir arka plan iş parçacığındaki akış verilerini bir dikey çizgi kullanarak okumasını sağlar. Bu yöntemi kullanmak için ContentProvider.PipeDataWriter arayüzünü uygulayın.

Etkili kopyalama ve yapıştırma işlevleri tasarlayın

Uygulamanız için etkili kopyalama ve yapıştırma işlevleri tasarlamak için şu noktaları göz önünde bulundurun:

  • Panoda herhangi bir zamanda yalnızca bir klip gösterilir. Sistemdeki herhangi bir uygulama tarafından gerçekleştirilen yeni bir kopyalama işlemi önceki klibin üzerine yazılır. Kullanıcı uygulamanızdan ayrılıp geri dönmeden önce kopyalayabileceğinden, panonun, kullanıcının daha önce sizin uygulamanızda kopyaladığı klibi içerdiğini varsayamazsınız.
  • Klip başına birden fazla ClipData.Item nesnesinin amacı, tek bir seçime farklı referans biçimleri yerine birden fazla seçimin kopyalanıp yapıştırılmasını desteklemektir. Genellikle bir klipteki tüm ClipData.Item nesnelerinin aynı biçimde olmasını istersiniz. Yani tümünün basit metin, içerik URI veya Intent olması ve karma olmaması gerekir.
  • Veri sağlarken farklı MIME temsilleri sunabilirsiniz. Desteklediğiniz MIME türlerini ClipDescription öğesine ekleyin, ardından MIME türlerini içerik sağlayıcınıza uygulayın.
  • Panodan veri aldığınızda, kullanılabilir MIME türlerini kontrol etmek ve varsa hangisinin kullanılacağına karar vermek uygulamanızın sorumluluğundadır. Panoda klip olsa bile kullanıcı yapıştırma isteğinde bulunsa bile uygulamanızın bu yapıştırma işlemini yapması gerekmez. MIME türü uyumluysa yapıştırma işlemini yapın. coerceToText() kullanarak panodaki verileri metne dönüştürmeye zorlayabilirsiniz. Uygulamanız mevcut MIME türlerinden birden fazlasını destekliyorsa kullanıcının hangisinin kullanılacağını seçmesine izin verebilirsiniz.