Android অনুলিপি এবং আটকানোর জন্য একটি শক্তিশালী ক্লিপবোর্ড-ভিত্তিক কাঠামো প্রদান করে। এটি টেক্সট স্ট্রিং, জটিল ডেটা স্ট্রাকচার, টেক্সট এবং বাইনারি স্ট্রিম ডেটা এবং অ্যাপ্লিকেশন সম্পদ সহ সাধারণ এবং জটিল ডেটা প্রকারগুলিকে সমর্থন করে। সরল পাঠ্য ডেটা সরাসরি ক্লিপবোর্ডে সংরক্ষণ করা হয়, যখন জটিল ডেটা একটি রেফারেন্স হিসাবে সংরক্ষণ করা হয় যা পেস্টিং অ্যাপ্লিকেশন একটি বিষয়বস্তু প্রদানকারীর সাথে সমাধান করে। অনুলিপি এবং আটকানো একটি অ্যাপ্লিকেশনের মধ্যে এবং ফ্রেমওয়ার্ক বাস্তবায়নকারী অ্যাপ্লিকেশনগুলির মধ্যে উভয়ই কাজ করে।
যেহেতু ফ্রেমওয়ার্কের একটি অংশ সামগ্রী সরবরাহকারী ব্যবহার করে, তাই এই নথিটি Android সামগ্রী প্রদানকারী API এর সাথে কিছু পরিচিতি অনুমান করে, যা বিষয়বস্তু প্রদানকারীতে বর্ণিত হয়েছে৷
ক্লিপবোর্ডে বিষয়বস্তু অনুলিপি করার সময় ব্যবহারকারীরা প্রতিক্রিয়া আশা করে, তাই কপি এবং পেস্ট করার ক্ষমতা দেয় এমন কাঠামোর পাশাপাশি, Android 13 (API স্তর 33) এবং উচ্চতর কপি করার সময় Android ব্যবহারকারীদের একটি ডিফল্ট UI দেখায়। এই বৈশিষ্ট্যের কারণে, নকল বিজ্ঞপ্তির ঝুঁকি রয়েছে। আপনি এই প্রান্ত কেস সম্পর্কে আরও জানতে পারেন ডুপ্লিকেট বিজ্ঞপ্তিগুলি এড়িয়ে চলুন বিভাগে৷

Android 12L (API লেভেল 32) এবং তার নিচে কপি করার সময় ব্যবহারকারীদের ম্যানুয়ালি ফিডব্যাক প্রদান করুন। এই নথিতে এই জন্য সুপারিশ দেখুন.
ক্লিপবোর্ড ফ্রেমওয়ার্ক
যখন আপনি ক্লিপবোর্ড ফ্রেমওয়ার্ক ব্যবহার করেন, তখন একটি ক্লিপ অবজেক্টে ডেটা রাখুন এবং তারপর ক্লিপ অবজেক্টটিকে সিস্টেম-ওয়াইড ক্লিপবোর্ডে রাখুন। ক্লিপ অবজেক্ট তিনটি ফর্মের একটি নিতে পারে:
- পাঠ্য
- একটি টেক্সট স্ট্রিং। স্ট্রিংটি সরাসরি ক্লিপ অবজেক্টে রাখুন, যা আপনি তারপর ক্লিপবোর্ডে রাখবেন। স্ট্রিংটি পেস্ট করতে, ক্লিপবোর্ড থেকে ক্লিপ অবজেক্টটি পান এবং স্ট্রিংটি আপনার অ্যাপ্লিকেশনের স্টোরেজে অনুলিপি করুন।
- ইউআরআই
- একটি
Uri
অবজেক্ট যা URI-এর যেকোনো রূপকে প্রতিনিধিত্ব করে। এটি মূলত একটি বিষয়বস্তু প্রদানকারীর কাছ থেকে জটিল ডেটা অনুলিপি করার জন্য। ডেটা কপি করতে, একটিUri
অবজেক্টকে একটি ক্লিপ অবজেক্টে রাখুন এবং ক্লিপ অবজেক্টটিকে ক্লিপবোর্ডে রাখুন। ডেটা পেস্ট করতে, ক্লিপ অবজেক্ট পান,Uri
অবজেক্ট পান, এটি একটি ডেটা উৎসে সমাধান করুন, যেমন একটি সামগ্রী প্রদানকারী, এবং উৎস থেকে ডেটা আপনার অ্যাপ্লিকেশনের স্টোরেজে অনুলিপি করুন। - অভিপ্রায়
- একটি
Intent
। এটি অনুলিপি অ্যাপ্লিকেশন শর্টকাট সমর্থন করে. ডেটা কপি করতে, একটিIntent
তৈরি করুন, এটি একটি ক্লিপ অবজেক্টে রাখুন এবং ক্লিপবোর্ডে ক্লিপ অবজেক্ট রাখুন। ডেটা পেস্ট করতে, ক্লিপ অবজেক্টটি পান এবং তারপরে আপনার অ্যাপ্লিকেশনের মেমরি এলাকায়Intent
অবজেক্টটি অনুলিপি করুন।
ক্লিপবোর্ড এক সময়ে শুধুমাত্র একটি ক্লিপ বস্তু ধারণ করে। যখন একটি অ্যাপ্লিকেশন ক্লিপবোর্ডে একটি ক্লিপ অবজেক্ট রাখে, পূর্ববর্তী ক্লিপ অবজেক্টটি অদৃশ্য হয়ে যায়।
আপনি যদি ব্যবহারকারীদের আপনার অ্যাপ্লিকেশনে ডেটা পেস্ট করতে দিতে চান তবে আপনাকে সব ধরনের ডেটা পরিচালনা করতে হবে না। ব্যবহারকারীদের পেস্ট করার বিকল্প দেওয়ার আগে আপনি ক্লিপবোর্ডে ডেটা পরীক্ষা করতে পারেন। একটি নির্দিষ্ট ডেটা ফর্ম থাকার পাশাপাশি, ক্লিপ অবজেক্টে মেটাডেটাও থাকে যা আপনাকে বলে যে MIME প্রকারগুলি উপলব্ধ। এই মেটাডেটা আপনাকে সিদ্ধান্ত নিতে সাহায্য করে যে আপনার অ্যাপ্লিকেশনটি ক্লিপবোর্ড ডেটার সাথে কার্যকর কিছু করতে পারে কিনা। উদাহরণস্বরূপ, যদি আপনার কাছে এমন একটি অ্যাপ্লিকেশন থাকে যা প্রাথমিকভাবে পাঠ্য পরিচালনা করে, আপনি ক্লিপ অবজেক্টগুলিকে উপেক্ষা করতে চাইতে পারেন যেগুলিতে একটি URI বা অভিপ্রায় রয়েছে৷
আপনি ক্লিপবোর্ডে ডেটার ফর্ম নির্বিশেষে ব্যবহারকারীদের পাঠ্য পেস্ট করতে দিতে চাইতে পারেন। এটি করার জন্য, ক্লিপবোর্ড ডেটাকে একটি পাঠ্য উপস্থাপনায় জোর করুন এবং তারপরে এই পাঠ্যটি আটকান। এটি ক্লিপবোর্ড থেকে পাঠ্য বিভাগে বাধ্য করা হয়েছে।
ক্লিপবোর্ড ক্লাস
এই বিভাগটি ক্লিপবোর্ড ফ্রেমওয়ার্ক দ্বারা ব্যবহৃত ক্লাস বর্ণনা করে।
ক্লিপবোর্ড ম্যানেজার
অ্যান্ড্রয়েড সিস্টেম ক্লিপবোর্ড গ্লোবাল ClipboardManager
ক্লাস দ্বারা প্রতিনিধিত্ব করা হয়। সরাসরি এই ক্লাসটি ইনস্ট্যান্টিয়েট করবেন না। পরিবর্তে, getSystemService(CLIPBOARD_SERVICE)
আহ্বান করে এটির একটি রেফারেন্স পান।
ClipData, ClipData.Item, এবং ClipDescription
ক্লিপবোর্ডে ডেটা যোগ করতে, একটি ClipData
অবজেক্ট তৈরি করুন যাতে ডেটা এবং ডেটার বিবরণ থাকে। ক্লিপবোর্ডে একবারে একটি ClipData
থাকে। একটি ClipData
একটি ClipDescription
অবজেক্ট এবং এক বা একাধিক ClipData.Item
অবজেক্ট ধারণ করে।
একটি ClipDescription
অবজেক্টে ক্লিপ সম্পর্কে মেটাডেটা থাকে। বিশেষ করে, এটিতে ক্লিপের ডেটার জন্য উপলব্ধ MIME প্রকারের একটি অ্যারে রয়েছে। উপরন্তু, Android 12 (API লেভেল 31) এবং উচ্চতর, মেটাডেটা অবজেক্টে স্টাইলাইজড টেক্সট আছে কিনা এবং অবজেক্টের টেক্সটের ধরন সম্পর্কে তথ্য অন্তর্ভুক্ত করে। আপনি যখন ক্লিপবোর্ডে একটি ক্লিপ রাখেন, তখন এই তথ্যটি অ্যাপ্লিকেশন পেস্ট করার জন্য উপলব্ধ থাকে, যা তারা ক্লিপ ডেটা পরিচালনা করতে পারে কিনা তা পরীক্ষা করতে পারে।
একটি ClipData.Item
অবজেক্টে পাঠ্য, URI, বা উদ্দেশ্য ডেটা থাকে:
- পাঠ্য
- একটি
CharSequence
। - ইউআরআই
- একটি
Uri
। এটি সাধারণত একটি বিষয়বস্তু প্রদানকারী URI ধারণ করে, যদিও যেকোনো URI অনুমোদিত। যে অ্যাপ্লিকেশনটি ডেটা সরবরাহ করে সেটি ক্লিপবোর্ডে URI রাখে। যে অ্যাপ্লিকেশনগুলি ডেটা পেস্ট করতে চায় তারা ক্লিপবোর্ড থেকে ইউআরআই পায় এবং সামগ্রী সরবরাহকারী বা অন্যান্য ডেটা উত্স অ্যাক্সেস করতে এবং ডেটা পুনরুদ্ধার করতে এটি ব্যবহার করে৷ - অভিপ্রায়
- একটি
Intent
। এই ডেটা টাইপ আপনাকে ক্লিপবোর্ডে একটি অ্যাপ্লিকেশন শর্টকাট কপি করতে দেয়। ব্যবহারকারীরা পরবর্তীতে ব্যবহারের জন্য তাদের অ্যাপ্লিকেশনে শর্টকাট পেস্ট করতে পারেন।
আপনি একটি ক্লিপে একাধিক ClipData.Item
বস্তু যোগ করতে পারেন। এটি ব্যবহারকারীদের একক ক্লিপ হিসাবে একাধিক নির্বাচন কপি এবং পেস্ট করতে দেয়। উদাহরণস্বরূপ, যদি আপনার একটি তালিকা উইজেট থাকে যা ব্যবহারকারীকে একবারে একাধিক আইটেম নির্বাচন করতে দেয়, আপনি একবারে সমস্ত আইটেম ক্লিপবোর্ডে অনুলিপি করতে পারেন। এটি করার জন্য, প্রতিটি তালিকা আইটেমের জন্য একটি পৃথক ClipData.Item
তৈরি করুন এবং তারপর ClipData
বস্তুতে ClipData.Item
অবজেক্ট যোগ করুন।
ক্লিপডেটা সুবিধার পদ্ধতি
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
অবজেক্টে একটি URI রয়েছে।ClipDescription
অবজেক্টের লেবেলlabel
সেট করা আছে। যদি URI একটি বিষয়বস্তু URI হয়—অর্থাৎ, যদিUri.getScheme()
content:
— পদ্ধতিটি সামগ্রী প্রদানকারীর কাছ থেকে উপলব্ধ MIME প্রকারগুলি পুনরুদ্ধার করতেresolver
প্রদত্তContentResolver
অবজেক্ট ব্যবহার করে। এটি তারপরClipDescription
তাদের সঞ্চয় করে। একটি URI-এর জন্য যা একটিcontent:
URI, পদ্ধতিটি MIME প্রকারকেMIMETYPE_TEXT_URILIST
এ সেট করে।একটি URI থেকে একটি ক্লিপ তৈরি করতে
newUri()
ব্যবহার করুন—বিশেষ করে একটিcontent:
URI। -
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()
null না হয়-coerceToText() টেক্সট ফেরত দেয়। - ইউআরআই
- যদি
ClipData.Item
একটি URI হয়—অর্থাৎ,getUri()
যদি শূন্য না হয়-coerceToText()
এটিকে একটি বিষয়বস্তু URI হিসেবে ব্যবহার করার চেষ্টা করে।- যদি URI একটি বিষয়বস্তু URI হয় এবং প্রদানকারী একটি পাঠ্য স্ট্রীম ফেরত দিতে পারে,
coerceToText()
একটি পাঠ্য স্ট্রীম প্রদান করে। - যদি URI একটি বিষয়বস্তু URI হয় কিন্তু প্রদানকারী একটি পাঠ্য স্ট্রীম অফার না করে,
coerceToText()
URI-এর একটি উপস্থাপনা প্রদান করে। উপস্থাপনাটিUri.toString()
দ্বারা প্রত্যাবর্তিত হিসাবে একই। - যদি URI একটি বিষয়বস্তু URI না হয়,
coerceToText()
URI-এর একটি উপস্থাপনা প্রদান করে। উপস্থাপনাটিUri.toString()
দ্বারা প্রত্যাবর্তিত হিসাবে একই।
- যদি URI একটি বিষয়বস্তু URI হয় এবং প্রদানকারী একটি পাঠ্য স্ট্রীম ফেরত দিতে পারে,
- অভিপ্রায়
- যদি
ClipData.Item
একটিIntent
হয়—অর্থাৎ,getIntent()
যদি শূন্য না হয়—coerceToText()
এটিকে একটি ইন্টেন্ট URI-তে রূপান্তর করে এবং ফেরত দেয়। উপস্থাপনাটিIntent.toUri(URI_INTENT_SCHEME)
দ্বারা প্রত্যাবর্তনের মতই।
ক্লিপবোর্ড ফ্রেমওয়ার্ক চিত্র 2-এ সংক্ষিপ্ত করা হয়েছে। ডেটা কপি করতে, একটি অ্যাপ্লিকেশন ClipboardManager
গ্লোবাল ক্লিপবোর্ডে একটি ClipData
অবজেক্ট রাখে। ClipData
এক বা একাধিক ClipData.Item
অবজেক্ট এবং একটি ClipDescription
অবজেক্ট থাকে। ডেটা পেস্ট করতে, একটি অ্যাপ্লিকেশন ClipData
পায়, ClipDescription
থেকে তার MIME প্রকার পায় এবং ClipData.Item
থেকে বা ClipData.Item
দ্বারা উল্লেখিত সামগ্রী প্রদানকারীর কাছ থেকে ডেটা পায়।

ক্লিপবোর্ডে কপি করুন
ক্লিপবোর্ডে ডেটা অনুলিপি করতে, গ্লোবাল ClipboardManager
অবজেক্টের একটি হ্যান্ডেল পান, একটি ClipData
অবজেক্ট তৈরি করুন এবং এতে একটি ClipDescription
এবং এক বা একাধিক ClipData.Item
আইটেম অবজেক্ট যোগ করুন। তারপর, ClipboardManager
অবজেক্টে সমাপ্ত ClipData
অবজেক্ট যোগ করুন। এটি নিম্নলিখিত পদ্ধতিতে আরও বর্ণনা করা হয়েছে:
- আপনি যদি একটি বিষয়বস্তু URI ব্যবহার করে ডেটা অনুলিপি করছেন, তাহলে একটি সামগ্রী প্রদানকারী সেট আপ করুন৷
- সিস্টেম ক্লিপবোর্ড পান:
কোটলিন
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 } }
জাভা
... // 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
অবজেক্টে ডেটা অনুলিপি করুন:- পাঠ্যের জন্য
কোটলিন
// Creates a new text clip to put on the clipboard. val clip: ClipData = ClipData.newPlainText("simple text", "Hello, World!")
জাভা
// Creates a new text clip to put on the clipboard. ClipData clip = ClipData.newPlainText("simple text", "Hello, World!");
- একটি URI-এর জন্য
এই স্নিপেট প্রদানকারীর জন্য কন্টেন্ট URI-এ একটি রেকর্ড আইডি এনকোড করে একটি URI তৈরি করে। এই কৌশলটি URI বিভাগে একটি শনাক্তকারী এনকোডিং- এ আরও বিস্তারিতভাবে কভার করা হয়েছে।
কোটলিন
// 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)
জাভা
// 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
তৈরি করে এবং তারপরে এটিকে ক্লিপ অবজেক্টে রাখে:কোটলিন
// 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)
জাভা
// 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);
- পাঠ্যের জন্য
- ক্লিপবোর্ডে নতুন ক্লিপ অবজেক্ট রাখুন:
কোটলিন
// Set the clipboard's primary clip. clipboard.setPrimaryClip(clip)
জাভা
// Set the clipboard's primary clip. clipboard.setPrimaryClip(clip);
ক্লিপবোর্ডে অনুলিপি করার সময় প্রতিক্রিয়া প্রদান করুন
যখন একটি অ্যাপ ক্লিপবোর্ডে বিষয়বস্তু কপি করে তখন ব্যবহারকারীরা ভিজ্যুয়াল ফিডব্যাক আশা করে। এটি অ্যান্ড্রয়েড 13 এবং উচ্চতর ব্যবহারকারীদের জন্য স্বয়ংক্রিয়ভাবে করা হয়, তবে এটি অবশ্যই পূর্ববর্তী সংস্করণগুলিতে ম্যানুয়ালি প্রয়োগ করা উচিত।
অ্যান্ড্রয়েড 13 থেকে শুরু করে, ক্লিপবোর্ডে সামগ্রী যোগ করা হলে সিস্টেমটি একটি স্ট্যান্ডার্ড ভিজ্যুয়াল নিশ্চিতকরণ প্রদর্শন করে। নতুন নিশ্চিতকরণ নিম্নলিখিতগুলি করে:
- কনফার্ম করে কন্টেন্ট সফলভাবে কপি করা হয়েছে।
- অনুলিপি করা বিষয়বস্তুর একটি পূর্বরূপ প্রদান করে।

