النسخ واللصق

يوفّر Android إطار عمل فعّالاً ومستندًا إلى الحافظة للنسخ واللصق. إنه يدعم البساطة وأنواع البيانات المعقدة، بما في ذلك السلاسل النصية وهياكل البيانات المعقدة والنص والتدفق الثنائي والبيانات وأصول التطبيقات. يتم تخزين البيانات النصية البسيطة مباشرة في الحافظة، في حين أنها تكون معقدة تخزين البيانات كمرجع يقوم تطبيق اللصق بحله مع موفّر المحتوى. جارٍ النسخ واللصق داخل التطبيق وبين التطبيقات التي تنفّذ إطار العمل.

ونظرًا لأن جزءًا من إطار العمل يستخدم موفري المحتوى، فإن هذا المستند يفترض بعض الإلمام واجهة برمجة التطبيقات لـ Android Content Provider API الموضحة في موفّرو المحتوى:

يتوقع المستخدمون الحصول على ملاحظات عند نسخ المحتوى إلى الحافظة، لذلك بالإضافة إلى إطار العمل يتيح النسخ واللصق، ويعرض Android واجهة مستخدم تلقائية للمستخدمين عند النسخ في Android 13 (المستوى 33 من واجهة برمجة التطبيقات) وأعلى. وبسبب هذه الميزة، هناك خطر تكرار إشعار. يمكنك معرفة المزيد حول هذه الحالة الهامشية في تجنُّب الإشعارات المكرَّرة .

صورة متحركة تعرض إشعار حافظة Android 13
الشكل 1. واجهة مستخدم تظهر عندما يدخل محتوى إلى الحافظة في نظام Android 13 عامًا وأكثر.

يمكنك تقديم ملاحظات يدويًا للمستخدمين عند نسخ البيانات في Android 12L (المستوى 32 لواجهة برمجة التطبيقات) والإصدارات الأقدم. عرض توصيات لهذا الغرض في هذا المستند.

إطار عمل الحافظة

عند استخدام إطار عمل الحافظة، ضع البيانات في كائن مقطع، ثم ضع كائن المقطع على الحافظة على مستوى النظام يمكن أن يتخذ كائن المقطع أحد الأشكال الثلاثة التالية:

نص
سلسلة نصية. ضع السلسلة مباشرةً في كائن المقطع، الذي تضعه بعد ذلك على الحافظة. للصق السلسلة، احصل على كائن المقطع من الحافظة وانسخ سلسلة إلى تخزين التطبيق.
URI
كائن Uri يمثل أي عنوان URI. الهدف الأساسي هو نسخ البيانات المعقدة من موفّر المحتوى. للنسخ ثم ضع كائن Uri في كائن مقطع ثم ضع كائن المقطع على الحافظة. للصق البيانات، احصل على كائن المقطع، واحصل على كائن Uri، وحلها إلى مصدر بيانات، مثل مقدم محتوى، ونسخ البيانات من المصدر إلى مساحة تخزين التطبيق.
النيّة بالشراء
إنّ Intent هذا النمط نسخ اختصارات التطبيقات. لنسخ البيانات، يمكنك إنشاء Intent ووضع في كائن مقطع ووضع كائن المقطع إلى الحافظة. للصق البيانات، احصل على كائن المقطع، ثم انسخ العنصر Intent إلى ملف منطقة الذاكرة.

تحتوي الحافظة على كائن مقطع واحد فقط في كل مرة. عندما يضع تطبيق كائن مقطع على الحافظة، يختفي كائن المقطع السابق.

إذا كنت تريد السماح للمستخدمين بلصق البيانات في تطبيقك، فلن تضطر إلى التعامل مع جميع أنواع البيانات. يمكنك فحص البيانات في الحافظة قبل منح المستخدمين خيار لصقها. وبالإضافة إلى توفُّر نموذج بيانات معيّن، يحتوي عنصر المقطع أيضًا على بيانات وصفية تخبرك بنوع MIME أنواعها. تساعدك هذه البيانات الوصفية في تحديد ما إذا كان بإمكان تطبيقك تنفيذ إجراء مفيد. مع بيانات الحافظة. فعلى سبيل المثال، إذا كان لديك تطبيق يعالج النصوص بشكل أساسي، تجاهل كائنات المقطع التي تحتوي على معرف موارد منتظم (URI) أو هدف.

