कॉपी करें और चिपकाएं

लिखने की सुविधा आज़माएं
Android के लिए, Jetpack Compose को यूज़र इंटरफ़ेस (यूआई) टूलकिट के तौर पर इस्तेमाल करने का सुझाव दिया जाता है. Compose में कॉपी और पेस्ट करने का तरीका जानें.

Android, कॉपी और चिपकाने के लिए क्लिपबोर्ड पर आधारित एक बेहतरीन फ़्रेमवर्क उपलब्ध कराता है. यह टेक्स्ट स्ट्रिंग, जटिल डेटा स्ट्रक्चर, टेक्स्ट और बाइनरी स्ट्रीम डेटा, और ऐप्लिकेशन ऐसेट जैसे सामान्य और जटिल डेटा टाइप के साथ काम करता है. सादे टेक्स्ट वाले डेटा को सीधे क्लिपबोर्ड में सेव किया जाता है. वहीं, जटिल डेटा को एक रेफ़रंस के तौर पर सेव किया जाता है. चिपकाने वाला ऐप्लिकेशन, कॉन्टेंट उपलब्ध कराने वाली कंपनी की मदद से इस रेफ़रंस को हल करता है. कॉपी करने और चिपकाने की सुविधा, ऐप्लिकेशन में और फ़्रेमवर्क लागू करने वाले ऐप्लिकेशन के बीच काम करती है.

फ़्रेमवर्क का कुछ हिस्सा, कॉन्टेंट उपलब्ध कराने वाली कंपनियों का इस्तेमाल करता है. इसलिए, इस दस्तावेज़ में यह मान लिया गया है कि आपको Android Content Provider API के बारे में कुछ जानकारी है. इसके बारे में कॉन्टेंट उपलब्ध कराने वाली कंपनियां में बताया गया है.

उपयोगकर्ताओं को क्लिपबोर्ड पर कॉन्टेंट कॉपी करने पर, इसकी जानकारी मिलनी चाहिए. इसलिए, कॉपी और चिपकाने की सुविधा देने वाले फ़्रेमवर्क के अलावा, Android 13 (एपीआई लेवल 33) और इसके बाद के वर्शन में, Android उपयोगकर्ताओं को कॉपी करते समय डिफ़ॉल्ट यूज़र इंटरफ़ेस (यूआई) दिखाता है. इस सुविधा की वजह से, डुप्लीकेट सूचना मिलने का खतरा होता है. इस खास मामले के बारे में ज़्यादा जानने के लिए, डुप्लीकेट सूचनाएं भेजने से बचें सेक्शन देखें.

Android 13 में क्लिपबोर्ड की सूचना दिखाने वाला ऐनिमेशन
पहली इमेज. Android 13 और इसके बाद के वर्शन में, क्लिपबोर्ड में कॉन्टेंट सेव होने पर दिखने वाला यूज़र इंटरफ़ेस (यूआई).

Android 12L (एपीआई लेवल 32) और इससे पहले के वर्शन में कॉपी करने पर, उपयोगकर्ताओं को मैन्युअल तरीके से सुझाव/राय दें या शिकायत करें. इस दस्तावेज़ में, इसके लिए सुझाव देखें.

क्लिपबोर्ड फ़्रेमवर्क

क्लिपबोर्ड फ़्रेमवर्क का इस्तेमाल करते समय, डेटा को क्लिप ऑब्जेक्ट में रखें. इसके बाद, क्लिप ऑब्जेक्ट को सिस्टम-वाइड क्लिपबोर्ड पर रखें. क्लिप ऑब्जेक्ट इन तीन में से किसी एक फ़ॉर्म में हो सकता है:

टेक्स्ट
यह एक टेक्स्ट स्ट्रिंग है. स्ट्रिंग को सीधे क्लिप ऑब्जेक्ट में डालें. इसके बाद, इसे क्लिपबोर्ड पर डालें. स्ट्रिंग चिपकाने के लिए, क्लिपबोर्ड से क्लिप ऑब्जेक्ट पाएं और स्ट्रिंग को अपने ऐप्लिकेशन के स्टोरेज में कॉपी करें.
यूआरआई
यह Uri ऑब्जेक्ट, यूआरआई के किसी भी फ़ॉर्म को दिखाता है. इसका इस्तेमाल मुख्य रूप से, कॉन्टेंट उपलब्ध कराने वाली कंपनी से जटिल डेटा कॉपी करने के लिए किया जाता है. डेटा कॉपी करने के लिए, Uri ऑब्जेक्ट को क्लिप ऑब्जेक्ट में रखें. इसके बाद, क्लिप ऑब्जेक्ट को क्लिपबोर्ड पर रखें. डेटा चिपकाने के लिए, क्लिप ऑब्जेक्ट और Uri ऑब्जेक्ट पाएं. इसके बाद, इसे किसी डेटा सोर्स, जैसे कि कॉन्टेंट उपलब्ध कराने वाली कंपनी के लिए हल करें. साथ ही, सोर्स से डेटा को अपने ऐप्लिकेशन के स्टोरेज में कॉपी करें.
इंटेंट
An Intent. यह ऐप्लिकेशन के शॉर्टकट कॉपी करने की सुविधा देता है. डेटा कॉपी करने के लिए, Intent बनाएं. इसके बाद, उसे क्लिप ऑब्जेक्ट में रखें और क्लिप ऑब्जेक्ट को क्लिपबोर्ड पर रखें. डेटा चिपकाने के लिए, क्लिप ऑब्जेक्ट पाएं. इसके बाद, Intent ऑब्जेक्ट को अपने ऐप्लिकेशन की मेमोरी में कॉपी करें.

क्लिपबोर्ड में एक बार में सिर्फ़ एक क्लिप ऑब्जेक्ट सेव किया जा सकता है. जब कोई ऐप्लिकेशन क्लिपबोर्ड पर क्लिप ऑब्जेक्ट रखता है, तो पिछला क्लिप ऑब्जेक्ट गायब हो जाता है.

अगर आपको उपयोगकर्ताओं को अपने ऐप्लिकेशन में डेटा चिपकाने की अनुमति देनी है, तो आपको सभी तरह के डेटा को मैनेज करने की ज़रूरत नहीं है. उपयोगकर्ताओं को क्लिपबोर्ड पर मौजूद डेटा चिपकाने का विकल्प देने से पहले, उसकी जांच की जा सकती है. क्लिप ऑब्जेक्ट में, किसी खास डेटा फ़ॉर्म के अलावा मेटाडेटा भी होता है. इससे आपको पता चलता है कि कौनसे MIME टाइप उपलब्ध हैं. इस मेटाडेटा से, यह तय करने में मदद मिलती है कि आपका ऐप्लिकेशन, क्लिपबोर्ड के डेटा का इस्तेमाल करके कुछ काम की कार्रवाई कर सकता है या नहीं. उदाहरण के लिए, अगर आपके पास ऐसा ऐप्लिकेशन है जो मुख्य रूप से टेक्स्ट को हैंडल करता है, तो हो सकता है कि आपको यूआरआई या इंटेंट वाले क्लिप ऑब्जेक्ट को अनदेखा करना पड़े.