Android 12L (API লেভেল 32) এবং তার নিচে, ব্যবহারকারীরা নিশ্চিত হতে পারে যে তারা সফলভাবে কন্টেন্ট কপি করেছে বা তারা কি কপি করেছে। এই বৈশিষ্ট্যটি অনুলিপি করার পরে অ্যাপগুলির দ্বারা প্রদর্শিত বিভিন্ন বিজ্ঞপ্তিগুলিকে মানসম্মত করে এবং ব্যবহারকারীদের ক্লিপবোর্ডের উপর আরও নিয়ন্ত্রণের প্রস্তাব দেয়।
ডুপ্লিকেট বিজ্ঞপ্তি এড়িয়ে চলুন
Android 12L (API লেভেল 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() }
ক্লিপবোর্ডে সংবেদনশীল বিষয়বস্তু যোগ করুন
যদি আপনার অ্যাপ ব্যবহারকারীদের ক্লিপবোর্ডে সংবেদনশীল বিষয়বস্তু কপি করতে দেয়, যেমন পাসওয়ার্ড বা ক্রেডিট কার্ডের তথ্য, তাহলে আপনাকে ClipboardManager.setPrimaryClip()
কল করার আগে ClipData
এ ClipDescription
এ একটি পতাকা যোগ করতে হবে। এই ফ্ল্যাগ যুক্ত করা হলে Android 13 এবং উচ্চতর সংস্করণে অনুলিপি করা সামগ্রীর ভিজ্যুয়াল নিশ্চিতকরণে সংবেদনশীল বিষয়বস্তু প্রদর্শিত হতে বাধা দেয়।


সংবেদনশীল বিষয়বস্তু ফ্ল্যাগ করতে, ClipDescription
এ একটি বুলিয়ান অতিরিক্ত যোগ করুন। লক্ষ্যবস্তু API স্তর নির্বিশেষে, সমস্ত অ্যাপকে অবশ্যই এটি করতে হবে।
// 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()
ব্যবহার করে এর পাঠ্যটি আপনার নিজস্ব স্টোরেজে অনুলিপি করুন, যা নিম্নলিখিত পদ্ধতিতে বর্ণিত হয়েছে:
-
getSystemService(CLIPBOARD_SERVICE)
ব্যবহার করে গ্লোবালClipboardManager
অবজেক্ট পান। এছাড়াও, পেস্ট করা পাঠ্য ধারণ করার জন্য একটি বিশ্বব্যাপী পরিবর্তনশীল ঘোষণা করুন:কোটলিন
var clipboard = getSystemService(Context.CLIPBOARD_SERVICE) as ClipboardManager var pasteData: String = ""
জাভা
ClipboardManager clipboard = (ClipboardManager) getSystemService(Context.CLIPBOARD_SERVICE); String pasteData = "";
- বর্তমান কার্যকলাপে আপনাকে "পেস্ট" বিকল্পটি সক্ষম বা নিষ্ক্রিয় করতে হবে কিনা তা নির্ধারণ করুন৷ যাচাই করুন যে ক্লিপবোর্ডে একটি ক্লিপ রয়েছে এবং আপনি ক্লিপ দ্বারা উপস্থাপিত ডেটার ধরন পরিচালনা করতে পারেন:
কোটলিন
// 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 } }
জাভা
// 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 রয়েছে যা প্লেইন টেক্সটকে নির্দেশ করে। নিম্নলিখিত কোড স্নিপেট এটি পরীক্ষা করে, কিন্তু এটি শুধুমাত্র প্লেইন টেক্সট পরিচালনার জন্য কোড দেখায়:
কোটলিন
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 } } } }
জাভা
// 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 প্রকার সরবরাহকারীর কাছ থেকে উপলব্ধ কিনা।
- MIME প্রকার ধারণ করার জন্য একটি বিশ্বব্যাপী পরিবর্তনশীল ঘোষণা করুন:
কোটলিন
// 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"
জাভা
// 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";
- গ্লোবাল ক্লিপবোর্ড পান। এছাড়াও একটি সামগ্রী সমাধানকারী পান যাতে আপনি সামগ্রী প্রদানকারীকে অ্যাক্সেস করতে পারেন:
কোটলিন
// Gets a handle to the Clipboard Manager. val clipboard = getSystemService(Context.CLIPBOARD_SERVICE) as ClipboardManager // Gets a content resolver instance. val cr = contentResolver
জাভা
// Gets a handle to the Clipboard Manager. ClipboardManager clipboard = (ClipboardManager) getSystemService(Context.CLIPBOARD_SERVICE); // Gets a content resolver instance. ContentResolver cr = getContentResolver();
- ক্লিপবোর্ড থেকে প্রাথমিক ক্লিপটি পান এবং একটি URI হিসাবে এর বিষয়বস্তু পান:
কোটলিন
// 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
জাভা
// 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 একটি বিষয়বস্তু URI কিনা তা পরীক্ষা করুন।Uri
কোনো বৈধ বিষয়বস্তু প্রদানকারীকে নির্দেশ না করলে এই পদ্ধতিটি শূন্য হয়ে যায়।কোটলিন
// If the clipboard contains a URI reference... pasteUri?.let { // ...is this a content URI? val uriMimeType: String? = cr.getType(it)
জাভা
// If the clipboard contains a URI reference... if (pasteUri != null) { // ...is this a content URI? String uriMimeType = cr.getType(pasteUri);
- বিষয়বস্তু প্রদানকারী একটি MIME প্রকার সমর্থন করে কিনা পরীক্ষা করুন যা অ্যাপ্লিকেশন বোঝে। যদি এটি হয়, তথ্য পেতে
ContentResolver.query()
কল করুন। রিটার্ন মান হল একটিCursor
।কোটলিন
// 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. } } } }
জাভা
// 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()
এ কল করুন। নিম্নলিখিত স্নিপেট এটি প্রদর্শন করে:
কোটলিন
// 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. }
জাভা
// 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 (API লেভেল 31) এবং তার উপরে, আপনার অ্যাপ getPrimaryClip()
কল করলে সিস্টেম সাধারণত একটি টোস্ট বার্তা দেখায়। বার্তার ভিতরের পাঠ্যটিতে নিম্নলিখিত বিন্যাস রয়েছে:
APP pasted from your clipboard
যখন আপনার অ্যাপ নিম্নলিখিতগুলির মধ্যে একটি করে তখন সিস্টেমটি একটি টোস্ট বার্তা দেখায় না:
- আপনার নিজের অ্যাপ থেকে
ClipData
অ্যাক্সেস করে। - একটি নির্দিষ্ট অ্যাপ থেকে বারবার
ClipData
অ্যাক্সেস করে। টোস্টটি তখনই প্রদর্শিত হয় যখন আপনার অ্যাপটি সেই অ্যাপ থেকে প্রথমবারের মতো ডেটা অ্যাক্সেস করে। - ক্লিপ অবজেক্টের জন্য মেটাডেটা পুনরুদ্ধার করে, যেমন
getPrimaryClipDescription()
এর পরিবর্তেgetPrimaryClip()
কল করে।
জটিল তথ্য অনুলিপি করতে সামগ্রী প্রদানকারী ব্যবহার করুন
বিষয়বস্তু প্রদানকারীরা জটিল ডেটা যেমন ডাটাবেস রেকর্ড বা ফাইল স্ট্রীম অনুলিপি করতে সমর্থন করে। ডেটা অনুলিপি করতে, ক্লিপবোর্ডে একটি বিষয়বস্তু URI রাখুন। অ্যাপ্লিকেশানগুলি পেস্ট করার পরে ক্লিপবোর্ড থেকে এই URI পান এবং ডাটাবেস ডেটা বা ফাইল স্ট্রিম বর্ণনাকারী পুনরুদ্ধার করতে এটি ব্যবহার করুন।
যেহেতু পেস্ট করা অ্যাপ্লিকেশনটিতে শুধুমাত্র আপনার ডেটার জন্য ইউআরআই বিষয়বস্তু রয়েছে, তাই এটি জানতে হবে কোন অংশটি পুনরুদ্ধার করতে হবে। আপনি URI-তে ডেটার জন্য একটি শনাক্তকারী এনকোড করে এই তথ্য প্রদান করতে পারেন, অথবা আপনি একটি অনন্য URI প্রদান করতে পারেন যা আপনি যে ডেটা কপি করতে চান তা ফেরত দেয়। আপনি কোন কৌশলটি বেছে নেবেন তা আপনার ডেটার সংগঠনের উপর নির্ভর করে।
নিম্নলিখিত বিভাগগুলি বর্ণনা করে যে কীভাবে URI সেট আপ করতে হয়, জটিল ডেটা সরবরাহ করতে হয় এবং ফাইল স্ট্রিম সরবরাহ করতে হয়। বর্ণনাগুলি অনুমান করে যে আপনি সামগ্রী প্রদানকারী ডিজাইনের সাধারণ নীতিগুলির সাথে পরিচিত৷
URI-তে একটি শনাক্তকারী এনকোড করুন
একটি URI দিয়ে ক্লিপবোর্ডে ডেটা অনুলিপি করার জন্য একটি দরকারী কৌশল হল URI-তে ডেটার জন্য একটি শনাক্তকারীকে এনকোড করা। আপনার বিষয়বস্তু প্রদানকারী তারপর URI থেকে শনাক্তকারী পেতে পারে এবং ডেটা পুনরুদ্ধার করতে এটি ব্যবহার করতে পারে। পেস্টিং অ্যাপ্লিকেশনটি সনাক্তকারী বিদ্যমান তা জানতে হবে না। এটিকে শুধুমাত্র ক্লিপবোর্ড থেকে আপনার "রেফারেন্স" - URI প্লাস শনাক্তকারী - পেতে হবে, এটি আপনার সামগ্রী প্রদানকারীকে দিন এবং ডেটা ফেরত পেতে হবে৷
আপনি সাধারণত একটি বিষয়বস্তু URI-এ একটি শনাক্তকারীকে URI-এর শেষে সংযুক্ত করে এনকোড করেন। উদাহরণস্বরূপ, ধরুন আপনি আপনার প্রদানকারী URI কে নিম্নলিখিত স্ট্রিং হিসাবে সংজ্ঞায়িত করেছেন:
"content://com.example.contacts"
আপনি যদি এই URI-তে একটি নাম এনকোড করতে চান তবে নিম্নলিখিত কোড স্নিপেটটি ব্যবহার করুন:
কোটলিন
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)
জাভা
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"
ইউআরআই অনুলিপি করার জন্য আপনি অন্য পথ যোগ করতে পারেন:
"content://com.example.contacts/copying"
তারপর আপনি প্যাটার্ন-ম্যাচিং দ্বারা একটি "অনুলিপি" URI সনাক্ত করতে পারেন এবং কপি এবং পেস্ট করার জন্য নির্দিষ্ট কোড দিয়ে এটি পরিচালনা করতে পারেন।
আপনি সাধারণত এনকোডিং কৌশল ব্যবহার করেন যদি আপনি ইতিমধ্যেই আপনার ডেটা সংগঠিত করার জন্য কোনও সামগ্রী প্রদানকারী, অভ্যন্তরীণ ডাটাবেস বা অভ্যন্তরীণ টেবিল ব্যবহার করেন। এই ক্ষেত্রে, আপনার কাছে একাধিক ডেটা রয়েছে যা আপনি অনুলিপি করতে চান এবং সম্ভবত প্রতিটি অংশের জন্য একটি অনন্য শনাক্তকারী। পেস্টিং অ্যাপ্লিকেশন থেকে একটি প্রশ্নের উত্তরে, আপনি এটির শনাক্তকারী দ্বারা ডেটা দেখতে পারেন এবং এটি ফেরত দিতে পারেন।
যদি আপনার কাছে একাধিক ডেটা না থাকে, তাহলে সম্ভবত আপনাকে একটি শনাক্তকারী এনকোড করার দরকার নেই। আপনি একটি URI ব্যবহার করতে পারেন যা আপনার প্রদানকারীর জন্য অনন্য। একটি প্রশ্নের উত্তরে, আপনার প্রদানকারী বর্তমানে এটিতে থাকা ডেটা ফেরত দেয়।
ডেটা স্ট্রাকচার কপি করুন
ContentProvider
উপাদানের একটি সাবক্লাস হিসাবে জটিল ডেটা অনুলিপি এবং আটকানোর জন্য একটি সামগ্রী প্রদানকারী সেট আপ করুন৷ আপনি ক্লিপবোর্ডে যে ইউআরআইটি রেখেছেন তা এনকোড করুন যাতে এটি আপনি যে সঠিক রেকর্ডটি প্রদান করতে চান তা নির্দেশ করে। উপরন্তু, আপনার আবেদনের বিদ্যমান অবস্থা বিবেচনা করুন:
- আপনার যদি ইতিমধ্যে একটি বিষয়বস্তু প্রদানকারী থাকে, আপনি এটির কার্যকারিতা যোগ করতে পারেন। ডেটা পেস্ট করতে চায় এমন অ্যাপ্লিকেশন থেকে আসা URIগুলি পরিচালনা করার জন্য আপনাকে শুধুমাত্র এটির
query()
পদ্ধতি পরিবর্তন করতে হবে। আপনি সম্ভবত একটি "অনুলিপি" URI প্যাটার্ন পরিচালনা করার পদ্ধতিটি পরিবর্তন করতে চান। - যদি আপনার অ্যাপ্লিকেশন একটি অভ্যন্তরীণ ডাটাবেস বজায় রাখে, তাহলে আপনি এটি থেকে অনুলিপি করার সুবিধার্থে এই ডাটাবেসটিকে একটি সামগ্রী প্রদানকারীতে স্থানান্তর করতে চাইতে পারেন।
- আপনি যদি একটি ডাটাবেস ব্যবহার না করেন, তাহলে আপনি একটি সাধারণ বিষয়বস্তু প্রদানকারীকে প্রয়োগ করতে পারেন যার একমাত্র উদ্দেশ্য হল ক্লিপবোর্ড থেকে পেস্ট করা অ্যাপ্লিকেশনগুলিতে ডেটা অফার করা৷
বিষয়বস্তু প্রদানকারীতে, অন্তত নিম্নলিখিত পদ্ধতিগুলিকে ওভাররাইড করুন:
-
query()
- পেস্ট করা অ্যাপ্লিকেশানগুলি ধরে নেয় যে তারা ক্লিপবোর্ডে আপনার দেওয়া URI দিয়ে এই পদ্ধতিটি ব্যবহার করে আপনার ডেটা পেতে পারে৷ অনুলিপি সমর্থন করার জন্য, এই পদ্ধতিটি একটি বিশেষ "কপি" পাথ ধারণকারী URI সনাক্ত করুন৷ তারপরে আপনার অ্যাপ্লিকেশনটি ক্লিপবোর্ডে রাখার জন্য একটি "অনুলিপি" URI তৈরি করতে পারে, যাতে কপি পাথ থাকে এবং আপনি যে সঠিক রেকর্ডটি কপি করতে চান তার একটি পয়েন্টার থাকে৷
-
getType()
- আপনি যে ডেটা অনুলিপি করতে চান তার জন্য এই পদ্ধতিটি অবশ্যই MIME প্রকারগুলি প্রদান করবে৷ নতুন
ClipData
অবজেক্টে MIME প্রকারগুলি স্থাপন করতেnewUri()
পদ্ধতিটিgetType()
কল করে।জটিল ডেটার জন্য MIME প্রকারগুলি বিষয়বস্তু প্রদানকারীগুলিতে বর্ণনা করা হয়েছে৷
আপনার অন্য কোন সামগ্রী প্রদানকারী পদ্ধতির প্রয়োজন নেই, যেমন insert()
বা update()
। একটি পেস্টিং অ্যাপ্লিকেশনের জন্য শুধুমাত্র আপনার সমর্থিত MIME প্রকারগুলি পেতে হবে এবং আপনার প্রদানকারীর কাছ থেকে ডেটা অনুলিপি করতে হবে৷ আপনার যদি ইতিমধ্যেই এই পদ্ধতিগুলি থাকে তবে তারা অনুলিপি ক্রিয়াকলাপে হস্তক্ষেপ করবে না।
নিম্নলিখিত স্নিপেটগুলি দেখায় কিভাবে জটিল ডেটা কপি করতে আপনার অ্যাপ্লিকেশন সেট আপ করবেন:
আপনার অ্যাপ্লিকেশনের জন্য বিশ্বব্যাপী ধ্রুবকগুলিতে, একটি বেস URI স্ট্রিং এবং একটি পাথ ঘোষণা করুন যা URI স্ট্রিংগুলি সনাক্ত করে যা আপনি ডেটা অনুলিপি করতে ব্যবহার করছেন। অনুলিপি করা ডেটার জন্য একটি MIME প্রকারও ঘোষণা করুন।
কোটলিন
// 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"
জাভা
// 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 রাখুন।
কোটলিন
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) } }
জাভা
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গুলির সাথে মেলে।
কোটলিন
// 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() { ... }
জাভা
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 প্যাটার্ন পরিচালনা করতে পারে, তবে ক্লিপবোর্ড কপি করার ক্রিয়াকলাপের জন্য শুধুমাত্র প্যাটার্ন দেখায়।কোটলিন
// 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. } } ... }
জাভা
// 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. ... }
অনুলিপি করা ডেটার জন্য একটি উপযুক্ত MIME প্রকার ফেরত দিতে
getType()
পদ্ধতি সেট আপ করুন:কোটলিন
// Sets up your provider's getType() method. override fun getType(uri: Uri): String? { ... return when(sUriMatcher.match(uri)) { GET_SINGLE_CONTACT -> MIME_TYPE_CONTACT ... } }
জাভা
// 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 পেতে হয় এবং ডেটা পেতে এবং পেস্ট করতে এটি ব্যবহার করতে হয়।
ডেটা স্ট্রীম কপি করুন
আপনি স্ট্রিম হিসাবে প্রচুর পরিমাণে পাঠ্য এবং বাইনারি ডেটা কপি এবং পেস্ট করতে পারেন। ডেটাতে নিম্নলিখিতগুলির মতো ফর্ম থাকতে পারে:
- প্রকৃত ডিভাইসে সঞ্চিত ফাইল
- সকেট থেকে প্রবাহ
- একটি প্রদানকারীর অন্তর্নিহিত ডাটাবেস সিস্টেমে প্রচুর পরিমাণে ডেটা সংরক্ষিত
ডেটা স্ট্রিমগুলির জন্য একটি বিষয়বস্তু প্রদানকারী একটি Cursor
অবজেক্টের পরিবর্তে একটি ফাইল বর্ণনাকারী বস্তুর সাথে তার ডেটাতে অ্যাক্সেস প্রদান করে, যেমন AssetFileDescriptor
। পেস্ট করা অ্যাপ্লিকেশনটি এই ফাইল বর্ণনাকারী ব্যবহার করে ডেটা স্ট্রিমটি পড়ে।
একটি প্রদানকারীর সাথে একটি ডেটা স্ট্রিম অনুলিপি করার জন্য আপনার অ্যাপ্লিকেশন সেট আপ করতে, এই পদক্ষেপগুলি অনুসরণ করুন:
- আপনি ক্লিপবোর্ডে যে ডেটা স্ট্রীমটি রাখছেন তার জন্য একটি সামগ্রী URI সেট আপ করুন৷ এটি করার বিকল্পগুলির মধ্যে নিম্নলিখিতগুলি অন্তর্ভুক্ত রয়েছে:
- URI বিভাগে ডেটা স্ট্রীমের জন্য একটি শনাক্তকারীকে এনকোড করুন, যেমন URI বিভাগে একটি শনাক্তকারীকে এনকোড করুন এবং তারপরে আপনার প্রদানকারীতে একটি সারণী বজায় রাখুন যাতে শনাক্তকারী এবং সংশ্লিষ্ট স্ট্রিম নাম থাকে।
- ইউআরআই-তে সরাসরি স্ট্রিমের নাম এনকোড করুন।
- একটি অনন্য URI ব্যবহার করুন যা সর্বদা প্রদানকারীর কাছ থেকে বর্তমান স্ট্রীম ফেরত দেয়। আপনি যদি এই বিকল্পটি ব্যবহার করেন, আপনি যখনই URI ব্যবহার করে ক্লিপবোর্ডে স্ট্রীমটি অনুলিপি করবেন তখনই একটি ভিন্ন স্ট্রিমের দিকে নির্দেশ করতে আপনার প্রদানকারীকে আপডেট করতে ভুলবেন না।
- আপনি অফার করার পরিকল্পনা করছেন প্রতিটি ধরণের ডেটা স্ট্রিমের জন্য একটি MIME প্রকার প্রদান করুন৷ পেস্ট করা অ্যাপ্লিকেশনগুলি ক্লিপবোর্ডে ডেটা পেস্ট করতে পারে কিনা তা নির্ধারণ করতে এই তথ্যের প্রয়োজন৷
-
ContentProvider
পদ্ধতির একটি প্রয়োগ করুন যা একটি স্ট্রিমের জন্য একটি ফাইল বর্ণনাকারী প্রদান করে। আপনি যদি কন্টেন্ট URI-তে আইডেন্টিফায়ার এনকোড করেন, তাহলে কোন স্ট্রিমটি খুলতে হবে তা নির্ধারণ করতে এই পদ্ধতিটি ব্যবহার করুন। - ক্লিপবোর্ডে ডেটা স্ট্রীম কপি করতে, কন্টেন্ট URI তৈরি করুন এবং ক্লিপবোর্ডে রাখুন।
একটি ডেটা স্ট্রীম পেস্ট করার জন্য, একটি অ্যাপ্লিকেশন ক্লিপবোর্ড থেকে ক্লিপ পায়, URI পায় এবং একটি ContentResolver
ফাইল বর্ণনাকারী পদ্ধতিতে কল করার জন্য এটি ব্যবহার করে যা স্ট্রিমটি খোলে। ContentResolver
পদ্ধতিটি সংশ্লিষ্ট ContentProvider
পদ্ধতিকে কল করে, এটিকে বিষয়বস্তু URI পাস করে। আপনার প্রদানকারী ফাইল বর্ণনাকারীকে ContentResolver
পদ্ধতিতে ফেরত দেয়। আটকানো অ্যাপ্লিকেশনটির তখন স্ট্রিম থেকে ডেটা পড়ার দায়িত্ব রয়েছে।
নিম্নলিখিত তালিকাটি একটি বিষয়বস্তু প্রদানকারীর জন্য সবচেয়ে গুরুত্বপূর্ণ ফাইল বর্ণনাকারী পদ্ধতিগুলি দেখায়৷ এইগুলির প্রত্যেকটির একটি সংশ্লিষ্ট ContentResolver
পদ্ধতি রয়েছে যার সাথে পদ্ধতির নামের সাথে "বিবরণকারী" স্ট্রিং যুক্ত করা হয়েছে। উদাহরণস্বরূপ, openAssetFile()
এর ContentResolver
এনালগ হল openAssetFileDescriptor()
।
-
openTypedAssetFile()
এই পদ্ধতিটি একটি সম্পদ ফাইল বর্ণনাকারী প্রদান করে, কিন্তু শুধুমাত্র যদি প্রদত্ত MIME প্রকার প্রদানকারী দ্বারা সমর্থিত হয়। কলার—যে অ্যাপ্লিকেশন পেস্ট করছে—একটি MIME ধরনের প্যাটার্ন প্রদান করে। অ্যাপ্লিকেশনটির বিষয়বস্তু প্রদানকারী যেটি ক্লিপবোর্ডে একটি URI অনুলিপি করে একটি
AssetFileDescriptor
ফাইল হ্যান্ডেল ফেরত দেয় যদি এটি সেই MIME প্রকার প্রদান করতে পারে এবং এটি না করতে পারলে একটি ব্যতিক্রম ছুড়ে দেয়৷এই পদ্ধতি ফাইলের উপবিভাগ পরিচালনা করে। বিষয়বস্তু প্রদানকারী ক্লিপবোর্ডে কপি করেছে এমন সম্পদ পড়তে আপনি এটি ব্যবহার করতে পারেন।
-
openAssetFile()
- এই পদ্ধতিটি
openTypedAssetFile()
এর আরও সাধারণ রূপ। এটি অনুমোদিত MIME প্রকারের জন্য ফিল্টার করে না, তবে এটি ফাইলের উপবিভাগ পড়তে পারে। -
openFile()
- এটি
openAssetFile()
এর আরও সাধারণ রূপ। এটি ফাইলের উপবিভাগ পড়তে পারে না।
আপনি ঐচ্ছিকভাবে আপনার ফাইল বর্ণনাকারী পদ্ধতির সাথে openPipeHelper()
পদ্ধতি ব্যবহার করতে পারেন। এটি পেস্টিং অ্যাপ্লিকেশনটিকে একটি পাইপ ব্যবহার করে একটি ব্যাকগ্রাউন্ড থ্রেডে স্ট্রিম ডেটা পড়তে দেয়৷ এই পদ্ধতিটি ব্যবহার করতে, ContentProvider.PipeDataWriter
ইন্টারফেস প্রয়োগ করুন।
ডিজাইন কার্যকর কপি এবং পেস্ট কার্যকারিতা
আপনার অ্যাপ্লিকেশনের জন্য কার্যকর কপি এবং পেস্ট কার্যকারিতা ডিজাইন করতে, এই পয়েন্টগুলি মনে রাখবেন:
- যে কোনো সময়, ক্লিপবোর্ডে শুধুমাত্র একটি ক্লিপ থাকে। সিস্টেমের যেকোনো অ্যাপ্লিকেশন দ্বারা একটি নতুন অনুলিপি অপারেশন পূর্ববর্তী ক্লিপটি ওভাররাইট করে। যেহেতু ব্যবহারকারী আপনার অ্যাপ্লিকেশন থেকে দূরে নেভিগেট করতে পারে এবং ফিরে আসার আগে অনুলিপি করতে পারে, তাই আপনি অনুমান করতে পারবেন না যে ক্লিপবোর্ডে সেই ক্লিপটি রয়েছে যা ব্যবহারকারী আপনার অ্যাপ্লিকেশনে পূর্বে অনুলিপি করেছেন৷
- ক্লিপ প্রতি একাধিক
ClipData.Item
অবজেক্টের উদ্দেশ্য হল একটি একক নির্বাচনের বিভিন্ন ধরনের রেফারেন্সের পরিবর্তে একাধিক নির্বাচনের অনুলিপি এবং আটকানো সমর্থন করা। আপনি সাধারণত একটি ক্লিপের সমস্তClipData.Item
অবজেক্ট একই ফর্ম চান৷ অর্থাৎ, সেগুলি অবশ্যই সাধারণ পাঠ্য, বিষয়বস্তু URI, বাIntent
হতে হবে এবং মিশ্রিত নয়৷ - যখন আপনি ডেটা প্রদান করেন, আপনি বিভিন্ন MIME উপস্থাপনা অফার করতে পারেন।
ClipDescription
এ আপনি সমর্থন করেন এমন MIME প্রকারগুলি যোগ করুন এবং তারপর আপনার সামগ্রী প্রদানকারীতে MIME প্রকারগুলি প্রয়োগ করুন৷ - আপনি যখন ক্লিপবোর্ড থেকে ডেটা পান, আপনার অ্যাপ্লিকেশনটি উপলব্ধ MIME প্রকারগুলি পরীক্ষা করার জন্য এবং তারপর কোনটি ব্যবহার করতে হবে তা সিদ্ধান্ত নেওয়ার জন্য দায়ী৷ এমনকি যদি ক্লিপবোর্ডে একটি ক্লিপ থাকে এবং ব্যবহারকারী একটি পেস্টের অনুরোধ করে, আপনার অ্যাপ্লিকেশনটিকে পেস্ট করার প্রয়োজন নেই৷ MIME টাইপ সামঞ্জস্যপূর্ণ হলে পেস্ট করুন। আপনি
coerceToText()
ব্যবহার করে ক্লিপবোর্ডের ডেটা টেক্সট করতে বাধ্য করতে পারেন। যদি আপনার অ্যাপ্লিকেশানটি উপলব্ধ MIME প্রকারের একাধিক সমর্থন করে, তাহলে আপনি ব্যবহারকারীকে কোনটি ব্যবহার করবেন তা বেছে নিতে দিতে পারেন।
Android অনুলিপি এবং আটকানোর জন্য একটি শক্তিশালী ক্লিপবোর্ড-ভিত্তিক কাঠামো প্রদান করে। এটি টেক্সট স্ট্রিং, জটিল ডেটা স্ট্রাকচার, টেক্সট এবং বাইনারি স্ট্রিম ডেটা এবং অ্যাপ্লিকেশন সম্পদ সহ সাধারণ এবং জটিল ডেটা প্রকারগুলিকে সমর্থন করে। সরল পাঠ্য ডেটা সরাসরি ক্লিপবোর্ডে সংরক্ষণ করা হয়, যখন জটিল ডেটা একটি রেফারেন্স হিসাবে সংরক্ষণ করা হয় যা পেস্টিং অ্যাপ্লিকেশন একটি বিষয়বস্তু প্রদানকারীর সাথে সমাধান করে। অনুলিপি এবং আটকানো একটি অ্যাপ্লিকেশনের মধ্যে এবং ফ্রেমওয়ার্ক বাস্তবায়নকারী অ্যাপ্লিকেশনগুলির মধ্যে উভয়ই কাজ করে।
যেহেতু ফ্রেমওয়ার্কের একটি অংশ সামগ্রী সরবরাহকারী ব্যবহার করে, তাই এই নথিটি Android সামগ্রী প্রদানকারী API এর সাথে কিছু পরিচিতি অনুমান করে, যা বিষয়বস্তু প্রদানকারীতে বর্ণিত হয়েছে৷
ক্লিপবোর্ডে বিষয়বস্তু অনুলিপি করার সময় ব্যবহারকারীরা প্রতিক্রিয়া আশা করে, তাই কপি এবং পেস্ট করার ক্ষমতা দেয় এমন কাঠামোর পাশাপাশি, Android 13 (API স্তর 33) এবং উচ্চতর কপি করার সময় Android ব্যবহারকারীদের একটি ডিফল্ট UI দেখায়। এই বৈশিষ্ট্যের কারণে, নকল বিজ্ঞপ্তির ঝুঁকি রয়েছে। আপনি এই প্রান্ত কেস সম্পর্কে আরও জানতে পারেন ডুপ্লিকেট বিজ্ঞপ্তিগুলি এড়িয়ে চলুন বিভাগে৷