قد ترغب أيضًا في السماح للمستخدمين بلصق النص بغض النظر عن شكل البيانات في الحافظة. إلى ثم فرض بيانات الحافظة في تمثيل نصي، ثم لصق هذا النص. هذا هو كما هو موضَّح في القسم فرض تحويل الحافظة إلى نص.

فئات الحافظة

يصف هذا القسم الفئات التي يستخدمها إطار عمل الحافظة.

مدير الحافظة

يتم تمثيل حافظة نظام Android بواسطة العلامة صف واحد (ClipboardManager). لا تنشئ مثيلاً لهذا الصف مباشرةً. بدلاً من ذلك، يمكنك الإشارة إليها عن طريق الاستدعاء getSystemService(CLIPBOARD_SERVICE)

ClipData وClipData.Item وClipDescription

لإضافة بيانات إلى الحافظة، قم بإنشاء عنصر ClipData يحتوي على وصف للبيانات والبيانات نفسها. تحتفظ الحافظة بواحد من ClipData في الوقت. يحتوي عنصر ClipData على عنصر واحد (ClipDescription) وواحد أو أكثر ClipData.Item عناصر

يحتوي عنصر ClipDescription على بيانات وصفية حول المقطع. وعلى وجه الخصوص، يحتوي على مصفوفة من أنواع MIME المتاحة لبيانات المقطع. بالإضافة إلى ذلك، في في نظام التشغيل Android 12 (المستوى 31 لواجهة برمجة التطبيقات) والإصدارات الأحدث، تتضمن البيانات الوصفية معلومات حول ما إذا كان العنصر يحتوي على بنمط معيّن وحول نوع النص في العنصر. عندما تضع مقطعًا في الحافظة، تتوفر هذه المعلومات للصق التطبيقات، التي فحص ما إذا كان بإمكانهم معالجة بيانات المقاطع.

يحتوي عنصر ClipData.Item على النص أو معرّف الموارد المنتظم (URI) أو بيانات الهدف:

نص
CharSequence.
URI
Uri. يشتمل هذا عادةً على معرف موارد منتظم (URI) لموفر المحتوى، على الرغم من أن أي معرف موارد منتظم (URI) هو مسموح به. يضع التطبيق الذي يوفر البيانات معرف الموارد المنتظم (URI) في الحافظة. الطلبات تريد لصق البيانات، تحصل على معرف الموارد المنتظم (URI) من الحافظة وتستخدمه للوصول إلى المحتوى أو مصدر بيانات آخر واسترداد البيانات.
النيّة بالشراء
إنّ Intent يتيح لك هذا النوع من البيانات نسخ اختصار تطبيق إلى الحافظة. ويمكن للمستخدمين بعد ذلك لصق الاختصار في تطبيقاتهم لاستخدامه لاحقًا.

يمكنك إضافة أكثر من عنصر ClipData.Item واحد إلى المقطع. يتيح هذا للمستخدمين نسخ ولصق تحديدات متعددة كمقطع واحد. على سبيل المثال، إذا كان لديك أداة قائمة تتيح المستخدم تحديد أكثر من عنصر في وقت واحد، يمكنك نسخ جميع العناصر إلى الحافظة مرة واحدة. للقيام بذلك، أنشئ عنصرًا ClipData.Item منفصلاً لكل عنصر في القائمة، ثم أضِف السمة ClipData.Item من الكائنات إلى الكائن ClipData.

طرق ملاءمة ClipData

توفّر الفئة ClipData طرقًا ملائمة ثابتة لإنشاء كائن ClipData يحتوي على كائن ClipData.Item واحد وبسيط كائن ClipDescription:

newPlainText(label, text)
عرض كائن ClipData الذي يتضمن كائن ClipData.Item المفرد يحتوي على سلسلة نصية. تم ضبط تصنيف الكائن ClipDescription على label إنّ نوع MIME الوحيد في ClipDescription هو MIMETYPE_TEXT_PLAIN

استخدِم newPlainText() لإنشاء مقطع من سلسلة نصية.