ऐसा भी हो सकता है कि आपको उपयोगकर्ताओं को क्लिपबोर्ड पर मौजूद डेटा के फ़ॉर्म से कोई फ़र्क़ न पड़े और उन्हें टेक्स्ट चिपकाने की अनुमति देनी हो. इसके लिए, क्लिपबोर्ड के डेटा को टेक्स्ट फ़ॉर्मैट में बदलें. इसके बाद, इस टेक्स्ट को चिपकाएं. इसके बारे में, क्लिपबोर्ड को टेक्स्ट में बदलें सेक्शन में बताया गया है.

क्लिपबोर्ड क्लास

इस सेक्शन में, क्लिपबोर्ड फ़्रेमवर्क की ओर से इस्तेमाल की जाने वाली क्लास के बारे में बताया गया है.

ClipboardManager

Android सिस्टम के क्लिपबोर्ड को ग्लोबल ClipboardManager क्लास से दिखाया जाता है. इस क्लास को सीधे तौर पर इंस्टैंशिएट न करें. इसके बजाय, getSystemService(CLIPBOARD_SERVICE) को चालू करके इसका रेफ़रंस पाएं.

ClipData, ClipData.Item, और ClipDescription

क्लिपबोर्ड में डेटा जोड़ने के लिए, एक ClipData ऑब्जेक्ट बनाएं. इसमें डेटा और डेटा की जानकारी शामिल होनी चाहिए. क्लिपबोर्ड में एक बार में सिर्फ़ एक ClipData सेव किया जा सकता है. ClipData में एक ClipDescription ऑब्जेक्ट और एक या उससे ज़्यादा ClipData.Item ऑब्जेक्ट होते हैं.

ClipDescription ऑब्जेक्ट में क्लिप के बारे में मेटाडेटा होता है. खास तौर पर, इसमें क्लिप के डेटा के लिए उपलब्ध MIME टाइप की एक कैटगरी होती है. इसके अलावा, Android 12 (एपीआई लेवल 31) और इसके बाद के वर्शन पर, मेटाडेटा में यह जानकारी शामिल होती है कि ऑब्जेक्ट में स्टाइल वाला टेक्स्ट शामिल है या नहीं. साथ ही, इसमें ऑब्जेक्ट में मौजूद टेक्स्ट के टाइप के बारे में भी जानकारी शामिल होती है. क्लिपबोर्ड पर कोई क्लिप रखने पर, यह जानकारी उन ऐप्लिकेशन के लिए उपलब्ध होती है जिनमें चिपकाने की सुविधा होती है. ये ऐप्लिकेशन यह देख सकते हैं कि वे क्लिप के डेटा को मैनेज कर सकते हैं या नहीं.

ClipData.Item ऑब्जेक्ट में टेक्स्ट, यूआरआई या इंटेंट डेटा होता है:

टेक्स्ट
A CharSequence.
यूआरआई
A Uri. इसमें आम तौर पर, कॉन्टेंट देने वाले का यूआरआई होता है. हालांकि, किसी भी यूआरआई का इस्तेमाल किया जा सकता है. डेटा उपलब्ध कराने वाला ऐप्लिकेशन, यूआरआई को क्लिपबोर्ड पर रखता है. डेटा चिपकाने वाले ऐप्लिकेशन, क्लिपबोर्ड से यूआरआई पाते हैं. इसके बाद, वे इसका इस्तेमाल कॉन्टेंट उपलब्ध कराने वाले या अन्य डेटा सोर्स को ऐक्सेस करने और डेटा पाने के लिए करते हैं.
इंटेंट
An Intent. इस डेटा टाइप की मदद से, ऐप्लिकेशन के शॉर्टकट को क्लिपबोर्ड पर कॉपी किया जा सकता है. इसके बाद, उपयोगकर्ता इस शॉर्टकट को अपने ऐप्लिकेशन में चिपका सकते हैं, ताकि वे इसे बाद में इस्तेमाल कर सकें.

किसी क्लिप में एक से ज़्यादा ClipData.Item ऑब्जेक्ट जोड़े जा सकते हैं. इस सुविधा की मदद से, उपयोगकर्ता एक से ज़्यादा आइटम को एक ही क्लिप के तौर पर कॉपी और चिपका सकते हैं. उदाहरण के लिए, अगर आपके पास कोई सूची वाला ऐसा विजेट है जिसमें उपयोगकर्ता एक बार में एक से ज़्यादा आइटम चुन सकता है, तो सभी आइटम को एक साथ क्लिपबोर्ड पर कॉपी किया जा सकता है. इसके लिए, सूची में मौजूद हर आइटम के लिए एक अलग ClipData.Item बनाएं. इसके बाद, ClipData.Item ऑब्जेक्ट को ClipData ऑब्जेक्ट में जोड़ें.

ClipData के लिए सुविधा देने वाले तरीके

ClipData क्लास, एक ClipData.Item ऑब्जेक्ट और एक सामान्य ClipDescription ऑब्जेक्ट की मदद से ClipData ऑब्जेक्ट बनाने के लिए, स्टैटिक तरीके उपलब्ध कराती है:

newPlainText(label, text)
यह एक ClipData ऑब्जेक्ट दिखाता है. इसके एक ClipData.Item ऑब्जेक्ट में टेक्स्ट स्ट्रिंग होती है. ClipDescription ऑब्जेक्ट का लेबल label पर सेट है. ClipDescription में मौजूद MIME टाइप MIMETYPE_TEXT_PLAIN है.

टेक्स्ट स्ट्रिंग से क्लिप बनाने के लिए, newPlainText() का इस्तेमाल करें.