Android 12L (API লেভেল 32) এবং তার নিচে কপি করার সময় ব্যবহারকারীদের ম্যানুয়ালি ফিডব্যাক প্রদান করুন। এই নথিতে এই জন্য সুপারিশ দেখুন.
ক্লিপবোর্ড ফ্রেমওয়ার্ক
যখন আপনি ক্লিপবোর্ড ফ্রেমওয়ার্ক ব্যবহার করেন, তখন একটি ক্লিপ অবজেক্টে ডেটা রাখুন এবং তারপর ক্লিপ অবজেক্টটিকে সিস্টেম-ওয়াইড ক্লিপবোর্ডে রাখুন। ক্লিপ অবজেক্ট তিনটি ফর্মের একটি নিতে পারে:
- পাঠ্য
- একটি পাঠ্য স্ট্রিং। স্ট্রিংটি সরাসরি ক্লিপ অবজেক্টে রাখুন, যা আপনি তারপর ক্লিপবোর্ডে রাখবেন। স্ট্রিংটি পেস্ট করতে, ক্লিপবোর্ড থেকে ক্লিপ অবজেক্টটি পান এবং স্ট্রিংটি আপনার অ্যাপ্লিকেশনের স্টোরেজে অনুলিপি করুন।
- ইউআরআই
- একটি
Uri
অবজেক্ট যা URI-এর যেকোনো রূপকে প্রতিনিধিত্ব করে। এটি মূলত একটি বিষয়বস্তু প্রদানকারীর কাছ থেকে জটিল ডেটা অনুলিপি করার জন্য। ডেটা কপি করতে, একটিUri
অবজেক্টকে একটি ক্লিপ অবজেক্টে রাখুন এবং ক্লিপ অবজেক্টটিকে ক্লিপবোর্ডে রাখুন। ডেটা পেস্ট করতে, ক্লিপ অবজেক্ট পান,Uri
অবজেক্ট পান, এটি একটি ডেটা উৎসে সমাধান করুন, যেমন একটি সামগ্রী প্রদানকারী, এবং উৎস থেকে ডেটা আপনার অ্যাপ্লিকেশনের স্টোরেজে অনুলিপি করুন। - অভিপ্রায়
- একটি
Intent
। এটি অনুলিপি অ্যাপ্লিকেশন শর্টকাট সমর্থন করে. ডেটা কপি করতে, একটিIntent
তৈরি করুন, এটি একটি ক্লিপ অবজেক্টে রাখুন এবং ক্লিপবোর্ডে ক্লিপ অবজেক্ট রাখুন। ডেটা পেস্ট করতে, ক্লিপ অবজেক্টটি পান এবং তারপরে আপনার অ্যাপ্লিকেশনের মেমরি এলাকায়Intent
অবজেক্টটি অনুলিপি করুন।
ক্লিপবোর্ড এক সময়ে শুধুমাত্র একটি ক্লিপ বস্তু ধারণ করে। যখন একটি অ্যাপ্লিকেশন ক্লিপবোর্ডে একটি ক্লিপ অবজেক্ট রাখে, পূর্ববর্তী ক্লিপ অবজেক্টটি অদৃশ্য হয়ে যায়।
আপনি যদি ব্যবহারকারীদের আপনার অ্যাপ্লিকেশনে ডেটা পেস্ট করতে দিতে চান তবে আপনাকে সব ধরনের ডেটা পরিচালনা করতে হবে না। ব্যবহারকারীদের পেস্ট করার বিকল্প দেওয়ার আগে আপনি ক্লিপবোর্ডে ডেটা পরীক্ষা করতে পারেন। একটি নির্দিষ্ট ডেটা ফর্ম থাকার পাশাপাশি, ক্লিপ অবজেক্টে মেটাডেটাও থাকে যা আপনাকে বলে যে MIME প্রকারগুলি উপলব্ধ। এই মেটাডেটা আপনাকে সিদ্ধান্ত নিতে সাহায্য করে যে আপনার অ্যাপ্লিকেশনটি ক্লিপবোর্ড ডেটার সাথে কার্যকর কিছু করতে পারে কিনা। উদাহরণস্বরূপ, যদি আপনার কাছে এমন একটি অ্যাপ্লিকেশন থাকে যা প্রাথমিকভাবে পাঠ্য পরিচালনা করে, আপনি ক্লিপ অবজেক্টগুলিকে উপেক্ষা করতে চাইতে পারেন যেগুলিতে একটি URI বা অভিপ্রায় রয়েছে৷
আপনি ক্লিপবোর্ডে ডেটার ফর্ম নির্বিশেষে ব্যবহারকারীদের পাঠ্য পেস্ট করতে দিতে চাইতে পারেন। এটি করার জন্য, ক্লিপবোর্ড ডেটাকে একটি পাঠ্য উপস্থাপনায় জোর করুন এবং তারপরে এই পাঠ্যটি আটকান। এটি ক্লিপবোর্ড থেকে পাঠ্য বিভাগে বাধ্য করা হয়েছে।
ক্লিপবোর্ড ক্লাস
এই বিভাগটি ক্লিপবোর্ড ফ্রেমওয়ার্ক দ্বারা ব্যবহৃত ক্লাস বর্ণনা করে।
ক্লিপবোর্ড ম্যানেজার
অ্যান্ড্রয়েড সিস্টেম ক্লিপবোর্ড গ্লোবাল ClipboardManager
ক্লাস দ্বারা প্রতিনিধিত্ব করা হয়। সরাসরি এই ক্লাসটি ইনস্ট্যান্টিয়েট করবেন না। পরিবর্তে, getSystemService(CLIPBOARD_SERVICE)
আহ্বান করে এটির একটি রেফারেন্স পান।
ClipData, ClipData.Item, এবং ClipDescription
ক্লিপবোর্ডে ডেটা যোগ করতে, একটি ClipData
অবজেক্ট তৈরি করুন যাতে ডেটা এবং ডেটার বিবরণ থাকে। ক্লিপবোর্ডে একবারে একটি ClipData
থাকে। একটি ClipData
একটি ClipDescription
অবজেক্ট এবং এক বা একাধিক ClipData.Item
অবজেক্ট ধারণ করে।
একটি ClipDescription
অবজেক্টে ক্লিপ সম্পর্কে মেটাডেটা থাকে। বিশেষ করে, এটিতে ক্লিপের ডেটার জন্য উপলব্ধ MIME প্রকারের একটি অ্যারে রয়েছে। উপরন্তু, Android 12 (API লেভেল 31) এবং উচ্চতর, মেটাডেটা অবজেক্টে স্টাইলাইজড টেক্সট আছে কিনা এবং অবজেক্টের টেক্সটের ধরন সম্পর্কে তথ্য অন্তর্ভুক্ত করে। আপনি যখন ক্লিপবোর্ডে একটি ক্লিপ রাখেন, তখন এই তথ্যটি অ্যাপ্লিকেশন পেস্ট করার জন্য উপলব্ধ থাকে, যা তারা ক্লিপ ডেটা পরিচালনা করতে পারে কিনা তা পরীক্ষা করতে পারে।
একটি ClipData.Item
অবজেক্টে পাঠ্য, URI, বা উদ্দেশ্য ডেটা থাকে:
- পাঠ্য
- একটি
CharSequence
। - ইউআরআই
- একটি
Uri
। এটি সাধারণত একটি বিষয়বস্তু প্রদানকারী URI ধারণ করে, যদিও যেকোনো URI অনুমোদিত। যে অ্যাপ্লিকেশনটি ডেটা সরবরাহ করে সেটি ক্লিপবোর্ডে URI রাখে। যে অ্যাপ্লিকেশনগুলি ডেটা পেস্ট করতে চায় তারা ক্লিপবোর্ড থেকে ইউআরআই পায় এবং সামগ্রী সরবরাহকারী বা অন্যান্য ডেটা উত্স অ্যাক্সেস করতে এবং ডেটা পুনরুদ্ধার করতে এটি ব্যবহার করে৷ - অভিপ্রায়
- একটি
Intent
। এই ডেটা টাইপ আপনাকে ক্লিপবোর্ডে একটি অ্যাপ্লিকেশন শর্টকাট কপি করতে দেয়। ব্যবহারকারীরা পরবর্তীতে ব্যবহারের জন্য তাদের অ্যাপ্লিকেশনে শর্টকাট পেস্ট করতে পারেন।
আপনি একটি ক্লিপে একাধিক ClipData.Item
বস্তু যোগ করতে পারেন। এটি ব্যবহারকারীদের একক ক্লিপ হিসাবে একাধিক নির্বাচন কপি এবং পেস্ট করতে দেয়। উদাহরণস্বরূপ, যদি আপনার একটি তালিকা উইজেট থাকে যা ব্যবহারকারীকে একবারে একাধিক আইটেম নির্বাচন করতে দেয়, আপনি একবারে সমস্ত আইটেম ক্লিপবোর্ডে অনুলিপি করতে পারেন। এটি করার জন্য, প্রতিটি তালিকা আইটেমের জন্য একটি পৃথক ClipData.Item
তৈরি করুন এবং তারপর ClipData
বস্তুতে ClipData.Item
অবজেক্ট যোগ করুন।
ক্লিপডেটা সুবিধার পদ্ধতি
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
অবজেক্টে একটি URI রয়েছে।ClipDescription
অবজেক্টের লেবেলlabel
সেট করা আছে। যদি URI একটি বিষয়বস্তু URI হয়—অর্থাৎ, যদিUri.getScheme()
content:
— পদ্ধতিটি সামগ্রী প্রদানকারীর কাছ থেকে উপলব্ধ MIME প্রকারগুলি পুনরুদ্ধার করতেresolver
প্রদত্তContentResolver
অবজেক্ট ব্যবহার করে। এটি তারপরClipDescription
তাদের সঞ্চয় করে। একটি ইউআরআইয়ের জন্য যা কোনওcontent:
ইউআরআই, পদ্ধতিটি মাইম টাইপটিMIMETYPE_TEXT_URILIST
সেট করে।ইউআরআই থেকে একটি ক্লিপ তৈরি করতে
newUri()
ব্যবহার করুন - বিশেষত একটিcontent:
ইউআরআই। -
newIntent(label, intent)
- একটি
ClipData
অবজেক্টটি ফেরত দেয় যার এককClipData.Item
অবজেক্টে একটিIntent
রয়েছে।ClipDescription
অবজেক্টের লেবেলটিlabel
সেট করা আছে। মাইম টাইপটিMIMETYPE_TEXT_INTENT
এ সেট করা আছে।কোনও
Intent
অবজেক্ট থেকে একটি ক্লিপ তৈরি করতেnewIntent()
ব্যবহার করুন।
ক্লিপবোর্ডের ডেটা পাঠাতে বাধ্য করুন
এমনকি যদি আপনার অ্যাপ্লিকেশনটি কেবল পাঠ্য পরিচালনা করে তবে আপনি ক্লিপবোর্ড থেকে নন-টেক্সট ডেটা ClipData.Item.coerceToText()
পদ্ধতির সাথে রূপান্তর করে অনুলিপি করতে পারেন।
এই পদ্ধতিটি ClipData.Item
-এর ডেটা পাঠাতে রূপান্তর করে এবং একটি CharSequence
ফেরত দেয়। ClipData.Item.coerceToText()
রিটার্নগুলি যে মানটি ClipData.Item
-তে ডেটা ফর্মের উপর ভিত্তি করে:
- পাঠ্য
- যদি
ClipData.Item
পাঠ্য হয় - এটি হ'ল, যদিgetText()
নাল না হয় - Cercototext () পাঠ্যটি ফেরত দেয়। - ইউআরআই
- যদি
ClipData.Item
একটি ইউআরআই হয় - তা হ'ল, যদিgetUri()
NULL—coerceToText()
না হয় তবে এটি একটি সামগ্রী URI হিসাবে ব্যবহার করার চেষ্টা করে।- যদি ইউআরআই কোনও সামগ্রী ইউআরআই হয় এবং সরবরাহকারী কোনও পাঠ্য প্রবাহ ফিরিয়ে দিতে পারে,
coerceToText()
একটি পাঠ্য প্রবাহকে ফেরত দেয়। - যদি ইউআরআই কোনও সামগ্রী URI হয় তবে সরবরাহকারী কোনও পাঠ্য প্রবাহ সরবরাহ করে না,
coerceToText()
ইউআরআইয়ের উপস্থাপনা দেয়। প্রতিনিধিত্বটিUri.toString()
দ্বারা ফিরে আসা একই। - যদি ইউআরআই কোনও সামগ্রী URI না হয়, তবে
coerceToText()
ইউআরআইয়ের প্রতিনিধিত্ব করে। প্রতিনিধিত্বটিUri.toString()
দ্বারা ফিরে আসা একই।
- যদি ইউআরআই কোনও সামগ্রী ইউআরআই হয় এবং সরবরাহকারী কোনও পাঠ্য প্রবাহ ফিরিয়ে দিতে পারে,
- অভিপ্রায়
- যদি
ClipData.Item
একটিIntent
হয় - এটি হ'ল, যদিgetIntent()
নাল না না হয়coerceToText()
এটিকে একটি অভিপ্রায় ইউআরআইতে রূপান্তর করে এবং এটি ফিরিয়ে দেয়। প্রতিনিধিত্বটিIntent.toUri(URI_INTENT_SCHEME)
ক্লিপবোর্ড ফ্রেমওয়ার্কটি চিত্র 2 এ সংক্ষিপ্ত করা হয়েছে। ডেটা অনুলিপি করতে, একটি অ্যাপ্লিকেশন ClipboardManager
গ্লোবাল ক্লিপবোর্ডে একটি ClipData
অবজেক্ট রাখে। ClipData
এক বা একাধিক ClipData.Item
অবজেক্ট এবং একটি ClipDescription
অবজেক্ট রয়েছে। ডেটা পেস্ট করার জন্য, একটি অ্যাপ্লিকেশন ClipData
পায়, ClipDescription
থেকে তার মাইম টাইপ পায় এবং ClipData.Item
থেকে বা ClipData.Item
দ্বারা উল্লিখিত সামগ্রী সরবরাহকারী থেকে ডেটা পায়।