newUri(resolver, label, URI)
عرض كائن ClipData الذي يتضمن كائن ClipData.Item المفرد يحتوي على معرف موارد منتظم (URI). تم ضبط تصنيف الكائن ClipDescription على label إذا كان معرف الموارد المنتظم (URI) هو عنوان URI للمحتوى - أي إذا Uri.getScheme() تُرجع content: - تستخدم الطريقة ContentResolver المحدد في resolver لاسترداد أنواع MIME المتاحة من المحتوى. وبعد ذلك، يتم تخزينها في ClipDescription. بالنسبة إلى معرف الموارد المنتظم (URI) الذي ليس معرّف موارد منتظم (URI) لـ content:، تضبط الطريقة نوع MIME MIMETYPE_TEXT_URILIST

يمكنك استخدام newUri() لإنشاء مقطع من عنوان URI، خاصةً معرّف الموارد المنتظم (URI) لـ content:.

newIntent(label, intent)
عرض كائن ClipData الذي يتضمن كائن ClipData.Item المفرد يحتوي على Intent. تم ضبط تصنيف الكائن ClipDescription على label تم ضبط نوع MIME على MIMETYPE_TEXT_INTENT

استخدِم newIntent() لإنشاء مقطع من عنصر Intent.

إرسال بيانات الحافظة إلى نص

حتى إذا كان تطبيقك يعالج النصوص فقط، يمكنك نسخ البيانات غير النصية من الحافظة عن طريق وتحويله باستخدام ClipData.Item.coerceToText() .

تُحوِّل هذه الطريقة البيانات في ClipData.Item إلى نص وتعرض CharSequence تستند القيمة التي تعرضها الدالة ClipData.Item.coerceToText() إلى على شكل بيانات في ClipData.Item:

نص
إذا كان ClipData.Item نصًا - أي، إذا getText() ليست خالية — تُرجع coerceToText() النص.
URI
إذا كان ClipData.Item هو عنوان URL، أي إذا كان getUri() ليس فارغًا - يحاول coerceToText() استخدامه كمعرّف الموارد المنتظم (URI) للمحتوى.
  • إذا كان معرف الموارد المنتظم (URI) هو معرف موارد منتظم (URI) للمحتوى وكان بإمكان الموفر عرض بث نصي، تعرض coerceToText() سلسلة محادثات نصية.
  • إذا كان معرف الموارد المنتظم (URI) هو معرف موارد منتظم (URI) للمحتوى ولكن الموفر لا يوفر تدفقًا نصيًا، تعرض الدالة coerceToText() تمثيلاً لمعرّف الموارد المنتظم (URI). التمثيل نفسها التي تم إرجاعها بواسطة Uri.toString()
  • إذا لم يكن معرّف الموارد المنتظم (URI) هو معرّف موارد منتظم (URI) للمحتوى، ستعرض coerceToText() تمثيلاً عنوان URI. التمثيل هو نفسه الذي تم عرضه بواسطة Uri.toString()
النيّة بالشراء
إذا كانت قيمة ClipData.Item هي Intent، أي إذا getIntent() ليست قيمة خالية - تحوِّلها coerceToText() إلى معرّف موارد منتظم (URI) للقصد وتعرضه. التمثيل هو نفسه الذي تم عرضه بواسطة Intent.toUri(URI_INTENT_SCHEME)

يتم تلخيص إطار عمل الحافظة في الشكل 2. لنسخ البيانات، يضع التطبيق الكائن ClipData في الحافظة العامة ClipboardManager. تشير رسالة الأشكال البيانية يحتوي ClipData على عنصر أو أكثر من عناصر ClipData.Item وعنصر واحد كائن ClipDescription. للصق البيانات، يحصل التطبيق على ClipData، تحصل على نوع MIME من ClipDescription، ثم تحصل على البيانات من ClipData.Item أو من موفّر المحتوى المشار إليه بواسطة ClipData.Item

صورة تعرض رسمًا بيانيًا كتليًا لإطار عمل النسخ واللصق
الشكل 2. إطار عمل حافظة Android

نسخ إلى الحافظة

