يوفّر Android إطار عمل فعّالاً يستند إلى الحافظة للنسخ واللصق. وهي تتيح استخدام أنواع البيانات البسيطة والمعقّدة، بما في ذلك السلاسل النصية وبُنى البيانات المعقّدة والنصوص وبيانات تدفق البيانات الثنائية ومواد عرض التطبيقات. يتم تخزين بيانات النص البسيط مباشرةً في الحافظة، بينما يتم تخزين البيانات المعقّدة كمرجع يحلّه تطبيق اللصق باستخدام أداة توفير المحتوى. يعمل النسخ واللصق داخل التطبيق وبين التطبيقات التي تنفذ إطار العمل.
بما أنّ جزءًا من إطار العمل يستخدم أدوات توفير المحتوى، يفترض هذا المستند أنّك على دراية ببعض المعلومات حول واجهة برمجة التطبيقات Android Content Provider API الموضّحة في أدوات توفير المحتوى.
يتوقّع المستخدمون تلقّي ملاحظات عند نسخ المحتوى إلى الحافظة، لذا بالإضافة إلى إطار العمل الذي يتيح النسخ واللصق، يعرض Android واجهة مستخدم تلقائية للمستخدمين عند النسخ في الإصدار 13 من نظام التشغيل Android (مستوى واجهة برمجة التطبيقات 33) والإصدارات الأحدث. بسبب هذه الميزة، هناك خطر من تكرار الإشعارات. يمكنك الاطّلاع على مزيد من المعلومات حول هذه الحالة الاستثنائية في قسم تجنُّب الإشعارات المكرّرة.
تقديم ملاحظات يدويًا للمستخدمين عند النسخ في الإصدار Android 12L (المستوى 32 لواجهة برمجة التطبيقات) والإصدارات الأقدم يمكنك الاطّلاع على الاقتراحات بشأن ذلك في هذا المستند.
إطار عمل الحافظة
عند استخدام إطار عمل الحافظة، ضع البيانات في عنصر مقطع، ثم ضع عنصر المقطع في الحافظة على مستوى النظام. يمكن أن يتّخذ عنصر المقطع أحد الأشكال الثلاثة التالية:
- نص
- سلسلة نصية ضع السلسلة مباشرةً في كائن المقطع، ثم ضعه في الحافظة. للصق السلسلة، احصل على عنصر المقطع من الحافظة وانسخ السلسلة إلى مساحة تخزين التطبيق.
- معرّف الموارد المنتظم (URI)
-
عنصر
Uriيمثّل أي شكل من أشكال معرّف الموارد المنتظم (URI). ويُستخدم هذا الإجراء بشكل أساسي لنسخ البيانات المعقّدة من أداة توفير المحتوى. لنسخ البيانات، ضع عنصرUriفي عنصر مقطع وضع عنصر المقطع في الحافظة. للصق البيانات، يمكنك الحصول على عنصر المقطع، والحصول على عنصرUri، وتحليله إلى مصدر بيانات، مثل أداة توفير المحتوى، ونسخ البيانات من المصدر إلى مساحة تخزين التطبيق. - النيّة
-
Intentيتيح هذا الإجراء نسخ اختصارات التطبيقات. لنسخ البيانات، أنشئIntent، وضعه في عنصر مقطع، ثم ضع عنصر المقطع في الحافظة. للصق البيانات، احصل على عنصر الحافظة ثم انسخ العنصرIntentإلى منطقة الذاكرة في تطبيقك.
تحتوي الحافظة على عنصر واحد فقط في كل مرة. عندما يضع تطبيق ما عنصرًا في الحافظة، يختفي العنصر السابق.
إذا كنت تريد السماح للمستخدمين بلصق البيانات في تطبيقك، فلن تحتاج إلى التعامل مع جميع أنواع البيانات. يمكنك فحص البيانات في الحافظة قبل منح المستخدمين خيار لصقها. بالإضافة إلى وجود نموذج بيانات معين، يحتوي كائن المقطع أيضًا على بيانات وصفية تخبرك بأنواع MIME المتاحة. تساعدك هذه البيانات الوصفية في تحديد ما إذا كان بإمكان تطبيقك تنفيذ إجراء مفيد باستخدام بيانات الحافظة. على سبيل المثال، إذا كان لديك تطبيق يتعامل بشكل أساسي مع النصوص، قد تحتاج إلى تجاهل عناصر المقطع التي تحتوي على معرّف موارد منتظم (URI) أو نية.
قد ترغب أيضًا في السماح للمستخدمين بلصق النص بغض النظر عن شكل البيانات في الحافظة. لإجراء ذلك، يمكنك فرض بيانات الحافظة في تمثيل نصي، ثم لصق هذا النص. يتم شرح ذلك في قسم فرض تحويل محتوى الحافظة إلى نص.
فئات الحافظة
يصف هذا القسم الفئات التي يستخدمها إطار عمل الحافظة.
ClipboardManager
يتم تمثيل حافظة نظام Android من خلال فئة ClipboardManager العامة.
لا تنشئ مثيلاً لهذه الفئة مباشرةً. بدلاً من ذلك، يمكنك الحصول على مرجع له من خلال استدعاء
getSystemService(CLIPBOARD_SERVICE).
ClipData وClipData.Item وClipDescription
لإضافة بيانات إلى الحافظة، أنشئ كائن
ClipData يحتوي على وصف للبيانات
والبيانات نفسها. تحتفظ الحافظة بعنصر واحد من ClipData في كل مرة. يحتوي ClipData على عنصر ClipDescription واحد وعنصر ClipData.Item واحد أو أكثر.
يحتوي عنصر ClipDescription على بيانات وصفية حول المقطع. على وجه الخصوص، يحتوي على مصفوفة من أنواع MIME المتاحة لبيانات المقطع. بالإضافة إلى ذلك، في الإصدار Android 12 (المستوى 31 من واجهة برمجة التطبيقات) والإصدارات الأحدث، تتضمّن البيانات الوصفية معلومات حول ما إذا كان العنصر يحتوي على نص منمّق وحول نوع النص في العنصر.
عند وضع مقطع في الحافظة، تكون هذه المعلومات متاحة للتطبيقات التي يمكنها لصقها، والتي يمكنها فحص ما إذا كان بإمكانها التعامل مع بيانات المقطع.
يحتوي عنصر ClipData.Item على النص أو معرّف الموارد المنتظم (URI) أو بيانات Intent:
- نص
-
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.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معرّف موارد منتظم (URI)، أي إذا لم يكنgetUri()فارغًا، يحاولcoerceToText()استخدامه كمعرّف موارد منتظم للمحتوى.- إذا كان معرّف الموارد المنتظم هو معرّف موارد منتظم للمحتوى وكان بإمكان مقدّم الخدمة عرض سلسلة نصية،
تعرض الدالة
coerceToText()سلسلة نصية. - إذا كان معرّف الموارد المنتظم (URI) هو معرّف موارد منتظم للمحتوى ولكن لا يوفّر المزوّد مصدرًا نصيًا،
تعرض الدالة
coerceToText()تمثيلاً لمعرّف الموارد المنتظم (URI). يكون التمثيل مماثلاً للتمثيل الذي تعرضه السمةUri.toString(). - إذا لم يكن معرّف الموارد المنتظم (URI) معرّف موارد منتظمًا للمحتوى، ستعرض الدالة
coerceToText()تمثيلاً لمعرّف الموارد المنتظم (URI). يكون التمثيل مماثلاً للتمثيل الذي تعرضه السمةUri.toString().
- إذا كان معرّف الموارد المنتظم هو معرّف موارد منتظم للمحتوى وكان بإمكان مقدّم الخدمة عرض سلسلة نصية،
تعرض الدالة
- النيّة
- إذا كان
ClipData.Itemعبارة عنIntent، أي إذا لم يكنgetIntent()فارغًا، يحوّلهcoerceToText()إلى معرّف URI لـ Intent ويعرضه. يكون التمثيل مماثلاً للتمثيل الذي تعرضه السمةIntent.toUri(URI_INTENT_SCHEME).
تم تلخيص إطار عمل الحافظة في الشكل 2. لنسخ البيانات، يضع التطبيق كائن ClipData في الحافظة العامة ClipboardManager. يحتوي
ClipData على عنصر واحد أو أكثر من عناصر ClipData.Item وعنصر واحد من عناصر
ClipDescription. للصق البيانات، يحصل التطبيق على ClipData،
ويحصل على نوع MIME من ClipDescription، ويحصل على البيانات من
ClipData.Item أو من أداة توفير المحتوى التي يشير إليها
ClipData.Item.
النسخ إلى الحافظة
لنسخ البيانات إلى الحافظة، احصل على مؤشر إلى عنصر ClipboardManager العام،
وأنشئ عنصر ClipData، وأضِف إليه عنصر ClipDescription وعنصر واحد أو أكثر من عناصر
ClipData.Item. بعد ذلك، أضِف عنصر ClipData المكتمل إلى عنصر ClipboardManager. يتم شرح ذلك بمزيد من التفصيل في الإجراء التالي:
- إذا كنت تنسخ البيانات باستخدام معرّف موارد منتظم للمحتوى، عليك إعداد أداة توفير المحتوى.
- الحصول على حافظة النظام:
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);
-
انسخ البيانات إلى كائن
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).
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);
-
للنصوص
-
ضع كائن المقطع الجديد في الحافظة:
Kotlin
// Set the clipboard's primary clip. clipboard.setPrimaryClip(clip)
Java
// Set the clipboard's primary clip. clipboard.setPrimaryClip(clip);
تقديم ملاحظات عند النسخ إلى الحافظة
يتوقّع المستخدمون تلقّي ملاحظات مرئية عندما ينسخ تطبيق محتوى إلى الحافظة. يتم تنفيذ ذلك تلقائيًا للمستخدمين في الإصدار 13 من نظام التشغيل Android والإصدارات الأحدث، ولكن يجب تنفيذه يدويًا في الإصدارات السابقة.
بدءًا من الإصدار Android 13، يعرض النظام تأكيدًا مرئيًا عاديًا عند إضافة محتوى إلى الحافظة. يؤدي التأكيد الجديد إلى ما يلي:
- يؤكّد أنّه تم نسخ المحتوى بنجاح.
- يوفّر معاينة للمحتوى الذي تم نسخه.
في الإصدار 12L من Android (المستوى 32 لواجهة برمجة التطبيقات) والإصدارات الأقدم، قد لا يكون المستخدمون متأكدين مما إذا كانوا قد نجحوا في نسخ المحتوى أو ما الذي نسخوه. تعمل هذه الميزة على توحيد الإشعارات المختلفة التي تعرضها التطبيقات بعد النسخ وتوفّر للمستخدمين مزيدًا من التحكّم في الحافظة.
تجنُّب الإشعارات المكرّرة
في الإصدار 12L من نظام التشغيل Android (مستوى واجهة برمجة التطبيقات 32) والإصدارات الأقدم، ننصحك بتنبيه المستخدمين عند نجاح عملية النسخ من خلال إصدار ملاحظات مرئية داخل التطبيق، باستخدام تطبيق مصغّر مثل Toast أو Snackbar، بعد النسخ.
لتجنُّب عرض المعلومات بشكل مكرّر، ننصح بشدة بإزالة رسائل الإعلام المؤقتة أو أشرطة الإعلام التي تظهر بعد النسخ داخل التطبيق على نظام التشغيل 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 والإصدارات الأحدث.
للإبلاغ عن محتوى حسّاس، أضِف قيمة منطقية إضافية إلى 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()، كما هو موضح في الإجراء التالي:
- احصل على العنصر العمومي
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 = "";
- تحديد ما إذا كنت بحاجة إلى تفعيل خيار "اللصق" أو إيقافه في النشاط
الحالي تأكَّد من أنّ الحافظة تحتوي على مقطع وأنّه يمكنك التعامل مع نوع البيانات
التي يمثّلها المقطع:
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); }
- انسخ البيانات من الحافظة. لا يمكن الوصول إلى هذه النقطة في الرمز إلا إذا كان خيار "لصق" في القائمة مفعَّلاً، لذا يمكنك افتراض أنّ الحافظة تحتوي على نص عادي. لا تعرف بعد ما إذا كان يحتوي على سلسلة نصية أو معرّف موارد منتظم (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; } }
لصق البيانات من معرّف موارد منتظم للمحتوى
إذا كان الكائن ClipData.Item يحتوي على معرّف موارد منتظم للمحتوى وتبيّن لك أنّه يمكنك
التعامل مع أحد أنواع MIME الخاصة به، أنشئ ContentResolver واستدعِ طريقة أداة توفير المحتوى
المناسبة لاسترداد البيانات.
يوضّح الإجراء التالي كيفية الحصول على البيانات من أداة توفير المحتوى استنادًا إلى معرّف موارد منتظم للمحتوى في الحافظة. يتحقّق من توفّر نوع MIME يمكن للتطبيق استخدامه من الموفّر.
-
أعلِن عن متغير عمومي يحتوي على نوع 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";
- الحصول على الحافظة العامة يمكنك أيضًا الحصول على محلّل محتوى لتتمكّن من الوصول إلى أداة توفير المحتوى:
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();
- احصل على المقطع الأساسي من الحافظة واحصل على محتواه كمعرّف موارد منتظم (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();
- اختبِر ما إذا كان معرّف الموارد المنتظم هو معرّف موارد منتظم للمحتوى من خلال استدعاء
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);
- اختبِر ما إذا كانت أداة توفير المحتوى متوافقة مع نوع 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(); } } } }
لصق هدف
للصق intent، عليك أولاً الحصول على الحافظة العامة. افحص الكائن 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. }
إشعار النظام الذي يظهر عند وصول تطبيقك إلى بيانات الحافظة
في الإصدار 12 من نظام التشغيل Android (المستوى 31 لواجهة برمجة التطبيقات) والإصدارات الأحدث، يعرض النظام عادةً رسالة مؤقتة عندما يستدعي تطبيقك
getPrimaryClip().
يحتوي النص داخل الرسالة على التنسيق التالي:
APP pasted from your clipboard
لا يعرض النظام رسالة مؤقتة عندما ينفّذ تطبيقك أحد الإجراءات التالية:
- الوصول إلى
ClipDataمن تطبيقك - يصل بشكل متكرر إلى
ClipDataمن تطبيق معيّن. تظهر رسالة الإشعار المؤقت فقط عندما يصل تطبيقك إلى البيانات من ذلك التطبيق لأول مرة. - يستردّ البيانات الوصفية لعنصر المقطع، مثلاً من خلال طلب
getPrimaryClipDescription()بدلاً منgetPrimaryClip().
استخدام أدوات توفير المحتوى لنسخ البيانات المعقّدة
تتيح أدوات توفير المحتوى نسخ البيانات المعقّدة، مثل سجلّات قواعد البيانات أو مصادر بيانات الملفات. لنسخ البيانات، ضع معرّف موارد منتظم للمحتوى في الحافظة. بعد ذلك، تحصل تطبيقات اللصق على معرّف الموارد المنتظم (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 المتوافقة ونسخ البيانات من مقدّم الخدمة.
إذا كانت هذه الطرق متوفّرة لديك، لن تتداخل مع عمليات النسخ.
توضّح المقتطفات التالية كيفية إعداد تطبيقك لنسخ البيانات المعقّدة:
-
في الثوابت العامة لتطبيقك، حدِّد سلسلة معرّف موارد منتظم (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";
- في النشاط الذي ينسخ المستخدمون البيانات منه، عليك إعداد الرمز لنسخ البيانات إلى الحافظة.
استجابةً لطلب نسخ، ضع معرّف الموارد المنتظم (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);
-
في النطاق العام لأداة توفير المحتوى، أنشئ أداة مطابقة لمعرّفات الموارد المنتظمة (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);
-
اضبط طريقة
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. ... }
-
اضبط طريقة
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); ... } }
يصف قسم لصق البيانات من معرّف موارد منتظم للمحتوى كيفية الحصول على معرّف موارد منتظم للمحتوى من الحافظة واستخدامه للحصول على البيانات ولصقها.
نسخ مصادر البيانات
يمكنك نسخ كميات كبيرة من النصوص والبيانات الثنائية ولصقها كسلاسل. يمكن أن تحتوي البيانات على نماذج مثل ما يلي:
- الملفات المخزَّنة على الجهاز الفعلي
- عمليات البث من المقابس
- كميات كبيرة من البيانات المخزّنة في نظام قاعدة البيانات الأساسي لمقدّم الخدمة
تتيح أداة توفير المحتوى لتدفقات البيانات الوصول إلى بياناتها باستخدام عنصر واصِف الملف،
مثل
AssetFileDescriptor،
بدلاً من عنصر Cursor. يقرأ تطبيق اللصق مصدر البيانات باستخدام واصِف الملف هذا.
لإعداد تطبيقك لنسخ مصدر بيانات مع مقدّم خدمة، اتّبِع الخطوات التالية:
-
إعداد معرّف موارد منتظم للمحتوى لمصدر البيانات الذي تضعه في الحافظة تشمل الخيارات المتاحة لتنفيذ ذلك ما يلي:
- ترميز معرّف لمصدر البيانات في معرّف الموارد المنتظم (URI)، كما هو موضّح في قسم ترميز معرّف في معرّف الموارد المنتظم (URI)، ثم الاحتفاظ بجدول في الموفّر يحتوي على المعرّفات واسم المصدر المقابل
- ترميز اسم البث مباشرةً في معرّف الموارد المنتظم (URI)
- استخدِم معرّف موارد منتظم (URI) فريدًا يعرض دائمًا البث الحالي من مقدّم الخدمة. إذا كنت تستخدم هذا الخيار، تذكَّر تعديل مقدّم الخدمة للإشارة إلى بث مختلف كلما نسخت البث إلى الحافظة باستخدام معرّف الموارد المنتظم (URI).
- قدِّم نوع MIME لكل نوع من مصادر البيانات التي تخطّط لتقديمها. وتحتاج التطبيقات التي يتم اللصق فيها إلى هذه المعلومات لتحديد ما إذا كان بإمكانها لصق البيانات في الحافظة.
- نفِّذ إحدى طرق
ContentProviderالتي تعرض واصِف ملف للبث. إذا كنت ترمّز المعرّفات في معرّف الموارد المنتظم للمحتوى، استخدِم هذه الطريقة لتحديد البث الذي تريد فتحه. - لنسخ مصدر البيانات إلى الحافظة، أنشئ معرّف الموارد المنتظم للمحتوى وضعه في الحافظة.
ولصق مصدر بيانات، يحصل التطبيق على المقطع من الحافظة، ويحصل على معرّف الموارد المنتظم (URI)، ويستخدمه في استدعاء طريقة واصِف ملف ContentResolver التي تفتح المصدر. يستدعي الأسلوب ContentResolver الأسلوب ContentProvider المقابل، ويمرّر إليه معرّف الموارد المنتظم للمحتوى. يعرض موفّر الخدمة واصِف الملف إلى طريقة
ContentResolver. ويكون تطبيق اللصق مسؤولاً عن قراءة البيانات من مصدر البيانات.
تعرض القائمة التالية أهم طرق واصف الملفات لأداة توفير المحتوى. ولكلّ منها طريقة ContentResolver مقابلة مع إلحاق السلسلة "Descriptor" باسم الطريقة. على سبيل المثال، القيمة المقابلة لـ openAssetFile() في ContentResolver هي openAssetFileDescriptor().
-
openTypedAssetFile() -
تعرض هذه الطريقة واصِف ملف مادة العرض، ولكن فقط إذا كان نوع MIME المقدَّم متوافقًا مع مقدّم الخدمة. يوفّر المتصل، أي التطبيق الذي ينفّذ عملية اللصق، نمط نوع MIME. تُرجع أداة توفير المحتوى للتطبيق الذي ينسخ معرّف موارد منتظم (URI) إلى الحافظة معالج ملفات
AssetFileDescriptorإذا كان بإمكانها توفير نوع MIME هذا، وتُرسل استثناءً إذا لم يكن بإمكانها ذلك.تتعامل هذه الطريقة مع الفقرات الفرعية للملفات. ويمكنك استخدامها لقراءة مواد العرض التي نسختها أداة توفير المحتوى إلى الحافظة.
-
openAssetFile() -
هذه الطريقة هي شكل أكثر عمومية من
openTypedAssetFile(). ولا تتم فلترة أنواع MIME المسموح بها، ولكن يمكن قراءة الفقرات الفرعية للملفات. -
openFile() -
هذا شكل أكثر عمومية من
openAssetFile(). ولا يمكنه قراءة الفقرات الفرعية من الملفات.
يمكنك اختياريًا استخدام طريقة
openPipeHelper()
مع طريقة واصِف الملف. يتيح ذلك لتطبيق اللصق قراءة بيانات البث في سلسلة محادثات في الخلفية باستخدام مسار. لاستخدام هذه الطريقة، يجب تنفيذ واجهة
ContentProvider.PipeDataWriter.
تصميم وظيفة نسخ ولصق فعّالة
لتصميم وظيفة نسخ ولصق فعالة لتطبيقك، تذكر هذه النقاط:
- في أي وقت، يتوفّر مقطع واحد فقط في الحافظة. وتؤدي أي عملية نسخ جديدة من أي تطبيق في النظام إلى استبدال المقطع السابق. بما أنّ المستخدم قد ينتقل بعيدًا عن تطبيقك وينسخ المحتوى قبل العودة، لا يمكنك افتراض أنّ الحافظة تحتوي على المقطع الذي نسخه المستخدم سابقًا في تطبيقك .
-
الغرض المقصود من استخدام عناصر
ClipData.Itemمتعددة لكل مقطع هو إتاحة نسخ ولصق اختيارات متعددة بدلاً من أشكال مختلفة من الإشارة إلى اختيار واحد. عادةً ما تريد أن تكون جميع كائناتClipData.Itemفي المقطع لها نفس الشكل. وهذا يعني أنّها يجب أن تكون جميعها نصًا بسيطًا أو معرّف موارد منتظمًا للمحتوى أوIntent، ولا يمكن الجمع بينها. -
عند تقديم البيانات، يمكنك تقديم تمثيلات MIME مختلفة. أضِف أنواع MIME التي تتيحها إلى
ClipDescription، ثم نفِّذ أنواع MIME في أداة توفير المحتوى. -
عند الحصول على بيانات من الحافظة، يكون تطبيقك مسؤولاً عن التحقّق من أنواع MIME المتاحة ثم تحديد النوع الذي سيتم استخدامه، إن وُجد. حتى إذا كان هناك
مقطع في الحافظة وطلب المستخدم لصقه، ليس مطلوبًا من تطبيقك
إجراء اللصق. نفِّذ عملية اللصق إذا كان نوع MIME متوافقًا. يمكنك فرض البيانات
في الحافظة على النص باستخدام
coerceToText(). إذا كان تطبيقك يتيح استخدام أكثر من نوع واحد من أنواع MIME المتاحة، يمكنك السماح للمستخدم باختيار النوع الذي يريد استخدامه.