ক্লিপবোর্ডে কপি করুন
ক্লিপবোর্ডে ডেটা অনুলিপি করতে, গ্লোবাল ClipboardManager
অবজেক্টে একটি হ্যান্ডেল পান, একটি ClipData
অবজেক্ট তৈরি করুন এবং এটিতে একটি ClipDescription
এবং এক বা একাধিক ClipData.Item
অবজেক্ট যুক্ত করুন। তারপরে, ClipboardManager
অবজেক্টে সমাপ্ত ClipData
অবজেক্ট যুক্ত করুন। এটি নিম্নলিখিত পদ্ধতিতে আরও বর্ণিত হয়েছে:
- আপনি যদি কোনও সামগ্রী URI ব্যবহার করে ডেটা অনুলিপি করে থাকেন তবে একটি সামগ্রী সরবরাহকারী সেট আপ করুন।
- সিস্টেম ক্লিপবোর্ড পান:
কোটলিন
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 } }
জাভা
... // 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
অবজেক্টে ডেটা অনুলিপি করুন:- পাঠ্যের জন্য
কোটলিন
// Creates a new text clip to put on the clipboard. val clip: ClipData = ClipData.newPlainText("simple text", "Hello, World!")
জাভা
// Creates a new text clip to put on the clipboard. ClipData clip = ClipData.newPlainText("simple text", "Hello, World!");
- একটি ইউআরআই জন্য
এই স্নিপেট সরবরাহকারীর জন্য URI সামগ্রীতে রেকর্ড আইডি এনকোড করে একটি ইউআরআই তৈরি করে। এই কৌশলটি ইউআরআই বিভাগে একটি সনাক্তকারী এনকোডিংয়ে আরও বিশদে আচ্ছাদিত।
কোটলিন
// 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)
জাভা
// 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
তৈরি করে এবং তারপরে এটি ক্লিপ অবজেক্টে রাখে:কোটলিন
// 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)
জাভা
// 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);
- পাঠ্যের জন্য
- ক্লিপবোর্ডে নতুন ক্লিপ অবজেক্টটি রাখুন:
কোটলিন
// Set the clipboard's primary clip. clipboard.setPrimaryClip(clip)
জাভা
// Set the clipboard's primary clip. clipboard.setPrimaryClip(clip);
ক্লিপবোর্ডে অনুলিপি করার সময় প্রতিক্রিয়া সরবরাহ করুন
যখন কোনও অ্যাপ্লিকেশন ক্লিপবোর্ডে সামগ্রী অনুলিপি করে তখন ব্যবহারকারীরা ভিজ্যুয়াল প্রতিক্রিয়া আশা করেন। এটি অ্যান্ড্রয়েড 13 এবং উচ্চতর ব্যবহারকারীদের জন্য স্বয়ংক্রিয়ভাবে করা হয় তবে এটি অবশ্যই পূর্বের সংস্করণগুলিতে ম্যানুয়ালি প্রয়োগ করা উচিত।
অ্যান্ড্রয়েড 13 থেকে শুরু করে, ক্লিপবোর্ডে সামগ্রী যুক্ত করা হলে সিস্টেমটি একটি স্ট্যান্ডার্ড ভিজ্যুয়াল নিশ্চিতকরণ প্রদর্শন করে। নতুন নিশ্চিতকরণ নিম্নলিখিতটি করে:
- নিশ্চিত করে যে সামগ্রীটি সফলভাবে অনুলিপি করা হয়েছিল।
- অনুলিপিযুক্ত সামগ্রীর একটি পূর্বরূপ সরবরাহ করে।

অ্যান্ড্রয়েড 12 এল (এপিআই স্তর 32) এবং লোয়ারে, ব্যবহারকারীরা সফলভাবে সামগ্রী অনুলিপি করেছেন বা তারা কী অনুলিপি করেছেন তা অনিশ্চিত হতে পারে। এই বৈশিষ্ট্যটি অনুলিপি করার পরে অ্যাপ্লিকেশনগুলির দ্বারা প্রদর্শিত বিভিন্ন বিজ্ঞপ্তিগুলিকে মানক করে তোলে এবং ব্যবহারকারীদের ক্লিপবোর্ডের উপর আরও নিয়ন্ত্রণ সরবরাহ করে।
সদৃশ বিজ্ঞপ্তিগুলি এড়িয়ে চলুন
অ্যান্ড্রয়েড 12 এল (এপিআই স্তর 32) এবং লোয়ারে, আমরা ব্যবহারকারীদের যখন তারা অনুলিপি করার পরে Toast
বা Snackbar
মতো উইজেট ব্যবহার করে ভিজ্যুয়াল, অ্যাপ্লিকেশন প্রতিক্রিয়া জারি করে সাফল্যের সাথে অনুলিপি করার সময় ব্যবহারকারীদের সতর্ক করার পরামর্শ দিই।
তথ্যের সদৃশ প্রদর্শনগুলি এড়াতে, আমরা অ্যান্ড্রয়েড 13 এবং উচ্চতর জন্য একটি অ্যাপ্লিকেশন অনুলিপি পরে প্রদর্শিত টোস্ট বা স্নাকবারগুলি সরিয়ে দেওয়ার দৃ strongly ়ভাবে সুপারিশ করি।