لنسخ البيانات إلى الحافظة، احصل على اسم معرِّف للكائن ClipboardManager العام، إنشاء كائن ClipData وإضافة ClipDescription وعنصر واحد أو أكثر اعتراض ClipData.Item. أضِف بعد ذلك الكائن ClipData النهائي إلى كائن ClipboardManager. يتم توضيح ذلك أكثر في الإجراء التالي:

  1. إذا كنت تنسخ البيانات باستخدام معرف موارد منتظم (URI) للمحتوى، فأعد موفّر المحتوى.
  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!");
      
    • بالنسبة إلى معرِّف الموارد المنتظم (URI)

      ينشئ هذا المقتطف معرف موارد منتظم (URI) من خلال ترميز معرف السجل على معرف الموارد المنتظم (URI) للمحتوى المزود. يتم تناول هذه التقنية بمزيد من التفصيل في ترميز معرِّف في قسم URI.

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

تقديم ملاحظات عند النسخ إلى الحافظة

يتوقع المستخدمون ملاحظات مرئية عندما ينسخ التطبيق المحتوى إلى الحافظة. تم تلقائيًا لمستخدمي الإصدار 13 من نظام التشغيل Android والإصدارات الأحدث، ولكن يجب تنفيذها يدويًا في السابق مماثلة.

بدءًا من Android 13، يعرض النظام تأكيدًا مرئيًا عاديًا عند إضافة المحتوى. إلى الحافظة. يؤدي التأكيد الجديد إلى ما يلي:

  • للتأكُّد من نسخ المحتوى بنجاح.
  • يتيح هذا الخيار معاينة المحتوى الذي تم نسخه.

صورة متحركة تعرض إشعار حافظة Android 13
الشكل 3. واجهة مستخدم تظهر عندما يدخل محتوى إلى الحافظة في نظام Android 13 عامًا وأكثر.

في Android 12L (المستوى 32 لواجهة برمجة التطبيقات) والإصدارات الأقدم، قد لا يكون المستخدمون متأكدين مما إذا تم نسخهم بنجاح أم لا. المحتوى أو ما تم نسخه. تعمل هذه الميزة على توحيد الإشعارات المختلفة التي تعرضها التطبيقات بعد النسخ ويوفر للمستخدمين مزيدًا من التحكم في الحافظة.

تجنُّب الإشعارات المكرَّرة

في Android 12L (المستوى 32 لواجهة برمجة التطبيقات) والإصدارات الأقدم، ننصح بتنبيه المستخدمين عند تنفيذ عملية النسخ بنجاح. من خلال إصدار ملاحظات مرئية داخل التطبيق باستخدام تطبيق مصغّر، مثل Toast أو Snackbar، بعد النسخ.

لتجنُّب عرض المعلومات بشكل متكرر، ننصحك بشدة بإزالة الإشعارات المحمصة. أو أشرطة الوجبات الخفيفة التي تظهر بعد نسخة داخل التطبيق لنظام التشغيل Android 13 والإصدارات الأحدث.

نشر شريط الإعلام المنبثق بعد نسخة داخل التطبيق
الشكل 4. إذا كنت تعرض شريط إعلام منبثق لتأكيد نسخ البيانات في نظام التشغيل Android 13 ظهور رسائل مكرّرة للمستخدم.
نشر إشعار منبثق بعد إنشاء نسخة داخل التطبيق
الشكل 5. إذا ظهرت رسالة التأكيد الخاصة بنسخة في 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()
}

إضافة محتوى حسّاس إلى الحافظة

إذا كان تطبيقك يسمح للمستخدمين بنسخ المحتوى الحسّاس إلى الحافظة، مثل كلمات المرور أو بيانات الرصيد. معلومات البطاقة، يجب إضافة علامة إلى ClipDescription في ClipData قبل الاتصال بـ ClipboardManager.setPrimaryClip(). ستؤدي إضافة هذه العلامة إلى منع الحساسية ظهور محتوى معيّن في رسالة التأكيد المرئية للمحتوى المنسوخ في الإصدار 13 من نظام التشغيل Android والإصدارات الأحدث.

تم نسخ معاينة النص بدون الإبلاغ عن المحتوى الحسّاس.
الشكل 6. تم نسخ معاينة النص بدون علامة على المحتوى الحسّاس.
تم نسخ معاينة النص للإبلاغ عن المحتوى الحسّاس.
الشكل 7. تم نسخ معاينة النص الذي يتضمّن علامة محتوى حسّاس.