newUri(resolver, label, URI)
यह एक ClipData ऑब्जेक्ट दिखाता है. इसके ClipData.Item ऑब्जेक्ट में यूआरआई होता है. ClipDescription ऑब्जेक्ट का लेबल label पर सेट है. अगर यूआरआई, कॉन्टेंट यूआरआई है, तो इसका मतलब है कि अगर Uri.getScheme() content: दिखाता है, तो यह तरीका resolver में दिए गए ContentResolver ऑब्जेक्ट का इस्तेमाल करके, कॉन्टेंट प्रोवाइडर से उपलब्ध MIME टाइप को वापस पाने के लिए करता है. इसके बाद, यह उन्हें ClipDescription में सेव करता है. जो यूआरआई content: यूआरआई नहीं है उसके लिए, यह तरीका एमआईएमई टाइप को MIMETYPE_TEXT_URILIST पर सेट करता है.

किसी यूआरआई से क्लिप बनाने के लिए, newUri() का इस्तेमाल करें. खास तौर पर, content: यूआरआई से क्लिप बनाने के लिए.

newIntent(label, intent)
यह एक ClipData ऑब्जेक्ट दिखाता है. इसके ClipData.Item ऑब्जेक्ट में Intent होता है. ClipDescription ऑब्जेक्ट का लेबल label पर सेट है. MIME टाइप को MIMETYPE_TEXT_INTENT पर सेट किया गया है.

Intent ऑब्जेक्ट से क्लिप बनाने के लिए, newIntent() का इस्तेमाल करें.

क्लिपबोर्ड के डेटा को टेक्स्ट में बदलें

अगर आपका ऐप्लिकेशन सिर्फ़ टेक्स्ट को प्रोसेस करता है, तब भी क्लिपबोर्ड से बिना टेक्स्ट वाला डेटा कॉपी किया जा सकता है. इसके लिए, आपको उसे ClipData.Item.coerceToText() तरीके से बदलना होगा.

यह तरीका, ClipData.Item में मौजूद डेटा को टेक्स्ट में बदलता है और CharSequence दिखाता है. ClipData.Item.coerceToText() से मिलने वाली वैल्यू, ClipData.Item में मौजूद डेटा के फ़ॉर्म पर आधारित होती है:

टेक्स्ट
अगर ClipData.Item टेक्स्ट है, तो इसका मतलब है कि अगर getText() शून्य नहीं है, तो coerceToText() टेक्स्ट दिखाता है.
यूआरआई
अगर ClipData.Item एक यूआरआई है, यानी अगर getUri() शून्य नहीं है, तो coerceToText() इसे कॉन्टेंट यूआरआई के तौर पर इस्तेमाल करने की कोशिश करता है.
  • अगर यूआरआई, कॉन्टेंट यूआरआई है और प्रोवाइडर टेक्स्ट स्ट्रीम दिखा सकता है, तो coerceToText() टेक्स्ट स्ट्रीम दिखाता है.
  • अगर यूआरआई, कॉन्टेंट यूआरआई है, लेकिन कॉन्टेंट देने वाला टेक्स्ट स्ट्रीम उपलब्ध नहीं कराता है, तो coerceToText() यूआरआई का प्रतिनिधित्व दिखाता है. यह प्रज़ेंटेशन, Uri.toString() से मिले प्रज़ेंटेशन जैसा ही है.
  • अगर यूआरआई, कॉन्टेंट यूआरआई नहीं है, तो coerceToText() यूआरआई का रिप्रेज़ेंटेशन दिखाता है. यह Uri.toString() से मिले जवाब जैसा ही होता है.
इंटेंट
अगर ClipData.Item एक Intent है, तो coerceToText() इसे Intent URI में बदल देता है और इसे दिखाता है. Intent का मतलब है कि getIntent() शून्य नहीं है. यह Intent.toUri(URI_INTENT_SCHEME) से मिले रिस्पॉन्स जैसा ही होता है.

क्लिपबोर्ड फ़्रेमवर्क के बारे में दूसरी इमेज में बताया गया है. डेटा कॉपी करने के लिए, कोई ऐप्लिकेशन ClipboardManager ग्लोबल क्लिपबोर्ड पर ClipData ऑब्जेक्ट रखता है. ClipData में एक या उससे ज़्यादा ClipData.Item ऑब्जेक्ट और एक ClipDescription ऑब्जेक्ट मौजूद है. डेटा चिपकाने के लिए, कोई ऐप्लिकेशन ClipData को ऐक्सेस करता है. इसके बाद, ClipDescription से इसका MIME टाइप मिलता है. इसके बाद, ClipData.Item या ClipData.Item से रेफ़र किए गए कॉन्टेंट प्रोवाइडर से डेटा मिलता है.

कॉपी और चिपकाने के फ़्रेमवर्क का ब्लॉक डायग्राम दिखाने वाली इमेज
दूसरी इमेज. Android का क्लिपबोर्ड फ़्रेमवर्क.

क्लिपबोर्ड पर कॉपी करें

डेटा को क्लिपबोर्ड पर कॉपी करने के लिए, ग्लोबल ClipboardManager ऑब्जेक्ट का हैंडल पाएं. इसके बाद, ClipData ऑब्जेक्ट बनाएं और उसमें ClipDescription और एक या उससे ज़्यादा ClipData.Item ऑब्जेक्ट जोड़ें. इसके बाद, तैयार किए गए ClipData ऑब्जेक्ट को ClipboardManager ऑब्जेक्ट में जोड़ें. इसके बारे में यहां बताया गया है:

  1. अगर कॉन्टेंट यूआरआई का इस्तेमाल करके डेटा कॉपी किया जा रहा है, तो कॉन्टेंट प्रोवाइडर सेट अप करें.
  2. सिस्टम क्लिपबोर्ड का डेटा पाने के लिए:

    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. डेटा को नए ClipData ऑब्जेक्ट में कॉपी करें:

    • टेक्स्ट के लिए

      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!");
    • किसी यूआरआई के लिए

      यह स्निपेट, रिकॉर्ड आईडी को कॉन्टेंट यूआरआई पर एन्कोड करके, यूआरआई बनाता है. यह यूआरआई, सेवा देने वाली कंपनी के लिए होता है. इस तकनीक के बारे में ज़्यादा जानकारी, यूआरआई पर आइडेंटिफ़ायर को एन्कोड करना सेक्शन में दी गई है.

      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);
    • किसी इंटेंट के लिए

      यह स्निपेट, किसी ऐप्लिकेशन के लिए Intent बनाता है. इसके बाद, इसे क्लिप ऑब्जेक्ट में डालता है:

      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. नए क्लिप ऑब्जेक्ट को क्लिपबोर्ड पर रखें:

    Kotlin

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

    Java

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

क्लिपबोर्ड पर कॉपी करते समय सुझाव/राय देना या शिकायत करना