এটি কীভাবে বাস্তবায়ন করা যায় তার একটি উদাহরণ এখানে:
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
একটি পতাকা যুক্ত করতে হবে। এই পতাকা যুক্ত করা সংবেদনশীল সামগ্রী অ্যান্ড্রয়েড 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()
ব্যবহার করে আপনার নিজের স্টোরেজে অনুলিপি করুন:
-
getSystemService(CLIPBOARD_SERVICE)
ব্যবহার করে গ্লোবালClipboardManager
অবজেক্টটি পান। এছাড়াও, পেস্ট করা পাঠ্যটি ধারণ করার জন্য একটি বিশ্বব্যাপী পরিবর্তনশীল ঘোষণা করুন:কোটলিন
var clipboard = getSystemService(Context.CLIPBOARD_SERVICE) as ClipboardManager var pasteData: String = ""
জাভা
ClipboardManager clipboard = (ClipboardManager) getSystemService(Context.CLIPBOARD_SERVICE); String pasteData = "";
- বর্তমান ক্রিয়াকলাপে আপনাকে "পেস্ট" বিকল্পটি সক্ষম বা অক্ষম করতে হবে কিনা তা নির্ধারণ করুন। যাচাই করুন যে ক্লিপবোর্ডে একটি ক্লিপ রয়েছে এবং আপনি ক্লিপ দ্বারা প্রতিনিধিত্ব করা ডেটার ধরণটি পরিচালনা করতে পারেন:
কোটলিন
// 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 } }
জাভা
// 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); }
- ক্লিপবোর্ড থেকে ডেটা অনুলিপি করুন। কোডের এই পয়েন্টটি কেবল তখনই পৌঁছনীয় যদি "পেস্ট" মেনু আইটেমটি সক্ষম করা থাকে, তাই আপনি ধরে নিতে পারেন যে ক্লিপবোর্ডে সরল পাঠ্য রয়েছে। আপনি এখনও জানেন না যে এটিতে কোনও পাঠ্য স্ট্রিং বা একটি ইউআরআই রয়েছে যা সরল পাঠ্যের দিকে নির্দেশ করে। নিম্নলিখিত কোড স্নিপেট এটি পরীক্ষা করে তবে এটি কেবল সরল পাঠ্য পরিচালনা করার জন্য কোডটি দেখায়:
কোটলিন
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 } } } }
জাভা
// 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
অবজেক্টে একটি সামগ্রী ইউআরআই থাকে এবং আপনি নির্ধারণ করেন যে আপনি এর একটি মাইম প্রকার পরিচালনা করতে পারেন, একটি ContentResolver
তৈরি করুন এবং ডেটা পুনরুদ্ধার করতে উপযুক্ত সামগ্রী সরবরাহকারী পদ্ধতিতে কল করুন।
নিম্নলিখিত পদ্ধতিটি ক্লিপবোর্ডে কোনও সামগ্রী URI এর উপর ভিত্তি করে কোনও সামগ্রী সরবরাহকারীর কাছ থেকে কীভাবে ডেটা পাবেন তা বর্ণনা করে। অ্যাপ্লিকেশনটি ব্যবহার করতে পারে এমন কোনও মাইম টাইপ সরবরাহকারীর কাছ থেকে উপলব্ধ কিনা তা পরীক্ষা করে।
- মাইম প্রকারটি ধারণ করতে একটি বিশ্বব্যাপী পরিবর্তনশীল ঘোষণা করুন:
কোটলিন
// 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"
জাভা
// 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";
- গ্লোবাল ক্লিপবোর্ড পান। এছাড়াও একটি সামগ্রী সমাধানকারী পান যাতে আপনি সামগ্রী সরবরাহকারী অ্যাক্সেস করতে পারেন:
কোটলিন
// Gets a handle to the Clipboard Manager. val clipboard = getSystemService(Context.CLIPBOARD_SERVICE) as ClipboardManager // Gets a content resolver instance. val cr = contentResolver
জাভা
// Gets a handle to the Clipboard Manager. ClipboardManager clipboard = (ClipboardManager) getSystemService(Context.CLIPBOARD_SERVICE); // Gets a content resolver instance. ContentResolver cr = getContentResolver();
- ক্লিপবোর্ড থেকে প্রাথমিক ক্লিপটি পান এবং ইউআরআই হিসাবে এর সামগ্রীগুলি পান:
কোটলিন
// 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
জাভা
// 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
কোনও বৈধ সামগ্রী সরবরাহকারীর দিকে নির্দেশ না করে তবে এই পদ্ধতিটি নালটি ফিরিয়ে দেয়।কোটলিন
// If the clipboard contains a URI reference... pasteUri?.let { // ...is this a content URI? val uriMimeType: String? = cr.getType(it)
জাভা
// If the clipboard contains a URI reference... if (pasteUri != null) { // ...is this a content URI? String uriMimeType = cr.getType(pasteUri);
- বিষয়বস্তু সরবরাহকারী একটি মাইম টাইপ সমর্থন করে কিনা তা পরীক্ষা করুন যা অ্যাপ্লিকেশনটি বোঝে। যদি এটি হয় তবে ডেটা পেতে
ContentResolver.query()
কল করুন। রিটার্ন মান একটিCursor
।কোটলিন
// 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. } } } }
জাভা
// 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()
কল করুন। নিম্নলিখিত স্নিপেট এটি প্রদর্শন করে:
কোটলিন
// 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. }
জাভা
// 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 (এপিআই স্তর 31) এবং উচ্চতর, সিস্টেমটি সাধারণত একটি টোস্ট বার্তা দেখায় যখন আপনার অ্যাপটি getPrimaryClip()
কল করে। বার্তার ভিতরে থাকা পাঠ্যটিতে নিম্নলিখিত ফর্ম্যাটটি রয়েছে:
APP pasted from your clipboard
যখন আপনার অ্যাপ্লিকেশন নিম্নলিখিতগুলির মধ্যে একটি করে তখন সিস্টেমটি টোস্ট বার্তা দেখায় না:
- আপনার নিজের অ্যাপ্লিকেশন থেকে
ClipData
অ্যাক্সেস করে। - বারবার একটি নির্দিষ্ট অ্যাপ্লিকেশন থেকে
ClipData
অ্যাক্সেস করে। টোস্টটি তখনই উপস্থিত হয় যখন আপনার অ্যাপটি প্রথমবারের জন্য সেই অ্যাপ্লিকেশন থেকে ডেটা অ্যাক্সেস করে। - ক্লিপ অবজেক্টের জন্য মেটাডেটা পুনরুদ্ধার করে, যেমন
getPrimaryClipDescription()
getPrimaryClip()
এর পরিবর্তে কল করে।
জটিল ডেটা অনুলিপি করতে সামগ্রী সরবরাহকারীদের ব্যবহার করুন
সামগ্রী সরবরাহকারীরা ডাটাবেস রেকর্ড বা ফাইল স্ট্রিমের মতো জটিল ডেটা অনুলিপি করে সমর্থন করে। ডেটা অনুলিপি করতে, ক্লিপবোর্ডে একটি সামগ্রী ইউআরআই রাখুন। অ্যাপ্লিকেশনগুলি পেস্ট করা তারপরে ক্লিপবোর্ড থেকে এই ইউআরআই পান এবং এটি ডাটাবেস ডেটা বা ফাইল স্ট্রিম বর্ণনাকারী পুনরুদ্ধার করতে ব্যবহার করুন।
যেহেতু পেস্টিং অ্যাপ্লিকেশনটিতে কেবল আপনার ডেটার জন্য URI সামগ্রী রয়েছে, তাই কোনটি ডেটা পুনরুদ্ধার করতে হবে তা জানতে হবে। আপনি নিজেই ইউআরআই -তে ডেটার জন্য একটি সনাক্তকারীকে এনকোড করে এই তথ্য সরবরাহ করতে পারেন, বা আপনি একটি অনন্য ইউআরআই সরবরাহ করতে পারেন যা আপনি অনুলিপি করতে চান এমন ডেটা ফেরত দেয়। আপনি কোন কৌশলটি চয়ন করেন তা আপনার ডেটার সংস্থার উপর নির্ভর করে।
নিম্নলিখিত বিভাগগুলি কীভাবে ইউআরআই সেট আপ করতে হবে, জটিল ডেটা সরবরাহ করবে এবং ফাইল স্ট্রিম সরবরাহ করবে তা বর্ণনা করে। বিবরণগুলি ধরে নিয়েছে যে আপনি সামগ্রী সরবরাহকারী ডিজাইনের সাধারণ নীতিগুলির সাথে পরিচিত।
ইউআরআই -তে একটি সনাক্তকারীকে এনকোড করুন
একটি ইউআরআই দিয়ে ক্লিপবোর্ডে ডেটা অনুলিপি করার জন্য একটি দরকারী কৌশল হ'ল ইউআরআই নিজেই ডেটার জন্য একটি সনাক্তকারীকে এনকোড করা। আপনার সামগ্রী সরবরাহকারী তখন ইউআরআই থেকে সনাক্তকারীটি পেতে এবং ডেটা পুনরুদ্ধার করতে এটি ব্যবহার করতে পারে। পেস্টিং অ্যাপ্লিকেশনটি সনাক্তকারীটি বিদ্যমান তা জানতে হবে না। এটি কেবল আপনার "রেফারেন্স" পেতে হবে - ইউআরআই প্লাস শনাক্তকারী - ক্লিপবোর্ড থেকে, এটি আপনার সামগ্রী সরবরাহকারী দিন এবং ডেটা ফিরে পেতে।
আপনি সাধারণত কোনও কন্টেন্ট ইউআরআই -তে একটি আইডেন্টিফায়ারকে এনকোড করে এটি ইউআরআইয়ের শেষে একত্রিত করে। উদাহরণস্বরূপ, ধরুন আপনি আপনার সরবরাহকারী ইউআরআইকে নিম্নলিখিত স্ট্রিং হিসাবে সংজ্ঞায়িত করেছেন:
"content://com.example.contacts"
আপনি যদি এই ইউআরআইতে কোনও নাম এনকোড করতে চান তবে নিম্নলিখিত কোড স্নিপেটটি ব্যবহার করুন:
কোটলিন
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)
জাভা
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()
- পেস্ট করা অ্যাপ্লিকেশনগুলি ধরে নিন যে আপনি ক্লিপবোর্ডে রেখেছেন এমন ইউআরআই দিয়ে এই পদ্ধতিটি ব্যবহার করে তারা আপনার ডেটা পেতে পারে। অনুলিপি সমর্থন করার জন্য, এই পদ্ধতিটি একটি বিশেষ "অনুলিপি" পাথযুক্ত ইউআরআই সনাক্ত করুন। আপনার অ্যাপ্লিকেশনটি তখন ক্লিপবোর্ডে রাখার জন্য একটি "অনুলিপি" ইউআরআই তৈরি করতে পারে, আপনি অনুলিপি করতে চান এমন সঠিক রেকর্ডের জন্য অনুলিপি পাথ এবং একটি পয়েন্টার সমন্বিত।
-
getType()
- আপনি অনুলিপি করতে চান এমন ডেটাগুলির জন্য এই পদ্ধতিটি অবশ্যই মাইম প্রকারগুলি ফিরিয়ে দিতে হবে। মাইম টাইপগুলি নতুন
ClipData
অবজেক্টে রাখার জন্যgetType()
কল করেnewUri()
) পদ্ধতিটি।জটিল ডেটার জন্য মাইম প্রকারগুলি সামগ্রী সরবরাহকারীদের মধ্যে বর্ণিত হয়।
আপনার অন্য কোনও সামগ্রী সরবরাহকারী পদ্ধতি যেমন insert()
বা update()
দরকার নেই। একটি পেস্টিং অ্যাপ্লিকেশনটি কেবল আপনার সমর্থিত মাইম প্রকারগুলি পেতে এবং আপনার সরবরাহকারীর কাছ থেকে ডেটা অনুলিপি করতে হবে। আপনার যদি ইতিমধ্যে এই পদ্ধতিগুলি থাকে তবে তারা অনুলিপি অপারেশনে হস্তক্ষেপ করবে না।
নিম্নলিখিত স্নিপেটগুলি কীভাবে জটিল ডেটা অনুলিপি করতে আপনার অ্যাপ্লিকেশন সেট আপ করবেন তা প্রদর্শন করে:
আপনার আবেদনের জন্য গ্লোবাল কনস্ট্যান্টগুলিতে, একটি বেস ইউআরআই স্ট্রিং এবং এমন একটি পথ ঘোষণা করুন যা আপনি ডেটা অনুলিপি করতে ব্যবহার করছেন এমন ইউআরআই স্ট্রিংগুলি সনাক্ত করে। অনুলিপিযুক্ত ডেটার জন্য একটি মাইম টাইপ ঘোষণা করুন।
কোটলিন
// 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"
জাভা
// 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 ক্লিপবোর্ডে রাখুন।
কোটলিন
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) } }
জাভা
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);
আপনার সামগ্রী সরবরাহকারীর বৈশ্বিক সুযোগে, একটি ইউআরআই ম্যাচার তৈরি করুন এবং একটি ইউআরআই প্যাটার্ন যুক্ত করুন যা আপনি ক্লিপবোর্ডে রেখেছেন ইউআরআইগুলির সাথে মেলে।
কোটলিন
// 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() { ... }
জাভা
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()
পদ্ধতি সেট আপ করুন। আপনি কীভাবে এটি কোড করে তার উপর নির্ভর করে এই পদ্ধতিটি বিভিন্ন ইউআরআই নিদর্শনগুলি পরিচালনা করতে পারে তবে ক্লিপবোর্ড অনুলিপি অপারেশন শোয়ের জন্য কেবল প্যাটার্ন।কোটলিন
// 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. } } ... }
জাভা
// 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()
পদ্ধতিটি সেট আপ করুন:কোটলিন
// Sets up your provider's getType() method. override fun getType(uri: Uri): String? { ... return when(sUriMatcher.match(uri)) { GET_SINGLE_CONTACT -> MIME_TYPE_CONTACT ... } }
জাভা
// 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 বিভাগ থেকে পেস্ট ডেটা ক্লিপবোর্ড থেকে কীভাবে সামগ্রী ইউআরআই পেতে পারে এবং ডেটা পেতে এবং পেস্ট করতে এটি ব্যবহার করতে পারে তা বর্ণনা করে।
ডেটা স্ট্রিমগুলি অনুলিপি করুন
আপনি স্ট্রিম হিসাবে প্রচুর পরিমাণে পাঠ্য এবং বাইনারি ডেটা অনুলিপি এবং পেস্ট করতে পারেন। ডেটাগুলিতে নিম্নলিখিতগুলির মতো ফর্ম থাকতে পারে:
- প্রকৃত ডিভাইসে সঞ্চিত ফাইলগুলি
- সকেট থেকে স্রোত
- কোনও সরবরাহকারীর অন্তর্নিহিত ডাটাবেস সিস্টেমে প্রচুর পরিমাণে ডেটা সঞ্চিত
ডেটা স্ট্রিমগুলির জন্য একটি সামগ্রী সরবরাহকারী কোনও ফাইল বর্ণনাকারী অবজেক্টের সাথে যেমন কোনও Cursor
অবজেক্টের পরিবর্তে AssetFileDescriptor
হিসাবে তার ডেটাতে অ্যাক্সেস সরবরাহ করে। পেস্টিং অ্যাপ্লিকেশনটি এই ফাইল বর্ণনাকারী ব্যবহার করে ডেটা স্ট্রিমটি পড়ে।
কোনও সরবরাহকারীর সাথে ডেটা স্ট্রিম অনুলিপি করতে আপনার অ্যাপ্লিকেশন সেট আপ করতে, এই পদক্ষেপগুলি অনুসরণ করুন:
- আপনি ক্লিপবোর্ডে যে ডেটা স্ট্রিম রাখছেন তার জন্য একটি সামগ্রী ইউআরআই সেট আপ করুন। এটি করার জন্য বিকল্পগুলি নিম্নলিখিতগুলি অন্তর্ভুক্ত করে:
- ইউআরআই বিভাগে একটি সনাক্তকারী এনকোডে বর্ণিত হিসাবে ইউআরআই -তে ডেটা স্ট্রিমের জন্য একটি সনাক্তকারীকে এনকোড করুন এবং তারপরে আপনার সরবরাহকারীর মধ্যে একটি টেবিল বজায় রাখুন যাতে সনাক্তকারী এবং সংশ্লিষ্ট স্ট্রিমের নাম থাকে।
- সরাসরি ইউআরআইতে স্ট্রিমের নামটি এনকোড করুন।
- একটি অনন্য ইউআরআই ব্যবহার করুন যা সর্বদা সরবরাহকারীর কাছ থেকে বর্তমান স্ট্রিমটি ফিরিয়ে দেয়। আপনি যদি এই বিকল্পটি ব্যবহার করেন তবে আপনি যখনই ইউআরআই ব্যবহার করে ক্লিপবোর্ডে স্ট্রিমটি অনুলিপি করেন তখন আপনার সরবরাহকারীকে অন্য কোনও স্ট্রিমের দিকে নির্দেশ করতে আপডেট করতে ভুলবেন না।
- আপনি যে অফার দেওয়ার পরিকল্পনা করছেন তা প্রতিটি ধরণের ডেটা স্ট্রিমের জন্য একটি মাইম টাইপ সরবরাহ করুন। ক্লিপবোর্ডে ডেটা পেস্ট করতে পারে কিনা তা নির্ধারণের জন্য অ্যাপ্লিকেশনগুলিকে আটকানো এই তথ্য প্রয়োজন।
-
ContentProvider
পদ্ধতিগুলির মধ্যে একটি প্রয়োগ করুন যা কোনও স্ট্রিমের জন্য একটি ফাইল বর্ণনাকারী প্রদান করে। আপনি যদি URI সামগ্রীতে আইডেন্টিফায়ারগুলি এনকোড করেন তবে কোন স্ট্রিমটি খুলতে হবে তা নির্ধারণ করতে এই পদ্ধতিটি ব্যবহার করুন। - ক্লিপবোর্ডে ডেটা স্ট্রিমটি অনুলিপি করতে, URI সামগ্রীটি তৈরি করুন এবং এটি ক্লিপবোর্ডে রাখুন।
ডেটা স্ট্রিমটি আটকানোর জন্য, একটি অ্যাপ্লিকেশন ক্লিপবোর্ড থেকে ক্লিপটি পায়, ইউআরআই পায় এবং এটি কোনও ContentResolver
ফাইল বর্ণনাকারী পদ্ধতিতে কল করে ব্যবহার করে যা স্ট্রিমটি খোলে। ContentResolver
পদ্ধতিটি সংশ্লিষ্ট ContentProvider
পদ্ধতিটিকে কল করে, এটি URI সামগ্রীটি পাস করে। আপনার সরবরাহকারী ফাইলের বর্ণনাকারীকে ContentResolver
পদ্ধতিতে ফেরত দেয়। পেস্ট অ্যাপ্লিকেশনটিতে স্ট্রিম থেকে ডেটা পড়ার দায়িত্ব রয়েছে।
নিম্নলিখিত তালিকাটি কোনও সামগ্রী সরবরাহকারীর জন্য সর্বাধিক গুরুত্বপূর্ণ ফাইল বর্ণনাকারী পদ্ধতিগুলি দেখায়। এগুলির প্রত্যেকেরই পদ্ধতির নামটিতে যুক্ত স্ট্রিং "বর্ণনাকারী" সহ একটি সম্পর্কিত ContentResolver
পদ্ধতি রয়েছে। উদাহরণস্বরূপ, openAssetFile()
এর ContentResolver
অ্যানালগটি openAssetFileDescriptor()
।
-
openTypedAssetFile()
এই পদ্ধতিটি একটি সম্পদ ফাইল বর্ণনাকারী প্রদান করে, তবে কেবলমাত্র সরবরাহকারী দ্বারা প্রদত্ত মাইম প্রকারটি সমর্থিত হয়। কলার - অ্যাপ্লিকেশনটি পেস্টিং করছে - একটি মাইম টাইপ প্যাটার্ন সরবরাহ করে। অ্যাপ্লিকেশনটির সামগ্রী সরবরাহকারী যা ক্লিপবোর্ডে একটি ইউআরআই অনুলিপি করে তা একটি
AssetFileDescriptor
ফাইল হ্যান্ডেলটি দেয় যদি এটি সেই মাইম টাইপ সরবরাহ করতে পারে এবং যদি এটি না করতে পারে তবে ব্যতিক্রম ছুঁড়ে দেয়।এই পদ্ধতিটি ফাইলগুলির সাবসেকশন পরিচালনা করে। সামগ্রী সরবরাহকারী ক্লিপবোর্ডে অনুলিপি করেছেন এমন সম্পদগুলি পড়তে আপনি এটি ব্যবহার করতে পারেন।
-
openAssetFile()
- এই পদ্ধতিটি
openTypedAssetFile()
এর আরও সাধারণ ফর্ম। এটি অনুমোদিত মাইম প্রকারের জন্য ফিল্টার করে না, তবে এটি ফাইলগুলির সাবসেকশনগুলি পড়তে পারে। -
openFile()
- এটি
openAssetFile()
এর আরও সাধারণ রূপ। এটি ফাইলগুলির সাবসেকশনগুলি পড়তে পারে না।
আপনি আপনার ফাইল বর্ণনাকারী পদ্ধতির সাথে openPipeHelper()
পদ্ধতিটি বিকল্পভাবে ব্যবহার করতে পারেন। এটি পেস্টিং অ্যাপ্লিকেশনটিকে পাইপ ব্যবহার করে একটি ব্যাকগ্রাউন্ড থ্রেডে স্ট্রিম ডেটা পড়তে দেয়। এই পদ্ধতিটি ব্যবহার করতে, ContentProvider.PipeDataWriter
ইন্টারফেসটি প্রয়োগ করুন।
কার্যকর অনুলিপি এবং পেস্ট কার্যকারিতা ডিজাইন করুন
আপনার আবেদনের জন্য কার্যকর অনুলিপি এবং পেস্ট কার্যকারিতা ডিজাইন করতে, এই পয়েন্টগুলি মনে রাখবেন:
- যে কোনও সময়, ক্লিপবোর্ডে কেবল একটি ক্লিপ রয়েছে। সিস্টেমের যে কোনও অ্যাপ্লিকেশন দ্বারা একটি নতুন অনুলিপি অপারেশন পূর্ববর্তী ক্লিপটিকে ওভাররাইট করে। যেহেতু ব্যবহারকারী আপনার অ্যাপ্লিকেশন থেকে দূরে নেভিগেট করতে পারে এবং ফিরে আসার আগে অনুলিপি করতে পারে, আপনি ধরে নিতে পারবেন না যে ক্লিপবোর্ডে ক্লিপটি রয়েছে যা ব্যবহারকারী আপনার অ্যাপ্লিকেশনটিতে আগে অনুলিপি করেছিলেন।
- ক্লিপ প্রতি একাধিক
ClipData.Item
অবজেক্টের উদ্দেশ্যযুক্ত উদ্দেশ্য হ'ল একক নির্বাচনের বিভিন্ন ধরণের রেফারেন্সের চেয়ে একাধিক নির্বাচনকে অনুলিপি করা এবং আটকানো সমর্থন করা। আপনি সাধারণতClipData.Item
সমস্ত ক্লিপটিতে একই ফর্মটি পেতে চান। এটি হ'ল এগুলি অবশ্যই সমস্ত সহজ পাঠ্য, সামগ্রী ইউআরআই বাIntent
এবং মিশ্রিত নয়। - আপনি যখন ডেটা সরবরাহ করেন, আপনি বিভিন্ন মাইম উপস্থাপনা সরবরাহ করতে পারেন।
ClipDescription
আপনার সমর্থনকারী মাইম প্রকারগুলি যুক্ত করুন এবং তারপরে আপনার সামগ্রী সরবরাহকারীর মধ্যে মাইম প্রকারগুলি প্রয়োগ করুন। - আপনি যখন ক্লিপবোর্ড থেকে ডেটা পাবেন, আপনার অ্যাপ্লিকেশনটি উপলভ্য মাইম প্রকারগুলি পরীক্ষা করার জন্য এবং তারপরে কোনটি ব্যবহার করবেন তা সিদ্ধান্ত নেওয়ার জন্য দায়বদ্ধ। এমনকি যদি ক্লিপবোর্ডে একটি ক্লিপ থাকে এবং ব্যবহারকারী কোনও পেস্টের জন্য অনুরোধ করে তবে আপনার অ্যাপ্লিকেশনটি পেস্টটি করার প্রয়োজন হয় না। মাইম টাইপ সামঞ্জস্যপূর্ণ হলে পেস্টটি করুন। আপনি ক্লিপবোর্ডে ডেটা
coerceToText()
ব্যবহার করে পাঠ্যতে ডেটা জোর করতে পারেন। যদি আপনার অ্যাপ্লিকেশনটি উপলভ্য মাইম প্রকারগুলির মধ্যে একটির বেশি সমর্থন করে তবে আপনি ব্যবহারকারীকে কোনটি ব্যবহার করতে পারেন তা চয়ন করতে পারেন।
অ্যান্ড্রয়েড অনুলিপি এবং আটকানোর জন্য একটি শক্তিশালী ক্লিপবোর্ড-ভিত্তিক কাঠামো সরবরাহ করে। এটি পাঠ্য স্ট্রিং, জটিল ডেটা স্ট্রাকচার, পাঠ্য এবং বাইনারি স্ট্রিম ডেটা এবং অ্যাপ্লিকেশন সম্পদ সহ সহজ এবং জটিল ডেটা প্রকারগুলিকে সমর্থন করে। সাধারণ পাঠ্য ডেটা সরাসরি ক্লিপবোর্ডে সংরক্ষণ করা হয়, যখন জটিল ডেটা একটি রেফারেন্স হিসাবে সংরক্ষণ করা হয় যে প্যাস্টিং অ্যাপ্লিকেশনটি কোনও সামগ্রী সরবরাহকারীর সাথে সমাধান করে। অনুলিপি করা এবং আটকানো উভয়ই একটি অ্যাপ্লিকেশন এবং অ্যাপ্লিকেশনগুলির মধ্যে কাজ করে যা কাঠামোটি প্রয়োগ করে।
যেহেতু ফ্রেমওয়ার্কের কিছু অংশ সামগ্রী সরবরাহকারী ব্যবহার করে, তাই এই দস্তাবেজটি অ্যান্ড্রয়েড সামগ্রী সরবরাহকারী এপিআইয়ের সাথে কিছু পরিচিতি ধরে নিয়েছে, যা সামগ্রী সরবরাহকারীদের মধ্যে বর্ণিত হয়েছে।
ক্লিপবোর্ডে সামগ্রী অনুলিপি করার সময় ব্যবহারকারীরা প্রতিক্রিয়া আশা করেন, সুতরাং অ্যান্ড্রয়েড 13 (এপিআই স্তর 33) এবং আরও উচ্চতর অনুলিপি করার সময় অ্যান্ড্রয়েড ব্যবহারকারীদের কাছে একটি ডিফল্ট ইউআই দেখায় এমন কাঠামোর পাশাপাশি অ্যান্ড্রয়েডের পাশাপাশি কাঠামোর পাশাপাশি অ্যান্ড্রয়েডের কাঠামো ছাড়াও। এই বৈশিষ্ট্যটির কারণে, সদৃশ বিজ্ঞপ্তির ঝুঁকি রয়েছে। আপনি এই প্রান্ত কেস সম্পর্কে আরও শিখতে পারেন ডুপ্লিকেট বিজ্ঞপ্তি বিভাগে এড়িয়ে চলুন ।