للإبلاغ عن محتوى حسّاس، أضِف قيمة منطقية إضافية إلى 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. الحصول على كائن ClipboardManager العام باستخدام getSystemService(CLIPBOARD_SERVICE) أيضًا، قم بتعريف متغير عمومي ليحتوي على النص الذي تم لصقه:

    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. نسخ البيانات من الحافظة لا يمكن الوصول إلى هذه النقطة في الرمز إلا إذا "لصق" عنصر القائمة مفعّل، لذا يمكنك افتراض أن الحافظة تحتوي على النص. لا تعرف حتى الآن ما إذا كان يحتوي على سلسلة نصية أو معرف موارد منتظم (URI) يشير إلى نص عادي. يختبر مقتطف الرمز التالي ذلك، لكنه يعرض فقط الرمز للتعامل مع النص العادي:

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

لصق البيانات من معرف موارد منتظم (URI) للمحتوى

إذا كان الكائن ClipData.Item يحتوي على معرّف موارد منتظم (URI) للمحتوى وحددت ما إذا كان بإمكانك التعامل مع أحد أنواع MIME التابعة له وإنشاء ContentResolver واستدعاء المحتوى المناسب لاسترداد البيانات.

يصف الإجراء التالي كيفية الحصول على بيانات من موفّر محتوى استنادًا إلى معرّف موارد منتظم (URI) للمحتوى في الحافظة. تتحقّق مما إذا كان نوع 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. احصل على المقطع الأساسي من الحافظة واحصل على محتواه كمعرّف الموارد المنتظم (URI):

    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. يمكنك اختبار ما إذا كان معرِّف الموارد المنتظم (URI) هو معرّف موارد منتظم (URI) للمحتوى من خلال استدعاء 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" بشكل متكرّر من تطبيق معيّن. لا يظهر النخب إلا عندما عندما يصل تطبيقك إلى البيانات من ذلك التطبيق للمرة الأولى
  • لاسترداد البيانات الوصفية لعنصر المقطع، مثل من خلال استدعاء getPrimaryClipDescription() بدلاً من getPrimaryClip().

استخدام موفري المحتوى لنسخ البيانات المعقدة

يتيح موفّرو المحتوى نسخ البيانات المعقدة مثل سجلات قواعد البيانات أو تدفقات الملفات. للنسخ البيانات، ضع عنوان URI للمحتوى في الحافظة. تحصل التطبيقات بعد ذلك على عنوان URI هذا من الحافظة واستخدامها لاسترداد بيانات قاعدة البيانات أو واصفات تدفق الملفات.

نظرًا لأن تطبيق اللصق لا يتضمن سوى معرف الموارد المنتظم (URI) للمحتوى الخاص ببياناتك، فإنه يحتاج إلى معرفة جزء من البيانات لاستردادها. يمكنك توفير هذه المعلومات من خلال ترميز معرّف البيانات. على معرف الموارد المنتظم (URI) نفسه، أو يمكنك توفير عنوان URI فريد يعرض البيانات التي تريد نسخها. أي الذي تختاره على تنظيم بياناتك.

توضح الأقسام التالية كيفية إعداد معرفات الموارد المنتظمة (URI)، وتوفير بيانات معقدة وتوفير جداول البيانات. تفترض الأوصاف أنك على دراية بالمبادئ العامة لموفّر المحتوى التصميم.

ترميز معرِّف على عنوان URI

هناك أسلوب مفيد لنسخ البيانات إلى الحافظة باستخدام عنوان URI وهو ترميز معرف البيانات على عنوان URI نفسه. ويمكن لموفّر المحتوى عندئذ الحصول على المعرّف من معرّف الموارد المنتظم (URI) واستخدام لاسترداد البيانات. ليس من الضروري أن يعرف تطبيق اللصق توفُّر المعرّف. أُنشأها جون هنتر، الذي كان متخصصًا فقط الحصول على "المرجع" - عنوان URI بالإضافة إلى المعرف - من الحافظة، ومنحه موفر المحتوى، واستعادة البيانات.

وتقوم عادةً بترميز أحد المعرفات في معرف موارد منتظم (URI) للمحتوى من خلال ربطه بنهاية معرف الموارد المنتظم (URI). على سبيل المثال، لنفترض أنك تحدد معرف الموارد المنتظم (URI) للموفر على أنه السلسلة التالية:

"content://com.example.contacts"

إذا كنت تريد ترميز اسم عبر معرّف الموارد المنتظم (URI) هذا، استخدِم مقتطف الرمز التالي:

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

وإذا كنت تستخدم موفّر محتوى من قبل، قد تحتاج إلى إضافة مسار URI جديد يشير إلى عنوان URI مخصص للنسخ. على سبيل المثال، لنفترض أن لديك مسارات URI التالية:

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

يمكنك إضافة مسار آخر لنسخ معرفات الموارد المنتظمة (URI):

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

يمكنك بعد ذلك اكتشاف "نسخة" معرف موارد منتظم (URI) عن طريق مطابقة الأنماط والتعامل معه مع رمز يمثل الخاصة بالنسخ واللصق.

أنت تستخدم أسلوب التشفير عادةً إذا كنت تستخدم موفِّر محتوى، أو قاعدة بيانات أو جدول داخلي لتنظيم بياناتك. في هذه الحالات، يكون لديك أجزاء متعددة من البيانات التي تريد نسخها، ويفترض أن تكون عبارة عن معرّف فريد لكل قطعة. ردًا على استعلام من تطبيق اللصق، يمكنك البحث عن البيانات من خلال معرفها وإعادتها.

إذا لم تتوفر لديك أجزاء متعددة من البيانات، لن تحتاج على الأرجح إلى ترميز معرِّف. يمكنك استخدام معرّف موارد منتظم (URI) فريد لموفّر الخدمة. ردًا على طلب بحث، يعرض الموفر البيانات التي تحتوي عليها حاليًا.

نسخ هياكل البيانات

قم بإعداد موفّر محتوى لنسخ البيانات المعقدة ولصقها كفئة فرعية من ContentProvider المكون. ترميز معرف الموارد المنتظم (URI) الذي تضعه في الحافظة بحيث يشير إلى السجل الدقيق الذي تريد التي تقدمها. بالإضافة إلى ذلك، يجب مراعاة الحالة الحالية لتطبيقك:

  • إذا كان لديك موفّر محتوى، يمكنك إضافة توفير محتوى إلى وظائفه. يمكنك فقط إلى تعديل طريقة query() للتعامل مع معرفات الموارد المنتظمة (URI) الواردة من التطبيقات التي تريد لصق البيانات. ربما ترغب في تعديل الطريقة لمعالجة "نسخة" معرّف موارد منتظم (URI) النمط.
  • إذا كان تطبيقك يحتفظ بقاعدة بيانات داخلية، قد تحتاج إلى نقل قاعدة البيانات هذه إلى موفّر محتوى لتسهيل النسخ منه.
  • إذا كنت لا تستخدم قاعدة بيانات، فيمكنك تطبيق موفر محتوى بسيط الغرض الوحيد هو تقديم البيانات للتطبيقات التي تلصق من الحافظة.

في موفِّر المحتوى، يمكنك إلغاء الطرق التالية على الأقل:

query()
تفترض التطبيقات التي يتم لصقها أن بإمكانها الحصول على بياناتك باستخدام هذه الطريقة مع معرِّف الموارد المنتظم (URI) الذي تستخدمه وضعه في الحافظة. لإتاحة النسخ، يمكنك استخدام هذه الطريقة لاكتشاف معرفات الموارد المنتظمة (URI) التي تحتوي على "نسخ" . يمكن لتطبيقك بعد ذلك إنشاء "نسخة" عنوان URI الذي يجب وضعه في تحتوي على مسار النسخ ومؤشر الماوس إلى السجل المحدد الذي تريد نسخه.
getType()
يجب أن تعرض هذه الطريقة أنواع MIME للبيانات التي تريد نسخها. الطريقة newUri() تستدعي getType() لإضافة أنواع MIME في ClipData الجديد. الخاص بك.

يتم توضيح أنواع MIME للبيانات المعقدة في موفّرو المحتوى:

ولن تحتاج إلى استخدام أي من طرق موفر المحتوى الأخرى، مثل insert() أو update() يحتاج تطبيق اللصق فقط إلى الحصول على أنواع MIME المتوافقة ونسخ البيانات من موفّر الخدمة. إذا كنت تستخدم هذه الطرق من قبل، فلن تتداخل مع عمليات النسخ.