जब कोई ऐप्लिकेशन, कॉन्टेंट को क्लिपबोर्ड पर कॉपी करता है, तो उपयोगकर्ता को विज़ुअल फ़ीडबैक मिलता है. Android 13 और इसके बाद के वर्शन वाले डिवाइसों पर, यह सुविधा अपने-आप लागू हो जाती है. हालांकि, इससे पहले के वर्शन में इसे मैन्युअल तरीके से लागू करना पड़ता है.

Android 13 से, क्लिपबोर्ड में कॉन्टेंट जोड़े जाने पर, सिस्टम एक स्टैंडर्ड विज़ुअल पुष्टि दिखाता है. पुष्टि करने की नई सुविधा से ये काम किए जा सकते हैं:

  • इस कुकी से पुष्टि होती है कि कॉन्टेंट को कॉपी कर लिया गया है.
  • इससे कॉपी किए गए कॉन्टेंट की झलक मिलती है.

Android 13 में क्लिपबोर्ड की सूचना दिखाने वाला ऐनिमेशन
तीसरी इमेज. Android 13 और इसके बाद के वर्शन में, क्लिपबोर्ड में कॉन्टेंट सेव होने पर दिखने वाला यूज़र इंटरफ़ेस (यूआई).

Android 12L (एपीआई लेवल 32) और इससे पहले के वर्शन में, उपयोगकर्ताओं को यह पता नहीं चल पाता कि उन्होंने कॉन्टेंट कॉपी किया है या नहीं. साथ ही, उन्हें यह भी नहीं पता चलता कि उन्होंने क्या कॉपी किया है. इस सुविधा से, कॉपी करने के बाद ऐप्लिकेशन की ओर से दिखाई जाने वाली अलग-अलग सूचनाओं को स्टैंडर्ड बनाया जाता है. साथ ही, इससे लोगों को क्लिपबोर्ड पर ज़्यादा कंट्रोल मिलता है.

डुप्लीकेट सूचनाएं पाने से बचें

Android 12L (एपीआई लेवल 32) और इससे पहले के वर्शन में, हमारा सुझाव है कि उपयोगकर्ताओं को कॉपी करने की प्रोसेस पूरी होने पर सूचना दें. इसके लिए, उन्हें विज़ुअल और इन-ऐप्लिकेशन फ़ीडबैक दें. साथ ही, कॉपी करने के बाद Toast या Snackbar जैसे विजेट का इस्तेमाल करें.

जानकारी को डुप्लीकेट तरीके से दिखाने से बचने के लिए, हमारा सुझाव है कि Android 13 और इसके बाद के वर्शन के लिए, ऐप्लिकेशन में कॉपी करने के बाद दिखने वाले टॉस्ट या स्नैकबार हटा दें.

इन-ऐप्लिकेशन कॉपी करने के बाद, स्नैकबार पोस्ट करें.
चौथी इमेज. Android 13 में कॉपी की पुष्टि करने वाला स्नैकबार दिखाने पर, उपयोगकर्ता को डुप्लीकेट मैसेज दिखते हैं.
ऐप्लिकेशन में कॉपी करने के बाद, सूचना दिखाएं.
पांचवीं इमेज. Android 13 में कॉपी करने की पुष्टि करने वाला सूचना मैसेज दिखाने पर, उपयोगकर्ता को डुप्लीकेट मैसेज दिखते हैं.

इसे लागू करने का तरीका यहां बताया गया है:

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

क्लिपबोर्ड में संवेदनशील कॉन्टेंट जोड़ना

अगर आपका ऐप्लिकेशन, उपयोगकर्ताओं को पासवर्ड या क्रेडिट कार्ड की जानकारी जैसे संवेदनशील कॉन्टेंट को क्लिपबोर्ड पर कॉपी करने की सुविधा देता है, तो आपको ClipboardManager.setPrimaryClip() को कॉल करने से पहले, ClipData में ClipDescription को जोड़ना होगा. इस फ़्लैग को जोड़ने से, Android 13 और इसके बाद के वर्शन में, कॉपी किए गए कॉन्टेंट की पुष्टि करने के लिए दिखने वाली इमेज में संवेदनशील कॉन्टेंट नहीं दिखता.

संवेदनशील कॉन्टेंट को फ़्लैग किए बिना, कॉपी किए गए टेक्स्ट की झलक
छठी इमेज. संवेदनशील कॉन्टेंट के फ़्लैग के बिना, कॉपी किए गए टेक्स्ट की झलक.
कॉपी किए गए टेक्स्ट की झलक में, संवेदनशील कॉन्टेंट को फ़्लैग किया गया है.
सातवीं इमेज. संवेदनशील कॉन्टेंट के फ़्लैग के साथ, कॉपी किए गए टेक्स्ट की झलक.

संवेदनशील कॉन्टेंट को फ़्लैग करने के लिए, ClipDescription में एक बूलियन एक्स्ट्रा जोड़ें. सभी ऐप्लिकेशन को ऐसा करना होगा. भले ही, टारगेट किया गया एपीआई लेवल कोई भी हो.

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

क्लिपबोर्ड से चिपकाएं

जैसा कि ऊपर बताया गया है, ग्लोबल क्लिपबोर्ड ऑब्जेक्ट और क्लिप ऑब्जेक्ट को पाकर, क्लिपबोर्ड से डेटा चिपकाएं. इसके बाद, क्लिप ऑब्जेक्ट के डेटा को देखें. अगर हो सके, तो क्लिप ऑब्जेक्ट से डेटा को अपने स्टोरेज में कॉपी करें. इस सेक्शन में, क्लिपबोर्ड के डेटा को तीन फ़ॉर्म में चिपकाने का तरीका बताया गया है.

सादा टेक्स्ट चिपकाएं