অ্যান্ড্রয়েড 12 এল (এপিআই স্তর 32) এবং কম অনুলিপি করার সময় ব্যবহারকারীদের ম্যানুয়ালি প্রতিক্রিয়া সরবরাহ করুন। এই দস্তাবেজে এটির জন্য সুপারিশগুলি দেখুন।
ক্লিপবোর্ড কাঠামো
আপনি যখন ক্লিপবোর্ড ফ্রেমওয়ার্কটি ব্যবহার করেন, তখন একটি ক্লিপ অবজেক্টে ডেটা রাখুন এবং তারপরে ক্লিপ অবজেক্টটি সিস্টেম-প্রশস্ত ক্লিপবোর্ডে রাখুন। ক্লিপ অবজেক্টটি তিনটি ফর্মের একটি নিতে পারে:
- পাঠ্য
- একটি পাঠ্য স্ট্রিং। স্ট্রিংটি সরাসরি ক্লিপ অবজেক্টে রাখুন, যা আপনি পরে ক্লিপবোর্ডে রেখেছিলেন। স্ট্রিংটি আটকানোর জন্য, ক্লিপবোর্ড থেকে ক্লিপ অবজেক্টটি পান এবং আপনার অ্যাপ্লিকেশনটির স্টোরেজে স্ট্রিংটি অনুলিপি করুন।
- ইউআরআই
- একটি
Uri
অবজেক্ট ইউআরআই এর যে কোনও রূপের প্রতিনিধিত্ব করে। এটি মূলত কোনও সামগ্রী সরবরাহকারীর কাছ থেকে জটিল ডেটা অনুলিপি করার জন্য। ডেটা অনুলিপি করতে, একটিUri
অবজেক্ট একটি ক্লিপ অবজেক্টে রাখুন এবং ক্লিপ অবজেক্টটি ক্লিপবোর্ডে রাখুন। ডেটা পেস্ট করতে, ক্লিপ অবজেক্টটি পান,Uri
অবজেক্টটি পান, এটি কোনও ডেটা উত্স যেমন কোনও সামগ্রী সরবরাহকারীকে সমাধান করুন এবং উত্স থেকে ডেটা আপনার অ্যাপ্লিকেশনটির স্টোরেজে অনুলিপি করুন। - অভিপ্রায়
- একটি
Intent
। এটি অ্যাপ্লিকেশন শর্টকাটগুলি অনুলিপি করতে সমর্থন করে। ডেটা অনুলিপি করতে, একটিIntent
তৈরি করুন, এটি একটি ক্লিপ অবজেক্টে রাখুন এবং ক্লিপবোর্ডে ক্লিপ অবজেক্টটি রাখুন। ডেটা পেস্ট করতে, ক্লিপ অবজেক্টটি পান এবং তারপরে আপনার অ্যাপ্লিকেশনটির মেমরি অঞ্চলেIntent
অবজেক্টটি অনুলিপি করুন।
ক্লিপবোর্ডটি একবারে কেবল একটি ক্লিপ অবজেক্ট ধারণ করে। যখন কোনও অ্যাপ্লিকেশন ক্লিপবোর্ডে একটি ক্লিপ অবজেক্ট রাখে, পূর্ববর্তী ক্লিপ অবজেক্টটি অদৃশ্য হয়ে যায়।
আপনি যদি ব্যবহারকারীদের আপনার অ্যাপ্লিকেশনটিতে ডেটা পেস্ট করতে চান তবে আপনাকে সমস্ত ধরণের ডেটা পরিচালনা করতে হবে না। ব্যবহারকারীদের এটি পেস্ট করার বিকল্প দেওয়ার আগে আপনি ক্লিপবোর্ডে থাকা ডেটা পরীক্ষা করতে পারেন। একটি নির্দিষ্ট ডেটা ফর্ম থাকার পাশাপাশি, ক্লিপ অবজেক্টটিতে মেটাডেটাও রয়েছে যা আপনাকে মিমের ধরণগুলি কী উপলব্ধ তা জানায়। এই মেটাডেটা আপনাকে সিদ্ধান্ত নিতে সহায়তা করে যে আপনার অ্যাপ্লিকেশনটি ক্লিপবোর্ডের ডেটা দিয়ে দরকারী কিছু করতে পারে কিনা। উদাহরণস্বরূপ, আপনার যদি এমন কোনও অ্যাপ্লিকেশন থাকে যা প্রাথমিকভাবে পাঠ্য পরিচালনা করে তবে আপনি ক্লিপ অবজেক্টগুলিকে উপেক্ষা করতে চাইতে পারেন যাতে একটি ইউআরআই বা অভিপ্রায় থাকে।
আপনি ক্লিপবোর্ডে ডেটা ফর্ম নির্বিশেষে ব্যবহারকারীদের পাঠ্য পেস্ট করতে দিতে পারেন। এটি করার জন্য, ক্লিপবোর্ডের ডেটা একটি পাঠ্য উপস্থাপনায় জোর করুন এবং তারপরে এই পাঠ্যটি আটকান। এটি কোর্সে ক্লিপবোর্ড থেকে পাঠ্য বিভাগে বর্ণিত হয়েছে।
ক্লিপবোর্ড ক্লাস
এই বিভাগটি ক্লিপবোর্ড ফ্রেমওয়ার্ক দ্বারা ব্যবহৃত ক্লাসগুলি বর্ণনা করে।
ক্লিপবোর্ড ম্যানেজার
অ্যান্ড্রয়েড সিস্টেম ক্লিপবোর্ডটি গ্লোবাল ClipboardManager
ক্লাস দ্বারা প্রতিনিধিত্ব করা হয়। এই ক্লাসটি সরাসরি ইনস্ট্যান্ট করবেন না। পরিবর্তে, getSystemService(CLIPBOARD_SERVICE)
অনুরোধ করে এটির একটি রেফারেন্স পান।
ক্লিপডাটা, ক্লিপডাটা.আইটেম, এবং ক্লিপডেসক্রিপশন
ক্লিপবোর্ডে ডেটা যুক্ত করতে, একটি ClipData
অবজেক্ট তৈরি করুন যাতে ডেটা এবং ডেটা নিজেই বর্ণনা থাকে। ক্লিপবোর্ডটি একবারে একটি ClipData
ধারণ করে। একটি ClipData
একটি ClipDescription
অবজেক্ট এবং এক বা একাধিক ClipData.Item
অবজেক্ট রয়েছে।
একটি ClipDescription
অবজেক্টে ক্লিপটি সম্পর্কে মেটাডেটা থাকে। বিশেষত, এটিতে ক্লিপের ডেটার জন্য উপলভ্য মাইম প্রকারের একটি অ্যারে রয়েছে। অতিরিক্তভাবে, অ্যান্ড্রয়েড 12 (এপিআই স্তর 31) এবং উচ্চতর, মেটাডেটাতে অবজেক্টটিতে স্টাইলাইজড পাঠ্য রয়েছে কিনা এবং অবজেক্টের পাঠ্যের ধরণ সম্পর্কে তথ্য অন্তর্ভুক্ত রয়েছে। আপনি যখন ক্লিপবোর্ডে একটি ক্লিপ রাখেন, তখন এই তথ্যগুলি অ্যাপ্লিকেশনগুলি আটকানোর জন্য উপলব্ধ, যা তারা ক্লিপ ডেটা পরিচালনা করতে পারে কিনা তা পরীক্ষা করতে পারে।
একটি ClipData.Item
অবজেক্টে পাঠ্য, ইউআরআই বা অভিপ্রায় ডেটা রয়েছে:
- পাঠ্য
- একটি
CharSequence
। - ইউআরআই
- একটি
Uri
। এটিতে সাধারণত একটি সামগ্রী সরবরাহকারী ইউআরআই থাকে, যদিও কোনও ইউআরআই অনুমোদিত। ডেটা সরবরাহ করে এমন অ্যাপ্লিকেশনটি ইউআরআইকে ক্লিপবোর্ডে রাখে। যে অ্যাপ্লিকেশনগুলি ডেটা পেস্ট করতে চায় তা ক্লিপবোর্ড থেকে ইউআরআই পেতে এবং সামগ্রী সরবরাহকারী বা অন্যান্য ডেটা উত্স অ্যাক্সেস করতে এবং ডেটা পুনরুদ্ধার করতে এটি ব্যবহার করে। - অভিপ্রায়
- একটি
Intent
। এই ডেটা টাইপ আপনাকে ক্লিপবোর্ডে একটি অ্যাপ্লিকেশন শর্টকাট অনুলিপি করতে দেয়। এরপরে ব্যবহারকারীরা শর্টকাটটি পরে ব্যবহারের জন্য তাদের অ্যাপ্লিকেশনগুলিতে পেস্ট করতে পারেন।
আপনি একটি ক্লিপটিতে একাধিক ClipData.Item
অবজেক্ট যুক্ত করতে পারেন। এটি ব্যবহারকারীদের একক ক্লিপ হিসাবে একাধিক নির্বাচন অনুলিপি এবং পেস্ট করতে দেয়। উদাহরণস্বরূপ, যদি আপনার কাছে কোনও তালিকা উইজেট থাকে যা ব্যবহারকারীকে একবারে একাধিক আইটেম নির্বাচন করতে দেয় তবে আপনি সমস্ত আইটেম একবারে ক্লিপবোর্ডে অনুলিপি করতে পারেন। এটি করার জন্য, প্রতিটি তালিকা আইটেমের জন্য একটি পৃথক ClipData.Item
তৈরি করুন এবং তারপরে ClipData.Item
অবজেক্টগুলি ClipData
অবজেক্টে যুক্ত করুন।
ক্লিপডাটা সুবিধার পদ্ধতি
ClipData
ক্লাসটি একটি ClipData.Item
অবজেক্ট এবং একটি সাধারণ ClipDescription
অবজেক্টের সাথে একটি ClipData
অবজেক্ট তৈরি করার জন্য স্থির সুবিধার পদ্ধতি সরবরাহ করে:
-
newPlainText(label, text)
- একটি
ClipData
অবজেক্টটি ফেরত দেয় যার এককClipData.Item
অবজেক্টে একটি পাঠ্য স্ট্রিং রয়েছে।ClipDescription
অবজেক্টের লেবেলটিlabel
সেট করা আছে।ClipDescription
একক মাইম টাইপ হ'লMIMETYPE_TEXT_PLAIN
।একটি পাঠ্য স্ট্রিং থেকে একটি ক্লিপ তৈরি করতে
newPlainText()
ব্যবহার করুন। -
newUri(resolver, label, URI)
- একটি
ClipData
অবজেক্টটি ফেরত দেয় যার এককClipData.Item
অবজেক্টে একটি ইউআরআই রয়েছে।ClipDescription
অবজেক্টের লেবেলটিlabel
সেট করা আছে। যদি ইউআরআই কোনও সামগ্রী URI হয় - তবে যদিUri.getScheme()
content:
of পদ্ধতিটি সামগ্রী সরবরাহকারীর কাছ থেকে উপলভ্য মাইম প্রকারগুলি পুনরুদ্ধার করতেresolver
প্রদত্তContentResolver
অবজেক্টটি ব্যবহার করে। এটি তখন তাদেরClipDescription
সঞ্চয় করে। একটি ইউআরআইয়ের জন্য যা কোনওcontent:
ইউআরআই, পদ্ধতিটি মাইম টাইপটিMIMETYPE_TEXT_URILIST
সেট করে।ইউআরআই থেকে একটি ক্লিপ তৈরি করতে
newUri()
ব্যবহার করুন - বিশেষত একটিcontent:
ইউআরআই। -
newIntent(label, intent)
- একটি
ClipData
অবজেক্টটি ফেরত দেয় যার এককClipData.Item
অবজেক্টে একটিIntent
রয়েছে।ClipDescription
অবজেক্টের লেবেলটিlabel
সেট করা আছে। মাইম টাইপটিMIMETYPE_TEXT_INTENT
এ সেট করা আছে।কোনও
Intent
অবজেক্ট থেকে একটি ক্লিপ তৈরি করতেnewIntent()
ব্যবহার করুন।
ক্লিপবোর্ডের ডেটা পাঠাতে বাধ্য করুন
এমনকি যদি আপনার অ্যাপ্লিকেশনটি কেবল পাঠ্য পরিচালনা করে তবে আপনি ক্লিপবোর্ড থেকে নন-টেক্সট ডেটা ClipData.Item.coerceToText()
পদ্ধতির সাথে রূপান্তর করে অনুলিপি করতে পারেন।
এই পদ্ধতিটি ClipData.Item
-এর ডেটা পাঠাতে রূপান্তর করে এবং একটি CharSequence
ফেরত দেয়। ClipData.Item.coerceToText()
রিটার্নগুলি যে মানটি ClipData.Item
-তে ডেটা ফর্মের উপর ভিত্তি করে:
- পাঠ্য
- যদি
ClipData.Item
পাঠ্য হয় - এটি হ'ল, যদিgetText()
নাল না হয় - Cercototext () পাঠ্যটি ফেরত দেয়। - ইউআরআই
- যদি
ClipData.Item
একটি ইউআরআই হয় - তা হ'ল, যদিgetUri()
NULL—coerceToText()
না হয় তবে এটি একটি সামগ্রী URI হিসাবে ব্যবহার করার চেষ্টা করে।- যদি ইউআরআই কোনও সামগ্রী ইউআরআই হয় এবং সরবরাহকারী কোনও পাঠ্য প্রবাহ ফিরিয়ে দিতে পারে,
coerceToText()
একটি পাঠ্য প্রবাহকে ফেরত দেয়। - যদি ইউআরআই কোনও সামগ্রী URI হয় তবে সরবরাহকারী কোনও পাঠ্য প্রবাহ সরবরাহ করে না,
coerceToText()
ইউআরআইয়ের উপস্থাপনা দেয়। প্রতিনিধিত্বটিUri.toString()
দ্বারা ফিরে আসা একই। - যদি ইউআরআই কোনও সামগ্রী URI না হয়, তবে
coerceToText()
ইউআরআইয়ের প্রতিনিধিত্ব করে। প্রতিনিধিত্বটিUri.toString()
দ্বারা ফিরে আসা একই।
- যদি ইউআরআই কোনও সামগ্রী ইউআরআই হয় এবং সরবরাহকারী কোনও পাঠ্য প্রবাহ ফিরিয়ে দিতে পারে,
- অভিপ্রায়
- যদি
ClipData.Item
একটিIntent
হয় - এটি হ'ল, যদিgetIntent()
নাল না না হয়coerceToText()
এটিকে একটি অভিপ্রায় ইউআরআইতে রূপান্তর করে এবং এটি ফিরিয়ে দেয়। প্রতিনিধিত্বটিIntent.toUri(URI_INTENT_SCHEME)
ক্লিপবোর্ড ফ্রেমওয়ার্কটি চিত্র 2 এ সংক্ষিপ্ত করা হয়েছে। ডেটা অনুলিপি করতে, একটি অ্যাপ্লিকেশন ClipboardManager
গ্লোবাল ক্লিপবোর্ডে একটি ClipData
অবজেক্ট রাখে। ClipData
এক বা একাধিক ClipData.Item
অবজেক্ট এবং একটি ClipDescription
অবজেক্ট রয়েছে। ডেটা পেস্ট করার জন্য, একটি অ্যাপ্লিকেশন ClipData
পায়, ClipDescription
থেকে তার মাইম টাইপ পায় এবং ClipData.Item
থেকে বা ClipData.Item
দ্বারা উল্লিখিত সামগ্রী সরবরাহকারী থেকে ডেটা পায়।