توضح المقتطفات التالية كيفية إعداد تطبيقك لنسخ البيانات المعقدة:

  1. في الثوابت العامة لتطبيقك، اذكر سلسلة URI أساسية ومسارًا سلاسل معرف الموارد المنتظم (URI) التي تستخدمها لنسخ البيانات. يُرجى التعريف أيضًا بنوع 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. في النشاط الذي ينسخ المستخدمون البيانات منه، يمكنك إعداد الرمز لنسخ البيانات إلى الحافظة. استجابةً لطلب النسخ، ضَع معرّف الموارد المنتظم (URI) في الحافظة.

    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. في النطاق العام لموفر المحتوى، أنشئ مُطابق عنوان URI وأضف نمط عنوان URI تتطابق مع معرّفات الموارد المنتظمة (URI) التي تضعها في الحافظة.

    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() . يمكن لهذه الطريقة التعامل مع أنماط معرف الموارد المنتظم (URI) المختلفة بناءً على طريقة ترميزها، ولكن فقط يظهر نمط عملية نسخ الحافظة.

    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. إعداد طريقة getType() لإرجاع نوع MIME مناسب للنسخ البيانات:

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

يصف قسم لصق البيانات من معرف الموارد المنتظم (URI) للمحتوى كيفية الحصول على معرف الموارد المنتظم (URI) للمحتوى من الحافظة واستخدمه للحصول على البيانات ولصقها.

نسخ مصادر البيانات

يمكنك نسخ كميات كبيرة من البيانات النصية والبيانات الثنائية ولصقها كمصادر. يمكن أن تحتوي البيانات على نماذج مثل ما يلي:

  • الملفات المخزَّنة على الجهاز
  • أحداث البث من الأجهزة
  • كميات كبيرة من البيانات المخزنة في نظام قاعدة البيانات الأساسية للمزود

يوفّر موفّر المحتوى لمصادر البيانات إمكانية الوصول إلى بياناتها باستخدام كائن واصف الملف، مثل AssetFileDescriptor, بدلاً من كائن Cursor. يقرأ تطبيق اللصق مصدر البيانات باستخدام هذا واصف الملفات.

لإعداد تطبيقك لنسخ مصدر بيانات مع موفّر خدمة، اتّبِع الخطوات التالية:

  1. يمكنك إعداد معرّف موارد منتظم (URI) للمحتوى لمصدر البيانات الذي تضعه في الحافظة. خيارات لإجراء ذلك، ما يلي:
    • يجب ترميز معرِّف لمصدر البيانات في عنوان URI، كما هو موضَّح في ترميز معرّف في قسم URI، ثم الاحتفاظ في موفّر الخدمة يتضمّن المعرّفات واسم مصدر البيانات المقابل
    • يجب ترميز اسم مصدر البيانات مباشرةً في معرّف الموارد المنتظم (URI).
    • استخدِم معرّف موارد منتظم (URI) فريد يعرض دائمًا البث الحالي من الموفّر. إذا كنت لاستخدام هذا الخيار، لا تنسَ تعديل موفّر الخدمة للتوجيه إلى بث مختلف. كلما نسخت ساحة المشاركات إلى الحافظة باستخدام معرّف الموارد المنتظم (URI).
  2. قدِّم نوع MIME لكل نوع من مصادر البيانات التي تخطط لتوفيرها. لصق التطبيقات إلى هذه المعلومات لتحديد ما إذا كان بإمكانه لصق البيانات في الحافظة.
  3. تنفيذ إحدى طرق ContentProvider التي تعرض واصف ملف للملف تدفق. إذا كنت ترمّز المعرّفات على معرّف الموارد المنتظم (URI) للمحتوى، استخدِم هذه الطريقة لتحديد البث لفتحه.
  4. لنسخ مصدر البيانات إلى الحافظة، أنشِئ معرّف الموارد المنتظم (URI) للمحتوى وضَعه في الحافظة.