सामान्य टेक्स्ट चिपकाने के लिए, ग्लोबल क्लिपबोर्ड पाएं और पुष्टि करें कि यह सामान्य टेक्स्ट दिखा सकता है. इसके बाद, क्लिप ऑब्जेक्ट पाएं और getText() का इस्तेमाल करके, उसके टेक्स्ट को अपने स्टोरेज में कॉपी करें. इसके लिए, नीचे दी गई प्रोसेस अपनाएं:

  1. getSystemService(CLIPBOARD_SERVICE) का इस्तेमाल करके, ग्लोबल ClipboardManager ऑब्जेक्ट पाएं. इसके अलावा, चिपकाए गए टेक्स्ट को शामिल करने के लिए, ग्लोबल वैरिएबल का एलान करें:

    Kotlin

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

    Java

    ClipboardManager clipboard = (ClipboardManager) getSystemService(Context.CLIPBOARD_SERVICE);
    String pasteData = "";
  2. इससे यह तय किया जाता है कि मौजूदा गतिविधि में "चिपकाएं" विकल्प को चालू करना है या बंद करना है. पुष्टि करें कि क्लिपबोर्ड में कोई क्लिप मौजूद है और आपके पास क्लिप में मौजूद डेटा को मैनेज करने का अधिकार है:

    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. क्लिपबोर्ड से डेटा कॉपी करें. कोड में इस पॉइंट तक सिर्फ़ तब पहुंचा जा सकता है, जब "paste" मेन्यू आइटम चालू हो. इसलिए, यह माना जा सकता है कि क्लिपबोर्ड में सामान्य टेक्स्ट मौजूद है. आपको अब तक यह नहीं पता कि इसमें कोई टेक्स्ट स्ट्रिंग है या कोई ऐसा यूआरआई है जो सादे टेक्स्ट की ओर ले जाता है. नीचे दिया गया कोड स्निपेट इसकी जांच करता है. हालांकि, इसमें सिर्फ़ सादे टेक्स्ट को मैनेज करने का कोड दिखता है:

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

कॉन्टेंट यूआरआई से डेटा चिपकाना

अगर ClipData.Item ऑब्जेक्ट में कॉन्टेंट यूआरआई मौजूद है और आपको लगता है कि इसके किसी MIME टाइप को मैनेज किया जा सकता है, तो ContentResolver बनाएं. इसके बाद, डेटा वापस पाने के लिए, कॉन्टेंट प्रोवाइडर के सही तरीके को कॉल करें.

यहां दी गई प्रोसेस में बताया गया है कि क्लिपबोर्ड पर मौजूद कॉन्टेंट यूआरआई के आधार पर, कॉन्टेंट उपलब्ध कराने वाली कंपनी से डेटा कैसे पाएं. यह कुकी यह जांच करती है कि ऐप्लिकेशन के लिए, प्रोवाइडर से ऐसा MIME टाइप उपलब्ध है या नहीं जिसका इस्तेमाल किया जा सकता है.

  1. MIME टाइप को शामिल करने के लिए, ग्लोबल वैरिएबल का एलान करें:

    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. ग्लोबल क्लिपबोर्ड पाएं. साथ ही, कॉन्टेंट रिज़ॉल्वर भी पाएं, ताकि कॉन्टेंट उपलब्ध कराने वाले व्यक्ति या कंपनी का कॉन्टेंट ऐक्सेस किया जा सके:

    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. क्लिपबोर्ड से प्राइमरी क्लिप पाएं और उसके कॉन्टेंट को यूआरआई के तौर पर पाएं:

    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) को कॉल करें. अगर Uri किसी मान्य कॉन्टेंट प्रोवाइडर की ओर इशारा नहीं करता है, तो यह तरीका शून्य दिखाता है.

    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. जांच करें कि कॉन्टेंट उपलब्ध कराने वाली कंपनी, ऐसे MIME टाइप का इस्तेमाल करती हो जिसे ऐप्लिकेशन समझता हो. अगर ऐसा होता है, तो डेटा पाने के लिए ContentResolver.query() को कॉल करें. इस फ़ंक्शन की रिटर्न वैल्यू 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();
                 }
             }
         }
    }

कोई इंटेंट चिपकाना

किसी इंटेंट को चिपकाने के लिए, पहले ग्लोबल क्लिपबोर्ड पाएं. ClipData.Item ऑब्जेक्ट की जांच करें, ताकि यह पता चल सके कि इसमें Intent मौजूद है या नहीं. इसके बाद, अपने स्टोरेज में इंटेंट कॉपी करने के लिए, getIntent() को कॉल करें. इस स्निपेट में यह दिखाया गया है:

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

जब आपका ऐप्लिकेशन क्लिपबोर्ड का डेटा ऐक्सेस करता है, तब सिस्टम की सूचना दिखती है

Android 12 (एपीआई लेवल 31) और इसके बाद के वर्शन पर, जब आपका ऐप्लिकेशन getPrimaryClip() को कॉल करता है, तो सिस्टम आम तौर पर एक सूचना दिखाता है. मैसेज में मौजूद टेक्स्ट में यह फ़ॉर्मैट शामिल है:

APP pasted from your clipboard

जब आपका ऐप्लिकेशन इनमें से कोई काम करता है, तो सिस्टम कोई सूचना नहीं दिखाता:

  • आपके ऐप्लिकेशन से ClipData को ऐक्सेस करता है.
  • किसी ऐप्लिकेशन से बार-बार ClipData को ऐक्सेस करता है. यह सूचना सिर्फ़ तब दिखती है, जब आपका ऐप्लिकेशन पहली बार उस ऐप्लिकेशन से डेटा ऐक्सेस करता है.
  • यह क्लिप ऑब्जेक्ट के लिए मेटाडेटा वापस लाता है. जैसे, getPrimaryClip() के बजाय getPrimaryClipDescription() को कॉल करके.

कॉन्टेंट उपलब्ध कराने वाली कंपनियों की सेवाओं का इस्तेमाल करके, जटिल डेटा कॉपी करना

कॉन्टेंट उपलब्ध कराने वाली कंपनियां, डेटाबेस रिकॉर्ड या फ़ाइल स्ट्रीम जैसे जटिल डेटा को कॉपी करने की सुविधा देती हैं. डेटा को कॉपी करने के लिए, कॉन्टेंट यूआरआई को क्लिपबोर्ड पर रखें. इसके बाद, चिपकाने वाले ऐप्लिकेशन को क्लिपबोर्ड से यह यूआरआई मिलता है. इसका इस्तेमाल, डेटाबेस डेटा या फ़ाइल स्ट्रीम डिस्क्रिप्टर को वापस पाने के लिए किया जाता है.

जिस ऐप्लिकेशन में डेटा चिपकाया जा रहा है उसके पास सिर्फ़ आपके डेटा का कॉन्टेंट यूआरआई होता है. इसलिए, उसे यह पता होना चाहिए कि कौनसे डेटा को वापस पाना है. यह जानकारी देने के लिए, यूआरआई पर मौजूद डेटा के लिए आइडेंटिफ़ायर को कोड में बदला जा सकता है. इसके अलावा, एक ऐसा यूनीक यूआरआई भी दिया जा सकता है जो कॉपी किए जाने वाले डेटा को दिखाता हो. आपको कौनसी तकनीक चुननी है, यह आपके डेटा के संगठन पर निर्भर करता है.

यहां दिए गए सेक्शन में, यूआरआई सेट अप करने, जटिल डेटा देने, और फ़ाइल स्ट्रीम देने का तरीका बताया गया है. इन ब्यौरों में यह मान लिया गया है कि आपको कॉन्टेंट उपलब्ध कराने वाले डिज़ाइन के सामान्य सिद्धांतों के बारे में पता है.