ক্লিপবোর্ডে কপি করুন
ক্লিপবোর্ডে ডেটা অনুলিপি করতে, গ্লোবাল ClipboardManager
অবজেক্টে একটি হ্যান্ডেল পান, একটি ClipData
অবজেক্ট তৈরি করুন এবং এটিতে একটি ClipDescription
এবং এক বা একাধিক ClipData.Item
অবজেক্ট যুক্ত করুন। তারপরে, ClipboardManager
অবজেক্টে সমাপ্ত ClipData
অবজেক্ট যুক্ত করুন। এটি নিম্নলিখিত পদ্ধতিতে আরও বর্ণিত হয়েছে:
- আপনি যদি কোনও সামগ্রী URI ব্যবহার করে ডেটা অনুলিপি করে থাকেন তবে একটি সামগ্রী সরবরাহকারী সেট আপ করুন।
- সিস্টেম ক্লিপবোর্ড পান:
কোটলিন
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 } }
জাভা
... // 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
অবজেক্টে ডেটা অনুলিপি করুন:- পাঠ্যের জন্য
কোটলিন
// Creates a new text clip to put on the clipboard. val clip: ClipData = ClipData.newPlainText("simple text", "Hello, World!")
জাভা
// Creates a new text clip to put on the clipboard. ClipData clip = ClipData.newPlainText("simple text", "Hello, World!");
- একটি ইউআরআই জন্য
এই স্নিপেট সরবরাহকারীর জন্য URI সামগ্রীতে রেকর্ড আইডি এনকোড করে একটি ইউআরআই তৈরি করে। এই কৌশলটি ইউআরআই বিভাগে একটি সনাক্তকারী এনকোডিংয়ে আরও বিশদে আচ্ছাদিত।
কোটলিন
// 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)
জাভা
// 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
তৈরি করে এবং তারপরে এটি ক্লিপ অবজেক্টে রাখে:কোটলিন
// 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)
জাভা
// 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);
- পাঠ্যের জন্য
- ক্লিপবোর্ডে নতুন ক্লিপ অবজেক্টটি রাখুন:
কোটলিন
// Set the clipboard's primary clip. clipboard.setPrimaryClip(clip)
জাভা
// Set the clipboard's primary clip. clipboard.setPrimaryClip(clip);
ক্লিপবোর্ডে অনুলিপি করার সময় প্রতিক্রিয়া সরবরাহ করুন
যখন কোনও অ্যাপ্লিকেশন ক্লিপবোর্ডে সামগ্রী অনুলিপি করে তখন ব্যবহারকারীরা ভিজ্যুয়াল প্রতিক্রিয়া আশা করেন। এটি অ্যান্ড্রয়েড 13 এবং উচ্চতর ব্যবহারকারীদের জন্য স্বয়ংক্রিয়ভাবে করা হয় তবে এটি অবশ্যই পূর্বের সংস্করণগুলিতে ম্যানুয়ালি প্রয়োগ করা উচিত।
অ্যান্ড্রয়েড 13 থেকে শুরু করে, ক্লিপবোর্ডে সামগ্রী যুক্ত করা হলে সিস্টেমটি একটি স্ট্যান্ডার্ড ভিজ্যুয়াল নিশ্চিতকরণ প্রদর্শন করে। নতুন নিশ্চিতকরণ নিম্নলিখিতটি করে:
- নিশ্চিত করে যে সামগ্রীটি সফলভাবে অনুলিপি করা হয়েছিল।
- অনুলিপিযুক্ত সামগ্রীর একটি পূর্বরূপ সরবরাহ করে।

অ্যান্ড্রয়েড 12 এল (এপিআই স্তর 32) এবং লোয়ারে, ব্যবহারকারীরা সফলভাবে সামগ্রী অনুলিপি করেছেন বা তারা কী অনুলিপি করেছেন তা অনিশ্চিত হতে পারে। এই বৈশিষ্ট্যটি অনুলিপি করার পরে অ্যাপ্লিকেশনগুলির দ্বারা প্রদর্শিত বিভিন্ন বিজ্ঞপ্তিগুলিকে মানক করে তোলে এবং ব্যবহারকারীদের ক্লিপবোর্ডের উপর আরও নিয়ন্ত্রণ সরবরাহ করে।
সদৃশ বিজ্ঞপ্তিগুলি এড়িয়ে চলুন
অ্যান্ড্রয়েড 12 এল (এপিআই স্তর 32) এবং লোয়ারে, আমরা ব্যবহারকারীদের যখন তারা অনুলিপি করার পরে Toast
বা Snackbar
মতো উইজেট ব্যবহার করে ভিজ্যুয়াল, অ্যাপ্লিকেশন প্রতিক্রিয়া জারি করে সাফল্যের সাথে অনুলিপি করার সময় ব্যবহারকারীদের সতর্ক করার পরামর্শ দিই।
তথ্যের সদৃশ প্রদর্শনগুলি এড়াতে, আমরা অ্যান্ড্রয়েড 13 এবং উচ্চতর জন্য একটি অ্যাপ্লিকেশন অনুলিপি পরে প্রদর্শিত টোস্ট বা স্নাকবারগুলি সরিয়ে দেওয়ার দৃ strongly ়ভাবে সুপারিশ করি।


এটি কীভাবে বাস্তবায়ন করা যায় তার একটি উদাহরণ এখানে:
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
একটি পতাকা যুক্ত করতে হবে। এই পতাকা যুক্ত করা সংবেদনশীল সামগ্রী অ্যান্ড্রয়েড 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()
ব্যবহার করে আপনার নিজের স্টোরেজে অনুলিপি করুন:
-
getSystemService(CLIPBOARD_SERVICE)
ব্যবহার করে গ্লোবালClipboardManager
অবজেক্টটি পান। এছাড়াও, পেস্ট করা পাঠ্যটি ধারণ করার জন্য একটি বিশ্বব্যাপী পরিবর্তনশীল ঘোষণা করুন:কোটলিন
var clipboard = getSystemService(Context.CLIPBOARD_SERVICE) as ClipboardManager var pasteData: String = ""
জাভা
ClipboardManager clipboard = (ClipboardManager) getSystemService(Context.CLIPBOARD_SERVICE); String pasteData = "";
- বর্তমান ক্রিয়াকলাপে আপনাকে "পেস্ট" বিকল্পটি সক্ষম বা অক্ষম করতে হবে কিনা তা নির্ধারণ করুন। Verify that the clipboard contains a clip and that you can handle the type of data represented by the clip:
কোটলিন
// 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 } }
জাভা
// 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); }
- Copy the data from the clipboard. This point in the code is only reachable if the "paste" menu item is enabled, so you can assume that the clipboard contains plain text. You don't yet know if it contains a text string or a URI that points to plain text. The following code snippet tests this, but it only shows the code for handling plain text:
কোটলিন
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 } } } }
জাভা
// 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; } }
Paste data from a content URI
If the ClipData.Item
object contains a content URI and you determine that you can handle one of its MIME types, create a ContentResolver
and call the appropriate content provider method to retrieve the data.
The following procedure describes how to get data from a content provider based on a content URI on the clipboard. It checks whether a MIME type that the application can use is available from the provider.
- Declare a global variable to contain the MIME type:
কোটলিন
// 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"
জাভা
// 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";
- Get the global clipboard. Also get a content resolver so you can access the content provider:
কোটলিন
// Gets a handle to the Clipboard Manager. val clipboard = getSystemService(Context.CLIPBOARD_SERVICE) as ClipboardManager // Gets a content resolver instance. val cr = contentResolver
জাভা
// Gets a handle to the Clipboard Manager. ClipboardManager clipboard = (ClipboardManager) getSystemService(Context.CLIPBOARD_SERVICE); // Gets a content resolver instance. ContentResolver cr = getContentResolver();
- Get the primary clip from the clipboard and get its contents as a URI:
কোটলিন
// 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
জাভা
// 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();
- Test whether the URI is a content URI by calling
getType(Uri)
. This method returns null ifUri
doesn't point to a valid content provider.কোটলিন
// If the clipboard contains a URI reference... pasteUri?.let { // ...is this a content URI? val uriMimeType: String? = cr.getType(it)
জাভা
// If the clipboard contains a URI reference... if (pasteUri != null) { // ...is this a content URI? String uriMimeType = cr.getType(pasteUri);
- Test whether the content provider supports a MIME type that the application understands. If it does, call
ContentResolver.query()
to get the data. The return value is aCursor
.কোটলিন
// 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. } } } }
জাভা
// 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(); } } } }
Paste an Intent
To paste an intent, first get the global clipboard. Examine the ClipData.Item
object to see whether it contains an Intent
. Then call getIntent()
to copy the intent to your own storage. The following snippet demonstrates this:
কোটলিন
// 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. }
জাভা
// 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. }
System notification shown when your app accesses clipboard data
On Android 12 (API level 31) and higher, the system usually shows a toast message when your app calls getPrimaryClip()
. The text inside the message contains the following format:
APP pasted from your clipboard
The system doesn't show a toast message when your app does one of the following:
- Accesses
ClipData
from your own app. - Repeatedly accesses
ClipData
from a specific app. The toast appears only when your app accesses the data from that app for the first time. - Retrieves metadata for the clip object, such as by calling
getPrimaryClipDescription()
instead ofgetPrimaryClip()
.
Use content providers to copy complex data
Content providers support copying complex data such as database records or file streams. To copy the data, put a content URI on the clipboard. Pasting applications then get this URI from the clipboard and use it to retrieve database data or file stream descriptors.
Since the pasting application only has the content URI for your data, it needs to know which piece of data to retrieve. You can provide this information by encoding an identifier for the data on the URI itself, or you can provide a unique URI that returns the data you want to copy. Which technique you choose depends on the organization of your data.
The following sections describe how to set up URIs, provide complex data, and provide file streams. The descriptions assume you are familiar with the general principles of content provider design.
Encode an identifier on the URI
A useful technique for copying data to the clipboard with a URI is to encode an identifier for the data on the URI itself. Your content provider can then get the identifier from the URI and use it to retrieve the data. The pasting application doesn't have to know that the identifier exists. It just has to get your "reference"—the URI plus the identifier—from the clipboard, give it your content provider, and get back the data.
You usually encode an identifier onto a content URI by concatenating it to the end of the URI. For example, suppose you define your provider URI as the following string:
"content://com.example.contacts"
If you want to encode a name onto this URI, use the following code snippet:
কোটলিন
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)
জাভা
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);
If you are already using a content provider, you might want to add a new URI path that indicates the URI is for copying. For example, suppose you already have the following URI paths:
"content://com.example.contacts/people" "content://com.example.contacts/people/detail" "content://com.example.contacts/people/images"
You can add another path that for copying URIs:
"content://com.example.contacts/copying"
You can then detect a "copy" URI by pattern-matching and handle it with code that is specific for copying and pasting.
You normally use the encoding technique if you're already using a content provider, internal database, or internal table to organize your data. In these cases, you have multiple pieces of data you want to copy, and presumably a unique identifier for each piece. In response to a query from the pasting application, you can look up the data by its identifier and return it.
If you don't have multiple pieces of data, then you probably don't need to encode an identifier. You can use a URI that is unique to your provider. In response to a query, your provider returns the data it currently contains.
Copy data structures
Set up a content provider for copying and pasting complex data as a subclass of the ContentProvider
component. Encode the URI you put on the clipboard so that it points to the exact record you want to provide. In addition, consider the existing state of your application:
- If you already have a content provider, you can add to its functionality. You might only need to modify its
query()
method to handle URIs coming from applications that want to paste data. You probably want to modify the method to handle a "copy" URI pattern. - If your application maintains an internal database, you might want to move this database into a content provider to facilitate copying from it.
- If you aren't using a database, you can implement a simple content provider whose sole purpose is to offer data to applications that are pasting from the clipboard.
In the content provider, override at least the following methods:
-
query()
- Pasting applications assume they can get your data by using this method with the URI you put on the clipboard. To support copying, have this method detect URIs containing a special "copy" path. Your application can then create a "copy" URI to put on the clipboard, containing the copy path and a pointer to the exact record you want to copy.
-
getType()
- This method must return the MIME types for the data you intend to copy. The method
newUri()
callsgetType()
to put the MIME types into the newClipData
object.MIME types for complex data are described in Content providers .
You don't need to have any of the other content provider methods, such as insert()
or update()
. A pasting application only needs to get your supported MIME types and copy data from your provider. If you already have these methods, they won't interfere with copy operations.
The following snippets demonstrate how to set up your application to copy complex data:
In the global constants for your application, declare a base URI string and a path that identifies URI strings you are using to copy data. Also declare a MIME type for the copied data.
কোটলিন
// 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"
জাভা
// 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";
- In the activity users copy data from, set up the code to copy data to the clipboard. In response to a copy request, put the URI on the clipboard.
কোটলিন
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) } }
জাভা
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);
In the global scope of your content provider, create a URI matcher and add a URI pattern that matches URIs you put on the clipboard.
কোটলিন
// 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() { ... }
জাভা
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);
Set up the
query()
method. This method can handle different URI patterns, depending on how you code it, but only the pattern for the clipboard copying operation shows.কোটলিন
// 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. } } ... }
জাভা
// 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. ... }
Set up the
getType()
method to return an appropriate MIME type for copied data:কোটলিন
// Sets up your provider's getType() method. override fun getType(uri: Uri): String? { ... return when(sUriMatcher.match(uri)) { GET_SINGLE_CONTACT -> MIME_TYPE_CONTACT ... } }
জাভা
// Sets up your provider's getType() method. public String getType(Uri uri) { ... switch (sUriMatcher.match(uri)) { case GET_SINGLE_CONTACT: return (MIME_TYPE_CONTACT); ... } }
The Paste data from a content URI section describes how to get a content URI from the clipboard and use it to get and paste data.
Copy data streams
You can copy and paste large amounts of text and binary data as streams. The data can have forms such as the following:
- Files stored on the actual device
- Streams from sockets
- Large amounts of data stored in a provider's underlying database system
A content provider for data streams provides access to its data with a file descriptor object, such as AssetFileDescriptor
, instead of a Cursor
object. The pasting application reads the data stream using this file descriptor.
To set up your application to copy a data stream with a provider, follow these steps:
- Set up a content URI for the data stream you are putting on the clipboard. Options for doing this include the following:
- Encode an identifier for the data stream onto the URI, as described in the Encode an identifier on the URI section, and then maintain a table in your provider that contains identifiers and the corresponding stream name.
- Encode the stream name directly on the URI.
- Use a unique URI that always returns the current stream from the provider. If you use this option, remember to update your provider to point to a different stream whenever you copy the stream to the clipboard using the URI.
- Provide a MIME type for each type of data stream you plan to offer. Pasting applications need this information to determine whether they can paste the data on the clipboard.
- Implement one of the
ContentProvider
methods that returns a file descriptor for a stream. If you encode identifiers on the content URI, use this method to determine which stream to open. - To copy the data stream to the clipboard, construct the content URI and place it on the clipboard.
To paste a data stream, an application gets the clip from the clipboard, gets the URI, and uses it in a call to a ContentResolver
file descriptor method that opens the stream. The ContentResolver
method calls the corresponding ContentProvider
method, passing it the content URI. Your provider returns the file descriptor to the ContentResolver
method. The pasting application then has the responsibility to read the data from the stream.
The following list shows the most important file descriptor methods for a content provider. Each of these has a corresponding ContentResolver
method with the string "Descriptor" appended to the method name. For example, the ContentResolver
analog of openAssetFile()
is openAssetFileDescriptor()
.
-
openTypedAssetFile()
This method returns an asset file descriptor, but only if the provided MIME type is supported by the provider. The caller—the application doing the pasting—provides a MIME type pattern. The content provider of the application that copies a URI to the clipboard returns an
AssetFileDescriptor
file handle if it can provide that MIME type and throws an exception if it can't.This method handles subsections of files. You can use it to read assets that the content provider has copied to the clipboard.
-
openAssetFile()
- This method is a more general form of
openTypedAssetFile()
. It doesn't filter for allowed MIME types, but it can read subsections of files. -
openFile()
- This is a more general form of
openAssetFile()
. It can't read subsections of files.
You can optionally use the openPipeHelper()
method with your file descriptor method. This lets the pasting application read the stream data in a background thread using a pipe. To use this method, implement the ContentProvider.PipeDataWriter
interface.
Design effective copy and paste functionality
To design effective copy and paste functionality for your application, remember these points:
- At any time, there is only one clip on the clipboard. A new copy operation by any application in the system overwrites the previous clip. Since the user might navigate away from your application and copy before returning, you can't assume the clipboard contains the clip that the user previously copied in your application.
- The intended purpose of multiple
ClipData.Item
objects per clip is to support copying and pasting of multiple selections rather than different forms of reference to a single selection. You usually want all of theClipData.Item
objects in a clip to have the same form. That is, they must all be simple text, content URI, orIntent
, and not mixed. - When you provide data, you can offer different MIME representations. Add the MIME types you support to the
ClipDescription
, and then implement the MIME types in your content provider. - When you get data from the clipboard, your application is responsible for checking the available MIME types and then deciding which one, if any, to use. Even if there is a clip on the clipboard and the user requests a paste, your application isn't required to do the paste. Do the paste if the MIME type is compatible. You might coerce the data on the clipboard to text using
coerceToText()
. If your application supports more than one of the available MIME types, you can let the user pick which one to use.
Android provides a powerful clipboard-based framework for copying and pasting. It supports simple and complex data types, including text strings, complex data structures, text and binary stream data, and application assets. Simple text data is stored directly in the clipboard, while complex data is stored as a reference that the pasting application resolves with a content provider. Copying and pasting works both within an application and between applications that implement the framework.
Since part of the framework uses content providers, this document assumes some familiarity with the Android Content Provider API, which is described in Content providers .
Users expect feedback when copying content to the clipboard, so in addition to the framework that powers copy and paste, Android shows a default UI to users when copying in Android 13 (API level 33) and higher. Due to this feature, there is a risk of duplicate notification. You can learn more about this edge case the in the Avoid duplicate notifications section.