للصق مصدر بيانات، يحصل التطبيق على المقطع من الحافظة، ويحصل على معرّف الموارد المنتظم (URI)، ويستخدم في استدعاء لطريقة واصف ملفات ContentResolver التي تفتح ساحة المشاركات. تشير رسالة الأشكال البيانية تستدعي طريقة ContentResolver طريقة ContentProvider المقابلة، وتمريره معرف الموارد المنتظم (URI) للمحتوى. يعيد الموفر واصف الملف إلى طريقة ContentResolver. عندئذٍ يتحمل تطبيق اللصق مسؤولية قراءة من مصدر البيانات.

تعرض القائمة التالية أهم طرق واصف الملفات بالنسبة إلى موفّر المحتوى. على كل لها طريقة ContentResolver مقابلة مع السلسلة "أداة الوصف" ملحق باسم الطريقة. على سبيل المثال، ContentResolver تناظري من openAssetFile() CANNOT TRANSLATE openAssetFileDescriptor()

openTypedAssetFile()

تعرض هذه الطريقة واصفًا لملف مادة العرض، ولكن فقط إذا كان نوع MIME المقدم يعتمده مزود الخدمة. يعرض المتصل، التطبيق الذي يجري اللصق، نمط MIME. موفِّر محتوى التطبيق الذي ينسخ معرف موارد منتظم (URI) إلى تعرض الحافظة مؤشر ملف AssetFileDescriptor إذا كان بإمكانها توفير ذلك وينشئ نوع MIME استثناءً إذا لم يكن كذلك.

تتعامل هذه الطريقة مع الأقسام الفرعية من الملفات. ويمكنك استخدامه لقراءة الأصول التي موفّر المحتوى قد نسخ إلى الحافظة.

openAssetFile()
هذه الطريقة هي شكل أكثر عمومية من openTypedAssetFile(). لا يقوم بتصفية لأنواع MIME المسموح بها، ولكن يمكنه قراءة الأقسام الفرعية من الملفات.
openFile()
هذا نموذج أكثر عمومية من openAssetFile(). ولا يمكنها قراءة الأقسام الفرعية من الملفات.

يمكنك اختياريًا استخدام openPipeHelper() باستخدام طريقة واصف الملف. يتيح هذا لتطبيق اللصق قراءة بيانات البث في مؤشر ترابط الخلفية باستخدام ممر. لاستخدام هذه الطريقة، نفذ ContentProvider.PipeDataWriter من واجهة pyplot.

تصميم وظيفة نسخ ولصق فعالة

لتصميم وظيفة نسخ ولصق فعالة لتطبيقك، تذكر النقاط التالية:

  • هناك مقطع واحد فقط في الحافظة في أي وقت. عملية نسخ جديدة بواسطة أي في النظام إلى استبدال المقطع السابق. نظرًا لأن المستخدم قد يتنقل بعيدًا عن التطبيق والنسخ قبل العودة، فلا يمكنك افتراض أن الحافظة يحتوي على المقطع الذي نسخته سابقًا في تطبيقك.
  • الغرض من تضمين عناصر ClipData.Item متعددة في كل مقطع هو دعم نسخ ولصق تحديدات متعددة بدلاً من أشكال مختلفة من الإشارة إلى تحديد واحد. تريد عادةً جميع ClipData.Item الكائنات في مقطع لها الشكل نفسه أي أنها يجب أن تكون جميعها نصًا بسيطًا أو محتوىً عنوان URI، أو Intent، وليس مختلطًا.
  • عند تقديم البيانات، يمكنك تقديم تمثيلات MIME مختلفة. إضافة أنواع MIME كنت تدعم ClipDescription، ثم تنفيذ أنواع MIME في في موفّر المحتوى
  • عندما تحصل على بيانات من الحافظة، يكون تطبيقك مسؤولاً عن التحقق من أنواع MIME المتاحة ثم تحديد أي نوع، إن وجد. حتى إذا كانت هناك مقطع إلى الحافظة وطلب المستخدم لصقه، فتطبيقك ليس مطلوبًا لعمل اللصق. وعليك إجراء اللصق إذا كان نوع MIME متوافقًا. قد تجبر البيانات في الحافظة إلى رسالة نصية باستخدام coerceToText(). إذا كان تطبيقك يتيح أكثر من نوع واحد من أنواع MIME المتاحة، يمكنك السماح للمستخدم باختيار أي نوع لاستخدامه.