यूआरआई पर आइडेंटिफ़ायर को कोड में बदलना

यूआरआई की मदद से डेटा को क्लिपबोर्ड पर कॉपी करने का एक तरीका यह है कि यूआरआई पर मौजूद डेटा के लिए आइडेंटिफ़ायर को एन्कोड किया जाए. इसके बाद, आपका कॉन्टेंट प्रोवाइडर यूआरआई से आइडेंटिफ़ायर पा सकता है और इसका इस्तेमाल करके डेटा वापस पा सकता है. जिस ऐप्लिकेशन में चिपकाया जा रहा है उसे यह जानने की ज़रूरत नहीं है कि आइडेंटिफ़ायर मौजूद है. इसे सिर्फ़ क्लिपबोर्ड से आपका "रेफ़रंस"—यूआरआई और आइडेंटिफ़ायर—लेना होता है. इसके बाद, इसे कॉन्टेंट उपलब्ध कराने वाली कंपनी को देना होता है और डेटा वापस पाना होता है.

आम तौर पर, किसी आइडेंटिफ़ायर को कॉन्टेंट यूआरआई में कोड किया जाता है. इसके लिए, आइडेंटिफ़ायर को यूआरआई के आखिर में जोड़ा जाता है. उदाहरण के लिए, मान लें कि आपने अपने प्रोवाइडर यूआरआई को इस स्ट्रिंग के तौर पर तय किया है:

"content://com.example.contacts"

अगर आपको इस यूआरआई पर कोई नाम एन्कोड करना है, तो इस कोड स्निपेट का इस्तेमाल करें:

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

अगर पहले से ही किसी कॉन्टेंट प्रोवाइडर का इस्तेमाल किया जा रहा है, तो हो सकता है कि आपको एक नया यूआरआई पाथ जोड़ना पड़े. इससे पता चलता है कि यूआरआई को कॉपी करने के लिए है. उदाहरण के लिए, मान लें कि आपके पास पहले से ही ये यूआरआई पाथ हैं:

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

यूआरआई कॉपी करने के लिए, कोई दूसरा पाथ जोड़ा जा सकता है:

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

इसके बाद, पैटर्न मैचिंग की मदद से "कॉपी" यूआरआई का पता लगाया जा सकता है. साथ ही, इसे कॉपी और चिपकाने के लिए खास तौर पर बनाए गए कोड की मदद से हैंडल किया जा सकता है.

डेटा को व्यवस्थित करने के लिए, कॉन्टेंट उपलब्ध कराने वाली कंपनी, इंटरनल डेटाबेस या इंटरनल टेबल का इस्तेमाल करने पर, आम तौर पर एन्कोडिंग तकनीक का इस्तेमाल किया जाता है. इन मामलों में, आपके पास कॉपी करने के लिए कई तरह का डेटा होता है. साथ ही, हर डेटा के लिए एक यूनीक आइडेंटिफ़ायर होता है. डेटा चिपकाने वाले ऐप्लिकेशन की क्वेरी के जवाब में, डेटा को उसके आइडेंटिफ़ायर के हिसाब से खोजा जा सकता है और उसे वापस भेजा जा सकता है.

अगर आपके पास एक से ज़्यादा डेटा नहीं है, तो शायद आपको आइडेंटिफ़ायर को कोड में बदलने की ज़रूरत नहीं है. आपके पास ऐसा यूआरआई इस्तेमाल करने का विकल्प होता है जो आपके प्रोवाइडर के लिए यूनीक हो. क्वेरी के जवाब में, सेवा देने वाली कंपनी वह डेटा दिखाती है जो उसके पास मौजूद है.

डेटा स्ट्रक्चर कॉपी करना

कॉपी करने और चिपकाने के लिए, कॉन्टेंट उपलब्ध कराने वाली कंपनी को सेट अप करें. यह ContentProvider कॉम्पोनेंट की सबक्लास के तौर पर काम करती है. क्लिपबोर्ड पर मौजूद यूआरआई को इस तरह से कोड में बदलें कि वह उस रिकॉर्ड की ओर इशारा करे जिसे आपको उपलब्ध कराना है. इसके अलावा, अपने आवेदन की मौजूदा स्थिति पर भी ध्यान दें:

  • अगर आपके पास पहले से ही कोई कॉन्टेंट प्रोवाइडर है, तो उसकी सुविधाओं को बढ़ाया जा सकता है. आपको सिर्फ़ query() तरीके में बदलाव करने की ज़रूरत पड़ सकती है, ताकि उन ऐप्लिकेशन से आने वाले यूआरआई को हैंडल किया जा सके जो डेटा चिपकाना चाहते हैं. आपको शायद "कॉपी" यूआरआई पैटर्न को हैंडल करने के तरीके में बदलाव करना होगा.
  • अगर आपका ऐप्लिकेशन इंटरनल डेटाबेस बनाए रखता है, तो आपको इस डेटाबेस को कॉन्टेंट प्रोवाइडर में ट्रांसफ़र करना पड़ सकता है, ताकि इससे कॉपी करना आसान हो.
  • अगर डेटाबेस का इस्तेमाल नहीं किया जा रहा है, तो एक सामान्य कॉन्टेंट प्रोवाइडर लागू किया जा सकता है. इसका मकसद सिर्फ़ उन ऐप्लिकेशन को डेटा उपलब्ध कराना है जो क्लिपबोर्ड से डेटा चिपका रहे हैं.

कॉन्टेंट देने वाली कंपनी के तौर पर, कम से कम इन तरीकों को बदलें:

query()
पेस्ट करने वाले ऐप्लिकेशन यह मान लेते हैं कि वे इस तरीके का इस्तेमाल करके, आपका डेटा पा सकते हैं. इसके लिए, वे उस यूआरआई का इस्तेमाल करते हैं जिसे आपने क्लिपबोर्ड पर रखा है. कॉपी करने की सुविधा के लिए, इस तरीके से ऐसे यूआरआई का पता लगाएं जिनमें "copy" पाथ शामिल हो. इसके बाद, आपका ऐप्लिकेशन क्लिपबोर्ड पर रखने के लिए, "कॉपी" यूआरआई बना सकता है. इसमें कॉपी पाथ और उस रिकॉर्ड का पॉइंटर होता है जिसे आपको कॉपी करना है.
getType()
इस तरीके से, आपको उस डेटा के लिए MIME टाइप दिखाने होंगे जिसे कॉपी करना है. newUri() वाला तरीका, getType() को कॉल करता है, ताकि MIME टाइप को नए ClipData ऑब्जेक्ट में डाला जा सके.