Manually provide feedback to users when copying in Android 12L (API level 32) and lower. See recommendations for this in this document.
The clipboard framework
When you use the clipboard framework, put data into a clip object, and then put the clip object on the system-wide clipboard. The clip object can take one of three forms:
- পাঠ্য
- A text string. Put the string directly in the clip object, which you then put on the clipboard. To paste the string, get the clip object from the clipboard and copy the string into your application's storage.
- ইউআরআই
- A
Uri
object representing any form of URI. This is primarily for copying complex data from a content provider. To copy data, put aUri
object into a clip object and put the clip object onto the clipboard. To paste the data, get the clip object, get theUri
object, resolve it to a data source, such as a content provider, and copy the data from the source into your application's storage. - অভিপ্রায়
- An
Intent
. This supports copying application shortcuts. To copy data, create anIntent
, put it in a clip object, and put the clip object on the clipboard. To paste the data, get the clip object and then copy theIntent
object into your application's memory area.
The clipboard holds only one clip object at a time. When an application puts a clip object on the clipboard, the previous clip object disappears.
If you want to let users paste data into your application, you don't have to handle all types of data. You can examine the data on the clipboard before you give users the option to paste it. Besides having a certain data form, the clip object also contains metadata that tells you what MIME types are available. This metadata helps you decide whether your application can do something useful with the clipboard data. For example, if you have an application that primarily handles text, you might want to ignore clip objects that contain a URI or intent.
You might also want to let users paste text regardless of the form of data on the clipboard. To do this, force the clipboard data into a text representation, and then paste this text. This is described in the Coerce the clipboard to text section.
Clipboard classes
This section describes the classes used by the clipboard framework.
ক্লিপবোর্ড ম্যানেজার
The Android system clipboard is represented by the global ClipboardManager
class. Don't instantiate this class directly. Instead, get a reference to it by invoking getSystemService(CLIPBOARD_SERVICE)
.
ClipData, ClipData.Item, and ClipDescription
To add data to the clipboard, create a ClipData
object that contains a description of the data and the data itself. The clipboard holds one ClipData
at a time. A ClipData
contains a ClipDescription
object and one or more ClipData.Item
objects.
A ClipDescription
object contains metadata about the clip. In particular, it contains an array of available MIME types for the clip's data. Additionally, on Android 12 (API level 31) and higher, the metadata includes information about whether the object contains stylized text and about the type of text in the object . When you put a clip on the clipboard, this information is available to pasting applications, which can examine whether they can handle the clip data.
A ClipData.Item
object contains the text, URI, or intent data:
- পাঠ্য
- A
CharSequence
. - ইউআরআই
- A
Uri
. This usually contains a content provider URI, although any URI is allowed. The application that provides the data puts the URI on the clipboard. Applications that want to paste the data get the URI from the clipboard and use it to access the content provider or other data source and retrieve the data. - অভিপ্রায়
- An
Intent
. This data type lets you copy an application shortcut to the clipboard. Users can then paste the shortcut into their applications for later use.
You can add more than one ClipData.Item
object to a clip. This lets users copy and paste multiple selections as a single clip. For example, if you have a list widget that lets the user select more than one item at a time, you can copy all the items to the clipboard at once. To do this, create a separate ClipData.Item
for each list item, and then add the ClipData.Item
objects to the ClipData
object.
ClipData convenience methods
The ClipData
class provides static convenience methods for creating a ClipData
object with a single ClipData.Item
object and a simple ClipDescription
object:
-
newPlainText(label, text)
- Returns a
ClipData
object whose singleClipData.Item
object contains a text string. TheClipDescription
object's label is set tolabel
. The single MIME type inClipDescription
isMIMETYPE_TEXT_PLAIN
.Use
newPlainText()
to create a clip from a text string. -
newUri(resolver, label, URI)
- Returns a
ClipData
object whose singleClipData.Item
object contains a URI. TheClipDescription
object's label is set tolabel
. If the URI is a content URI—that is, ifUri.getScheme()
returnscontent:
—the method uses theContentResolver
object provided inresolver
to retrieve the available MIME types from the content provider. It then stores them inClipDescription
. For a URI that isn't acontent:
URI, the method sets the MIME type toMIMETYPE_TEXT_URILIST
.Use
newUri()
to create a clip from a URI—particularly acontent:
URI. -
newIntent(label, intent)
- Returns a
ClipData
object whose singleClipData.Item
object contains anIntent
. TheClipDescription
object's label is set tolabel
. The MIME type is set toMIMETYPE_TEXT_INTENT
.Use
newIntent()
to create a clip from anIntent
object.
Coerce the clipboard data to text
Even if your application only handles text, you can copy non-text data from the clipboard by converting it with the ClipData.Item.coerceToText()
method.
This method converts the data in ClipData.Item
to text and returns a CharSequence
. The value that ClipData.Item.coerceToText()
returns is based on the form of data in ClipData.Item
:
- পাঠ্য
- If
ClipData.Item
is text—that is, ifgetText()
isn't null—coerceToText() returns the text. - ইউআরআই
- If
ClipData.Item
is a URI—that is, ifgetUri()
isn't null—coerceToText()
tries to use it as a content URI.- If the URI is a content URI and the provider can return a text stream,
coerceToText()
returns a text stream. - If the URI is a content URI but the provider doesn't offer a text stream,
coerceToText()
returns a representation of the URI. The representation is the same as that returned byUri.toString()
. - If the URI isn't a content URI,
coerceToText()
returns a representation of the URI. The representation is the same as that returned byUri.toString()
.
- If the URI is a content URI and the provider can return a text stream,
- অভিপ্রায়
- If
ClipData.Item
is anIntent
—that is, ifgetIntent()
isn't null—coerceToText()
converts it to an Intent URI and returns it. The representation is the same as that returned byIntent.toUri(URI_INTENT_SCHEME)
.
The clipboard framework is summarized in figure 2. To copy data, an application puts a ClipData
object on the ClipboardManager
global clipboard. The ClipData
contains one or more ClipData.Item
objects and one ClipDescription
object. To paste data, an application gets the ClipData
, gets its MIME type from the ClipDescription
, and gets the data from the ClipData.Item
or from the content provider referred to by ClipData.Item
.

ক্লিপবোর্ডে কপি করুন
To copy data to the clipboard, get a handle to the global ClipboardManager
object, create a ClipData
object, and add a ClipDescription
and one or more ClipData.Item
objects to it. Then, add the finished ClipData
object to the ClipboardManager
object. This is described further in the following procedure:
- If you are copying data using a content URI, set up a content provider.
- Get the system clipboard:
কোটলিন
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 } }
জাভা
... // If the user selects copy. case R.id.menu_copy: // Gets a handle to the clipboard service. ClipboardManager clipboard = (ClipboardManager) getSystemService(Context.CLIPBOARD_SERVICE);
Copy the data to a new
ClipData
object:- For text
কোটলিন
// Creates a new text clip to put on the clipboard. val clip: ClipData = ClipData.newPlainText("simple text", "Hello, World!")
জাভা
// Creates a new text clip to put on the clipboard. ClipData clip = ClipData.newPlainText("simple text", "Hello, World!");
- For a URI
This snippet constructs a URI by encoding a record ID onto the content URI for the provider. This technique is covered in more detail in the Encoding an identifier on the URI section.
কোটলিন
// 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)
জাভা
// 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);
- For an intent
This snippet constructs an
Intent
for an application and then puts it in the clip object:কোটলিন
// 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)
জাভা
// 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);
- For text
- Put the new clip object on the clipboard:
কোটলিন
// Set the clipboard's primary clip. clipboard.setPrimaryClip(clip)
জাভা
// Set the clipboard's primary clip. clipboard.setPrimaryClip(clip);
Provide feedback when copying to the clipboard
Users expect visual feedback when an app copies content to the clipboard. This is done automatically for users in Android 13 and higher, but it must be manually implemented in prior versions.
Starting in Android 13, the system displays a standard visual confirmation when content is added to the clipboard. The new confirmation does the following:
- Confirms the content was successfully copied.
- Provides a preview of the copied content.

In Android 12L (API level 32) and lower, users might be unsure whether they successfully copied content or what they copied. This feature standardizes the various notifications shown by apps after copying and offers users more control over the clipboard.
Avoid duplicate notifications
In Android 12L (API level 32) and lower, we recommend alerting users when they successfully copy by issuing visual, in-app feedback, using a widget like a Toast
or a Snackbar
, after copying.
To avoid duplicate displays of information, we strongly recommend removing toasts or snackbars shown after an in-app copy for Android 13 and higher.


এটি কীভাবে বাস্তবায়ন করা যায় তার একটি উদাহরণ এখানে:
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() }
Add sensitive content to the clipboard
If your app lets users copy sensitive content to the clipboard, such as passwords or credit card information, you must add a flag to ClipDescription
in ClipData
before calling ClipboardManager.setPrimaryClip()
. Adding this flag prevents sensitive content from appearing in the visual confirmation of copied content in Android 13 and higher.


To flag sensitive content, add a boolean extra to the ClipDescription
. All apps must do this, regardless of the targeted API level.
// If your app is compiled with the API level 33 SDK or higher. clipData.apply { description.extras = PersistableBundle().apply { putBoolean(ClipDescription.EXTRA_IS_SENSITIVE, true) } } // If your app is compiled with a lower SDK. clipData.apply { description.extras = PersistableBundle().apply { putBoolean("android.content.extra.IS_SENSITIVE", true) } }
ক্লিপবোর্ড থেকে পেস্ট করুন
As described previously, paste data from the clipboard by getting the global clipboard object, getting the clip object, looking at its data, and if possible copying the data from the clip object to your own storage. This section explains in detail how to paste the three forms of clipboard data.
প্লেইন টেক্সট পেস্ট করুন
To paste plain text, get the global clipboard and verify that it can return plain text. Then get the clip object and copy its text to your own storage using getText()
, as described in the following procedure:
- Get the global
ClipboardManager
object usinggetSystemService(CLIPBOARD_SERVICE)
. Also, declare a global variable to contain the pasted text:কোটলিন
var clipboard = getSystemService(Context.CLIPBOARD_SERVICE) as ClipboardManager var pasteData: String = ""
জাভা
ClipboardManager clipboard = (ClipboardManager) getSystemService(Context.CLIPBOARD_SERVICE); String pasteData = "";
- Determine whether you need to enable or disable the "paste" option in the current activity. Verify that the clipboard contains a clip and that you can handle the type of data represented by the clip:
কোটলিন
// 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 } }
জাভা
// 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); }
- Copy the data from the clipboard. This point in the code is only reachable if the "paste" menu item is enabled, so you can assume that the clipboard contains plain text. You don't yet know if it contains a text string or a URI that points to plain text. The following code snippet tests this, but it only shows the code for handling plain text:
কোটলিন
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 } } } }
জাভা
// 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; } }
Paste data from a content URI
If the ClipData.Item
object contains a content URI and you determine that you can handle one of its MIME types, create a ContentResolver
and call the appropriate content provider method to retrieve the data.
The following procedure describes how to get data from a content provider based on a content URI on the clipboard. It checks whether a MIME type that the application can use is available from the provider.
- Declare a global variable to contain the MIME type:
কোটলিন
// 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"
জাভা
// 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";
- Get the global clipboard. Also get a content resolver so you can access the content provider:
কোটলিন
// Gets a handle to the Clipboard Manager. val clipboard = getSystemService(Context.CLIPBOARD_SERVICE) as ClipboardManager // Gets a content resolver instance. val cr = contentResolver
জাভা
// Gets a handle to the Clipboard Manager. ClipboardManager clipboard = (ClipboardManager) getSystemService(Context.CLIPBOARD_SERVICE); // Gets a content resolver instance. ContentResolver cr = getContentResolver();
- Get the primary clip from the clipboard and get its contents as a URI:
কোটলিন
// 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
জাভা
// 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();
- Test whether the URI is a content URI by calling
getType(Uri)
. This method returns null ifUri
doesn't point to a valid content provider.কোটলিন
// If the clipboard contains a URI reference... pasteUri?.let { // ...is this a content URI? val uriMimeType: String? = cr.getType(it)
জাভা
// If the clipboard contains a URI reference... if (pasteUri != null) { // ...is this a content URI? String uriMimeType = cr.getType(pasteUri);
- Test whether the content provider supports a MIME type that the application understands. If it does, call
ContentResolver.query()
to get the data. The return value is aCursor
.কোটলিন
// 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. } } } }
জাভা
// 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(); } } } }
Paste an Intent
To paste an intent, first get the global clipboard. Examine the ClipData.Item
object to see whether it contains an Intent
. Then call getIntent()
to copy the intent to your own storage. The following snippet demonstrates this:
কোটলিন
// 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. }
জাভা
// 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. }
System notification shown when your app accesses clipboard data
On Android 12 (API level 31) and higher, the system usually shows a toast message when your app calls getPrimaryClip()
. The text inside the message contains the following format:
APP pasted from your clipboard
The system doesn't show a toast message when your app does one of the following:
- Accesses
ClipData
from your own app. - Repeatedly accesses
ClipData
from a specific app. The toast appears only when your app accesses the data from that app for the first time. - Retrieves metadata for the clip object, such as by calling
getPrimaryClipDescription()
instead ofgetPrimaryClip()
.
Use content providers to copy complex data
Content providers support copying complex data such as database records or file streams. To copy the data, put a content URI on the clipboard. Pasting applications then get this URI from the clipboard and use it to retrieve database data or file stream descriptors.
Since the pasting application only has the content URI for your data, it needs to know which piece of data to retrieve. You can provide this information by encoding an identifier for the data on the URI itself, or you can provide a unique URI that returns the data you want to copy. Which technique you choose depends on the organization of your data.
The following sections describe how to set up URIs, provide complex data, and provide file streams. The descriptions assume you are familiar with the general principles of content provider design.
Encode an identifier on the URI
A useful technique for copying data to the clipboard with a URI is to encode an identifier for the data on the URI itself. Your content provider can then get the identifier from the URI and use it to retrieve the data. The pasting application doesn't have to know that the identifier exists. It just has to get your "reference"—the URI plus the identifier—from the clipboard, give it your content provider, and get back the data.
You usually encode an identifier onto a content URI by concatenating it to the end of the URI. For example, suppose you define your provider URI as the following string:
"content://com.example.contacts"
If you want to encode a name onto this URI, use the following code snippet:
কোটলিন
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)
জাভা
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);
If you are already using a content provider, you might want to add a new URI path that indicates the URI is for copying. For example, suppose you already have the following URI paths:
"content://com.example.contacts/people" "content://com.example.contacts/people/detail" "content://com.example.contacts/people/images"
You can add another path that for copying URIs:
"content://com.example.contacts/copying"
You can then detect a "copy" URI by pattern-matching and handle it with code that is specific for copying and pasting.
You normally use the encoding technique if you're already using a content provider, internal database, or internal table to organize your data. In these cases, you have multiple pieces of data you want to copy, and presumably a unique identifier for each piece. In response to a query from the pasting application, you can look up the data by its identifier and return it.
If you don't have multiple pieces of data, then you probably don't need to encode an identifier. You can use a URI that is unique to your provider. In response to a query, your provider returns the data it currently contains.
Copy data structures
Set up a content provider for copying and pasting complex data as a subclass of the ContentProvider
component. Encode the URI you put on the clipboard so that it points to the exact record you want to provide. In addition, consider the existing state of your application:
- If you already have a content provider, you can add to its functionality. You might only need to modify its
query()
method to handle URIs coming from applications that want to paste data. You probably want to modify the method to handle a "copy" URI pattern. - If your application maintains an internal database, you might want to move this database into a content provider to facilitate copying from it.
- If you aren't using a database, you can implement a simple content provider whose sole purpose is to offer data to applications that are pasting from the clipboard.
In the content provider, override at least the following methods:
-
query()
- Pasting applications assume they can get your data by using this method with the URI you put on the clipboard. To support copying, have this method detect URIs containing a special "copy" path. Your application can then create a "copy" URI to put on the clipboard, containing the copy path and a pointer to the exact record you want to copy.
-
getType()
- This method must return the MIME types for the data you intend to copy. The method
newUri()
callsgetType()
to put the MIME types into the newClipData
object.MIME types for complex data are described in Content providers .
You don't need to have any of the other content provider methods, such as insert()
or update()
. A pasting application only needs to get your supported MIME types and copy data from your provider. If you already have these methods, they won't interfere with copy operations.
The following snippets demonstrate how to set up your application to copy complex data:
In the global constants for your application, declare a base URI string and a path that identifies URI strings you are using to copy data. Also declare a MIME type for the copied data.
কোটলিন
// 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"
জাভা
// 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";
- In the activity users copy data from, set up the code to copy data to the clipboard. In response to a copy request, put the URI on the clipboard.
কোটলিন
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) } }
জাভা
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);
In the global scope of your content provider, create a URI matcher and add a URI pattern that matches URIs you put on the clipboard.
কোটলিন
// 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() { ... }
জাভা
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);
Set up the
query()
method. This method can handle different URI patterns, depending on how you code it, but only the pattern for the clipboard copying operation shows.কোটলিন
// 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. } } ... }
জাভা
// 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. ... }
Set up the
getType()
method to return an appropriate MIME type for copied data:কোটলিন
// Sets up your provider's getType() method. override fun getType(uri: Uri): String? { ... return when(sUriMatcher.match(uri)) { GET_SINGLE_CONTACT -> MIME_TYPE_CONTACT ... } }
জাভা
// Sets up your provider's getType() method. public String getType(Uri uri) { ... switch (sUriMatcher.match(uri)) { case GET_SINGLE_CONTACT: return (MIME_TYPE_CONTACT); ... } }
The Paste data from a content URI section describes how to get a content URI from the clipboard and use it to get and paste data.
Copy data streams
You can copy and paste large amounts of text and binary data as streams. The data can have forms such as the following:
- Files stored on the actual device
- Streams from sockets
- Large amounts of data stored in a provider's underlying database system
A content provider for data streams provides access to its data with a file descriptor object, such as AssetFileDescriptor
, instead of a Cursor
object. The pasting application reads the data stream using this file descriptor.
To set up your application to copy a data stream with a provider, follow these steps:
- Set up a content URI for the data stream you are putting on the clipboard. Options for doing this include the following:
- Encode an identifier for the data stream onto the URI, as described in the Encode an identifier on the URI section, and then maintain a table in your provider that contains identifiers and the corresponding stream name.
- Encode the stream name directly on the URI.
- Use a unique URI that always returns the current stream from the provider. If you use this option, remember to update your provider to point to a different stream whenever you copy the stream to the clipboard using the URI.
- Provide a MIME type for each type of data stream you plan to offer. Pasting applications need this information to determine whether they can paste the data on the clipboard.
- Implement one of the
ContentProvider
methods that returns a file descriptor for a stream. If you encode identifiers on the content URI, use this method to determine which stream to open. - To copy the data stream to the clipboard, construct the content URI and place it on the clipboard.
To paste a data stream, an application gets the clip from the clipboard, gets the URI, and uses it in a call to a ContentResolver
file descriptor method that opens the stream. The ContentResolver
method calls the corresponding ContentProvider
method, passing it the content URI. Your provider returns the file descriptor to the ContentResolver
method. The pasting application then has the responsibility to read the data from the stream.
The following list shows the most important file descriptor methods for a content provider. Each of these has a corresponding ContentResolver
method with the string "Descriptor" appended to the method name. For example, the ContentResolver
analog of openAssetFile()
is openAssetFileDescriptor()
.
-
openTypedAssetFile()
This method returns an asset file descriptor, but only if the provided MIME type is supported by the provider. The caller—the application doing the pasting—provides a MIME type pattern. The content provider of the application that copies a URI to the clipboard returns an
AssetFileDescriptor
file handle if it can provide that MIME type and throws an exception if it can't.This method handles subsections of files. You can use it to read assets that the content provider has copied to the clipboard.
-
openAssetFile()
- This method is a more general form of
openTypedAssetFile()
. It doesn't filter for allowed MIME types, but it can read subsections of files. -
openFile()
- This is a more general form of
openAssetFile()
. It can't read subsections of files.
You can optionally use the openPipeHelper()
method with your file descriptor method. This lets the pasting application read the stream data in a background thread using a pipe. To use this method, implement the ContentProvider.PipeDataWriter
interface.
Design effective copy and paste functionality
To design effective copy and paste functionality for your application, remember these points:
- At any time, there is only one clip on the clipboard. A new copy operation by any application in the system overwrites the previous clip. Since the user might navigate away from your application and copy before returning, you can't assume the clipboard contains the clip that the user previously copied in your application.
- The intended purpose of multiple
ClipData.Item
objects per clip is to support copying and pasting of multiple selections rather than different forms of reference to a single selection. You usually want all of theClipData.Item
objects in a clip to have the same form. That is, they must all be simple text, content URI, orIntent
, and not mixed. - When you provide data, you can offer different MIME representations. Add the MIME types you support to the
ClipDescription
, and then implement the MIME types in your content provider. - When you get data from the clipboard, your application is responsible for checking the available MIME types and then deciding which one, if any, to use. Even if there is a clip on the clipboard and the user requests a paste, your application isn't required to do the paste. Do the paste if the MIME type is compatible. You might coerce the data on the clipboard to text using
coerceToText()
. If your application supports more than one of the available MIME types, you can let the user pick which one to use.