कॉम्प्लेक्स डेटा के लिए एमआईएमई टाइप के बारे में कॉन्टेंट उपलब्ध कराने वाली कंपनियां में बताया गया है.

आपको कॉन्टेंट उपलब्ध कराने वाले किसी अन्य तरीके का इस्तेमाल करने की ज़रूरत नहीं है. जैसे, insert() या update(). पेस्ट करने वाले ऐप्लिकेशन को सिर्फ़ आपके साथ काम करने वाले एमआईएमई टाइप पाने और आपके प्रोवाइडर से डेटा कॉपी करने की ज़रूरत होती है. अगर आपके पास पहले से ही ये तरीके हैं, तो ये कॉपी करने की कार्रवाइयों में कोई रुकावट नहीं डालेंगे.

यहां दिए गए स्निपेट में, मुश्किल डेटा को कॉपी करने के लिए अपने ऐप्लिकेशन को सेट अप करने का तरीका बताया गया है:

  1. अपने ऐप्लिकेशन के ग्लोबल कॉन्स्टेंट में, एक बेस यूआरआई स्ट्रिंग और एक ऐसा पाथ तय करें जो डेटा कॉपी करने के लिए इस्तेमाल की जा रही यूआरआई स्ट्रिंग की पहचान करता हो. कॉपी किए गए डेटा के लिए, MIME टाइप भी तय करें.

    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. जिस गतिविधि से उपयोगकर्ता डेटा कॉपी करते हैं उसमें, क्लिपबोर्ड पर डेटा कॉपी करने के लिए कोड सेट अप करें. कॉपी करने के अनुरोध के जवाब में, यूआरआई को क्लिपबोर्ड पर रखें.

    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. कॉन्टेंट उपलब्ध कराने वाली कंपनी के तौर पर, अपने ग्लोबल स्कोप में यूआरआई मैच करने वाला टूल बनाएं. इसके बाद, ऐसा यूआरआई पैटर्न जोड़ें जो क्लिपबोर्ड पर मौजूद यूआरआई से मेल खाता हो.

    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() तरीका सेट अप करें. इस तरीके से अलग-अलग यूआरआई पैटर्न को हैंडल किया जा सकता है. हालांकि, यह इस बात पर निर्भर करता है कि आपने इसे कैसे कोड किया है. इसमें सिर्फ़ क्लिपबोर्ड पर कॉपी करने की कार्रवाई का पैटर्न दिखता है.

    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. कॉपी किए गए डेटा के लिए सही MIME टाइप दिखाने के लिए, getType() तरीका सेट अप करें:

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

कॉन्टेंट यूआरआई से डेटा चिपकाएं सेक्शन में बताया गया है कि क्लिपबोर्ड से कॉन्टेंट यूआरआई कैसे पाएं. साथ ही, इसका इस्तेमाल करके डेटा को कैसे पाएं और चिपकाएं.

डेटा स्ट्रीम कॉपी करना

स्ट्रीम के तौर पर, ज़्यादा टेक्स्ट और बाइनरी डेटा को कॉपी करके चिपकाया जा सकता है. डेटा इस तरह का हो सकता है:

  • असली डिवाइस पर सेव की गई फ़ाइलें
  • सॉकेट से स्ट्रीम की गई जानकारी
  • किसी प्रोवाइडर के डेटाबेस सिस्टम में बड़ी मात्रा में डेटा सेव किया गया हो

डेटा स्ट्रीम के लिए कॉन्टेंट उपलब्ध कराने वाली कंपनी, अपने डेटा का ऐक्सेस फ़ाइल डिस्क्रिप्टर ऑब्जेक्ट के साथ देती है. जैसे, AssetFileDescriptor, न कि Cursor ऑब्जेक्ट के साथ. डेटा चिपकाने वाला ऐप्लिकेशन, इस फ़ाइल डिस्क्रिप्टर का इस्तेमाल करके डेटा स्ट्रीम को पढ़ता है.

डेटा स्ट्रीम को कॉपी करने के लिए, अपने ऐप्लिकेशन को सेट अप करने के लिए यह तरीका अपनाएं:

  1. आपको जिस डेटा स्ट्रीम को क्लिपबोर्ड पर रखना है उसके लिए कॉन्टेंट यूआरआई सेट अप करें. इसके लिए, आपके पास ये विकल्प उपलब्ध होंगे:
    • यूआरआई पर डेटा स्ट्रीम के लिए आइडेंटिफ़ायर को एन्कोड करें. इसके बारे में यूआरआई पर आइडेंटिफ़ायर को एन्कोड करना सेक्शन में बताया गया है. इसके बाद, अपने प्रोवाइडर के खाते में एक टेबल बनाए रखें. इसमें आइडेंटिफ़ायर और उससे जुड़ा स्ट्रीम का नाम शामिल हो.
    • स्ट्रीम के नाम को सीधे यूआरआई पर कोड में बदलें.
    • ऐसे यूनीक यूआरआई का इस्तेमाल करें जो हमेशा सेवा देने वाली कंपनी से मौजूदा स्ट्रीम दिखाता हो. इस विकल्प का इस्तेमाल करने पर, यह याद रखें कि जब भी यूआरआई का इस्तेमाल करके स्ट्रीम को क्लिपबोर्ड पर कॉपी किया जाए, तब अपने प्रोवाइडर को अपडेट करके किसी दूसरी स्ट्रीम पर पॉइंट करें.
  2. आपको जिस तरह की डेटा स्ट्रीम उपलब्ध करानी है उसके लिए, MIME टाइप दें. पेस्ट करने वाले ऐप्लिकेशन को इस जानकारी की ज़रूरत होती है, ताकि यह तय किया जा सके कि वे क्लिपबोर्ड पर मौजूद डेटा को पेस्ट कर सकते हैं या नहीं.
  3. ContentProvider के किसी ऐसे तरीके को लागू करें जो स्ट्रीम के लिए फ़ाइल डिस्क्रिप्टर दिखाता हो. अगर आपने कॉन्टेंट यूआरआई पर आइडेंटिफ़ायर को कोड में बदला है, तो इस तरीके का इस्तेमाल करके यह तय करें कि कौनसी स्ट्रीम खोलनी है.
  4. डेटा स्ट्रीम को क्लिपबोर्ड पर कॉपी करने के लिए, कॉन्टेंट यूआरआई बनाएं और उसे क्लिपबोर्ड पर रखें.

किसी डेटा स्ट्रीम को चिपकाने के लिए, ऐप्लिकेशन क्लिपबोर्ड से क्लिप को पाता है, यूआरआई पाता है, और इसका इस्तेमाल ContentResolver फ़ाइल डिस्क्रिप्टर के उस तरीके में करता है जो स्ट्रीम को खोलता है. ContentResolver तरीका, इससे जुड़े ContentProvider तरीके को कॉल करता है और उसे कॉन्टेंट यूआरआई पास करता है. आपका प्रोवाइडर, फ़ाइल डिस्क्रिप्टर को ContentResolver तरीके पर वापस भेजता है. इसके बाद, डेटा को स्ट्रीम से पढ़ने की ज़िम्मेदारी, डेटा चिपकाने वाले ऐप्लिकेशन की होती है.

यहां दी गई सूची में, कॉन्टेंट प्रोवाइडर के लिए सबसे ज़रूरी फ़ाइल डिस्क्रिप्टर के तरीके दिखाए गए हैं. इनमें से हर एक के लिए, ContentResolver तरीका उपलब्ध है. इस तरीके के नाम में "Descriptor" स्ट्रिंग जोड़ी जाती है. उदाहरण के लिए, ContentResolver का ऐनलॉग openAssetFile() है और openAssetFile() का ऐनलॉग openAssetFileDescriptor() है.

openTypedAssetFile()

यह तरीका, ऐसेट फ़ाइल डिस्क्रिप्टर दिखाता है. हालांकि, ऐसा सिर्फ़ तब होता है, जब दिया गया एमआईएमई टाइप, सेवा देने वाली कंपनी के साथ काम करता हो. कॉल करने वाला ऐप्लिकेशन, चिपकाने के लिए एमआईएमई टाइप पैटर्न देता है. यूआरआई को क्लिपबोर्ड पर कॉपी करने वाले ऐप्लिकेशन का कॉन्टेंट देने वाला व्यक्ति, AssetFileDescriptor फ़ाइल हैंडल दिखाता है. ऐसा तब होता है, जब वह उस MIME टाइप को उपलब्ध करा सकता है. अगर वह ऐसा नहीं कर पाता है, तो एक अपवाद दिखाता है.

यह तरीका, फ़ाइलों के सब-सेक्शन को मैनेज करता है. इसका इस्तेमाल, कॉन्टेंट उपलब्ध कराने वाली कंपनी की ओर से क्लिपबोर्ड पर कॉपी की गई ऐसेट को पढ़ने के लिए किया जा सकता है.

openAssetFile()
यह तरीका, openTypedAssetFile() का ज़्यादा सामान्य रूप है. यह अनुमति वाले MIME टाइप के लिए फ़िल्टर नहीं करता है, लेकिन यह फ़ाइलों के उप-अनुभागों को पढ़ सकता है.
openFile()
यह openAssetFile() का ज़्यादा सामान्य रूप है. यह फ़ाइलों के सब-सेक्शन नहीं पढ़ सकता.

आपके पास फ़ाइल डिस्क्रिप्टर के साथ openPipeHelper() तरीके का इस्तेमाल करने का विकल्प होता है. इससे, पाइप का इस्तेमाल करके बैकग्राउंड थ्रेड में स्ट्रीम डेटा को पढ़ने की अनुमति मिलती है. इस तरीके का इस्तेमाल करने के लिए, ContentProvider.PipeDataWriter इंटरफ़ेस लागू करें.

कॉपी करने और चिपकाने की सुविधा को असरदार तरीके से डिज़ाइन करना

अपने ऐप्लिकेशन के लिए कॉपी और पेस्ट करने की सुविधा को असरदार तरीके से डिज़ाइन करने के लिए, इन बातों का ध्यान रखें:

  • क्लिपबोर्ड पर एक बार में सिर्फ़ एक क्लिप होती है. सिस्टम में मौजूद किसी भी ऐप्लिकेशन के ज़रिए कॉपी की गई नई क्लिप, पिछली क्लिप की जगह ले लेती है. ऐसा हो सकता है कि उपयोगकर्ता आपके ऐप्लिकेशन से बाहर चला जाए और वापस आने से पहले क्लिपबोर्ड पर मौजूद कॉन्टेंट को कॉपी कर ले. इसलिए, यह नहीं माना जा सकता कि क्लिपबोर्ड में वही क्लिप मौजूद है जिसे उपयोगकर्ता ने आपके ऐप्लिकेशन में पहले कॉपी किया था.
  • हर क्लिप में एक से ज़्यादा ClipData.Item ऑब्जेक्ट जोड़ने का मकसद, एक ही ऑब्जेक्ट के अलग-अलग फ़ॉर्म के बजाय, एक से ज़्यादा ऑब्जेक्ट को कॉपी और चिपकाने की सुविधा देना है. आम तौर पर, आपको क्लिप में मौजूद सभी ClipData.Item ऑब्जेक्ट एक ही तरह के चाहिए होते हैं. इसका मतलब है कि वे सभी, सामान्य टेक्स्ट, कॉन्टेंट यूआरआई या Intent होने चाहिए. इन्हें मिक्स नहीं किया जाना चाहिए.
  • डेटा देते समय, अलग-अलग MIME फ़ॉर्मैट में डेटा दिया जा सकता है. ClipDescription में वे MIME टाइप जोड़ें जिनके साथ आपका ऐप्लिकेशन काम करता है. इसके बाद, अपने कॉन्टेंट प्रोवाइडर में उन MIME टाइप को लागू करें.
  • क्लिपबोर्ड से डेटा पाने पर, आपका ऐप्लिकेशन उपलब्ध MIME टाइप की जांच करने के लिए ज़िम्मेदार होता है. इसके बाद, वह यह तय करता है कि इनमें से किस MIME टाइप का इस्तेमाल करना है. अगर क्लिपबोर्ड पर कोई क्लिप मौजूद है और उपयोगकर्ता उसे चिपकाने का अनुरोध करता है, तो आपके ऐप्लिकेशन को उसे चिपकाने की ज़रूरत नहीं है. अगर MIME टाइप काम करता है, तो उसे चिपकाएं. क्लिपबोर्ड पर मौजूद डेटा को टेक्स्ट में बदलने के लिए, coerceToText() का इस्तेमाल किया जा सकता है. अगर आपका ऐप्लिकेशन, उपलब्ध MIME टाइप में से एक से ज़्यादा टाइप के साथ काम करता है, तो उपयोगकर्ता को यह चुनने का विकल्प दिया जा सकता है कि उसे कौनसा टाइप इस्तेमाल करना है.