অ্যান্ড্রয়েড ৪.৪ (এপিআই লেভেল ১৯) এবং উচ্চতর সংস্করণে চালিত ডিভাইসগুলিতে, আপনার অ্যাপ স্টোরেজ অ্যাক্সেস ফ্রেমওয়ার্ক ব্যবহার করে একটি ডকুমেন্ট প্রদানকারীর সাথে ইন্টারঅ্যাক্ট করতে পারে, যার মধ্যে রয়েছে বহিরাগত স্টোরেজ ভলিউম এবং ক্লাউড-ভিত্তিক স্টোরেজ। এই ফ্রেমওয়ার্ক ব্যবহারকারীদের একটি সিস্টেম পিকারের সাথে ইন্টারঅ্যাক্ট করে একটি ডকুমেন্ট প্রদানকারী বেছে নিতে এবং আপনার অ্যাপ তৈরি, খোলা বা পরিবর্তন করার জন্য নির্দিষ্ট ডকুমেন্ট এবং অন্যান্য ফাইল নির্বাচন করতে দেয়।
যেহেতু ব্যবহারকারী আপনার অ্যাপ কোন ফাইল বা ডিরেক্টরি অ্যাক্সেস করতে পারে তা নির্বাচন করার সাথে জড়িত, তাই এই প্রক্রিয়াটির জন্য কোনও সিস্টেম অনুমতির প্রয়োজন হয় না এবং ব্যবহারকারীর নিয়ন্ত্রণ এবং গোপনীয়তা উন্নত করা হয়। অতিরিক্তভাবে, এই ফাইলগুলি, যা একটি অ্যাপ-নির্দিষ্ট ডিরেক্টরির বাইরে এবং মিডিয়া স্টোরের বাইরে সংরক্ষণ করা হয়, আপনার অ্যাপ আনইনস্টল করার পরেও ডিভাইসে থেকে যায়।
কাঠামো ব্যবহারের ক্ষেত্রে নিম্নলিখিত পদক্ষেপগুলি অন্তর্ভুক্ত রয়েছে:
- একটি অ্যাপ এমন একটি ইন্টেন্ট চালু করে যার মধ্যে একটি স্টোরেজ-সম্পর্কিত অ্যাকশন থাকে। এই অ্যাকশনটি ফ্রেমওয়ার্ক দ্বারা উপলব্ধ একটি নির্দিষ্ট ব্যবহারের ক্ষেত্রের সাথে সঙ্গতিপূর্ণ।
- ব্যবহারকারী একটি সিস্টেম পিকার দেখতে পান, যা তাদের একটি ডকুমেন্ট প্রদানকারী ব্রাউজ করতে এবং স্টোরেজ-সম্পর্কিত ক্রিয়াটি যেখানে ঘটে সেখানে একটি অবস্থান বা ডকুমেন্ট বেছে নেওয়ার অনুমতি দেয়।
- অ্যাপটি ব্যবহারকারীর নির্বাচিত অবস্থান বা নথির প্রতিনিধিত্বকারী একটি URI-তে পঠন এবং লেখার অ্যাক্সেস পায়। এই URI ব্যবহার করে, অ্যাপটি নির্বাচিত অবস্থানে ক্রিয়াকলাপ সম্পাদন করতে পারে।
অ্যান্ড্রয়েড ৯ (এপিআই লেভেল ২৮) বা তার কম ভার্সন চালিত ডিভাইসগুলিতে মিডিয়া ফাইল অ্যাক্সেস সমর্থন করতে, READ_EXTERNAL_STORAGE অনুমতি ঘোষণা করুন এবং maxSdkVersion কে 28 এ সেট করুন।
এই নির্দেশিকাটি ফাইল এবং অন্যান্য নথির সাথে কাজ করার জন্য ফ্রেমওয়ার্কটি যে বিভিন্ন ব্যবহারের ক্ষেত্রে সমর্থন করে তা ব্যাখ্যা করে। এটি ব্যবহারকারী-নির্বাচিত স্থানে কীভাবে ক্রিয়াকলাপ সম্পাদন করতে হয় তাও ব্যাখ্যা করে।
নথি এবং অন্যান্য ফাইল অ্যাক্সেস করার জন্য কেস ব্যবহার করুন
স্টোরেজ অ্যাক্সেস ফ্রেমওয়ার্ক ফাইল এবং অন্যান্য নথি অ্যাক্সেস করার জন্য নিম্নলিখিত ব্যবহারের ক্ষেত্রে সমর্থন করে।
- একটি নতুন ফাইল তৈরি করুন
-
ACTION_CREATE_DOCUMENTইনটেন্ট অ্যাকশন ব্যবহারকারীদের একটি নির্দিষ্ট স্থানে একটি ফাইল সংরক্ষণ করতে দেয়। - একটি নথি বা ফাইল খুলুন
-
ACTION_OPEN_DOCUMENTইন্টেন্ট অ্যাকশন ব্যবহারকারীদের খোলার জন্য একটি নির্দিষ্ট নথি বা ফাইল নির্বাচন করতে দেয়। - ডিরেক্টরির বিষয়বস্তুতে অ্যাক্সেস মঞ্জুর করুন
- অ্যান্ড্রয়েড ৫.০ (এপিআই লেভেল ২১) এবং তার উচ্চতর সংস্করণে উপলব্ধ
ACTION_OPEN_DOCUMENT_TREEইন্টেন্ট অ্যাকশন ব্যবহারকারীদের একটি নির্দিষ্ট ডিরেক্টরি নির্বাচন করতে দেয়, যা আপনার অ্যাপকে সেই ডিরেক্টরির মধ্যে থাকা সমস্ত ফাইল এবং সাব-ডিরেক্টরিতে অ্যাক্সেস দেয়।
নিম্নলিখিত বিভাগগুলি প্রতিটি ব্যবহারের ক্ষেত্রে কীভাবে কনফিগার করতে হয় সে সম্পর্কে নির্দেশিকা প্রদান করে।
একটি নতুন ফাইল তৈরি করুন
সিস্টেম ফাইল পিকার লোড করার জন্য ACTION_CREATE_DOCUMENT ইন্টেন্ট অ্যাকশন ব্যবহার করুন এবং ব্যবহারকারীকে ফাইলের বিষয়বস্তু লেখার জন্য একটি অবস্থান বেছে নেওয়ার অনুমতি দিন। এই প্রক্রিয়াটি অন্যান্য অপারেটিং সিস্টেম ব্যবহার করে এমন "সেভ অ্যাজ" ডায়ালগে ব্যবহৃত প্রক্রিয়ার অনুরূপ।
দ্রষ্টব্য: ACTION_CREATE_DOCUMENT কোনও বিদ্যমান ফাইল ওভাররাইট করতে পারে না। যদি আপনার অ্যাপ একই নামের কোনও ফাইল সংরক্ষণ করার চেষ্টা করে, তাহলে সিস্টেমটি ফাইলের নামের শেষে বন্ধনীতে একটি সংখ্যা যুক্ত করে।
উদাহরণস্বরূপ, যদি আপনার অ্যাপটি confirmation.pdf নামক একটি ফাইল এমন একটি ডিরেক্টরিতে সংরক্ষণ করার চেষ্টা করে যেখানে ইতিমধ্যেই সেই নামের একটি ফাইল রয়েছে, তাহলে সিস্টেমটি confirmation(1).pdf নামক নতুন ফাইলটি সংরক্ষণ করে।
ইনটেন্ট কনফিগার করার সময়, ফাইলের নাম এবং MIME টাইপ উল্লেখ করুন, এবং ঐচ্ছিকভাবে EXTRA_INITIAL_URI ইনটেন্ট অতিরিক্ত ব্যবহার করে ফাইল বা ডিরেক্টরিটির URI নির্দিষ্ট করুন যা ফাইল পিকার প্রথম লোড হওয়ার সময় প্রদর্শন করবে।
নিম্নলিখিত কোড স্নিপেটটি দেখায় কিভাবে একটি ফাইল তৈরি করতে হয় এবং তৈরির উদ্দেশ্যটি কীভাবে ব্যবহার করতে হয়:
কোটলিন
// Request code for creating a PDF document. const val CREATE_FILE = 1 private fun createFile(pickerInitialUri: Uri) { val intent = Intent(Intent.ACTION_CREATE_DOCUMENT).apply { addCategory(Intent.CATEGORY_OPENABLE) type = "application/pdf" putExtra(Intent.EXTRA_TITLE, "invoice.pdf") // Optionally, specify a URI for the directory that should be opened in // the system file picker before your app creates the document. putExtra(DocumentsContract.EXTRA_INITIAL_URI, pickerInitialUri) } startActivityForResult(intent, CREATE_FILE) }
জাভা
// Request code for creating a PDF document. private static final int CREATE_FILE = 1; private void createFile(Uri pickerInitialUri) { Intent intent = new Intent(Intent.ACTION_CREATE_DOCUMENT); intent.addCategory(Intent.CATEGORY_OPENABLE); intent.setType("application/pdf"); intent.putExtra(Intent.EXTRA_TITLE, "invoice.pdf"); // Optionally, specify a URI for the directory that should be opened in // the system file picker when your app creates the document. intent.putExtra(DocumentsContract.EXTRA_INITIAL_URI, pickerInitialUri); startActivityForResult(intent, CREATE_FILE); }
একটি ফাইল খুলুন
আপনার অ্যাপটি স্টোরেজের একক হিসেবে ডকুমেন্ট ব্যবহার করতে পারে যেখানে ব্যবহারকারীরা এমন ডেটা প্রবেশ করান যা তারা সহকর্মীদের সাথে ভাগ করে নিতে বা অন্যান্য ডকুমেন্টে আমদানি করতে চাইতে পারে। বেশ কয়েকটি উদাহরণের মধ্যে রয়েছে একজন ব্যবহারকারী একটি প্রোডাক্টিভিটি ডকুমেন্ট খোলেন বা একটি EPUB ফাইল হিসেবে সংরক্ষিত একটি বই খোলেন।
এই ক্ষেত্রে, ব্যবহারকারীকে ACTION_OPEN_DOCUMENT ইন্টেন্ট ব্যবহার করে ফাইলটি খোলার জন্য বেছে নেওয়ার অনুমতি দিন, যা সিস্টেমের ফাইল পিকার অ্যাপটি খোলে। আপনার অ্যাপ যে ধরণের ফাইল সমর্থন করে শুধুমাত্র সেগুলি দেখানোর জন্য, একটি MIME টাইপ নির্দিষ্ট করুন। এছাড়াও, আপনি ঐচ্ছিকভাবে EXTRA_INITIAL_URI ইন্টেন্ট অতিরিক্ত ব্যবহার করে ফাইলটির URI নির্দিষ্ট করতে পারেন যা ফাইল পিকার প্রথম লোড হওয়ার সময় প্রদর্শন করবে।
নিম্নলিখিত কোড স্নিপেটটি দেখায় কিভাবে একটি PDF ডকুমেন্ট তৈরি এবং খোলার উদ্দেশ্যটি ব্যবহার করতে হয়:
কোটলিন
// Request code for selecting a PDF document. const val PICK_PDF_FILE = 2 fun openFile(pickerInitialUri: Uri) { val intent = Intent(Intent.ACTION_OPEN_DOCUMENT).apply { addCategory(Intent.CATEGORY_OPENABLE) type = "application/pdf" // Optionally, specify a URI for the file that should appear in the // system file picker when it loads. putExtra(DocumentsContract.EXTRA_INITIAL_URI, pickerInitialUri) } startActivityForResult(intent, PICK_PDF_FILE) }
জাভা
// Request code for selecting a PDF document. private static final int PICK_PDF_FILE = 2; private void openFile(Uri pickerInitialUri) { Intent intent = new Intent(Intent.ACTION_OPEN_DOCUMENT); intent.addCategory(Intent.CATEGORY_OPENABLE); intent.setType("application/pdf"); // Optionally, specify a URI for the file that should appear in the // system file picker when it loads. intent.putExtra(DocumentsContract.EXTRA_INITIAL_URI, pickerInitialUri); startActivityForResult(intent, PICK_PDF_FILE); }
অ্যাক্সেস সীমাবদ্ধতা
অ্যান্ড্রয়েড ১১ (এপিআই লেভেল ৩০) এবং তার উচ্চতর সংস্করণে, আপনি ACTION_OPEN_DOCUMENT ইন্টেন্ট অ্যাকশন ব্যবহার করে ব্যবহারকারীকে নিম্নলিখিত ডিরেক্টরিগুলি থেকে পৃথক ফাইল নির্বাচন করার অনুরোধ করতে পারবেন না:
-
Android/data/ডিরেক্টরি এবং সমস্ত সাবডিরেক্টরি। -
Android/obb/ডিরেক্টরি এবং সমস্ত সাবডিরেক্টরি।
ডিরেক্টরির বিষয়বস্তুতে অ্যাক্সেস মঞ্জুর করুন
ফাইল ম্যানেজমেন্ট এবং মিডিয়া-ক্রিয়েশন অ্যাপগুলি সাধারণত একটি ডিরেক্টরি হায়ারার্কিতে ফাইলের গ্রুপ পরিচালনা করে। আপনার অ্যাপে এই ক্ষমতা প্রদানের জন্য, ACTION_OPEN_DOCUMENT_TREE ইন্টেন্ট অ্যাকশন ব্যবহার করুন, যা ব্যবহারকারীকে Android 11 (API লেভেল 30) থেকে শুরু করে কিছু ব্যতিক্রম বাদে একটি সম্পূর্ণ ডিরেক্টরি ট্রিতে অ্যাক্সেস দেওয়ার অনুমতি দেয়। এরপর আপনার অ্যাপ নির্বাচিত ডিরেক্টরি এবং এর যেকোনো সাব-ডিরেক্টরিতে যেকোনো ফাইল অ্যাক্সেস করতে পারবে।
ACTION_OPEN_DOCUMENT_TREE ব্যবহার করার সময়, আপনার অ্যাপটি কেবলমাত্র ব্যবহারকারীর নির্বাচিত ডিরেক্টরিতে থাকা ফাইলগুলিতে অ্যাক্সেস পায়। ব্যবহারকারীর নির্বাচিত ডিরেক্টরির বাইরে থাকা অন্যান্য অ্যাপের ফাইলগুলিতে আপনার অ্যাক্সেস নেই। এই ব্যবহারকারী-নিয়ন্ত্রিত অ্যাক্সেস ব্যবহারকারীদের আপনার অ্যাপের সাথে কোন সামগ্রী ভাগ করতে স্বাচ্ছন্দ্য বোধ করে তা ঠিক করতে দেয়।
ঐচ্ছিকভাবে, আপনি EXTRA_INITIAL_URI ইনটেন্ট অতিরিক্ত ব্যবহার করে ফাইল পিকারটি প্রথম লোড হওয়ার সময় যে ডিরেক্টরিটি প্রদর্শন করবে তার URI নির্দিষ্ট করতে পারেন।
নিচের কোড স্নিপেটটি দেখায় কিভাবে একটি ডিরেক্টরি খোলার উদ্দেশ্য তৈরি এবং প্রয়োগ করতে হয়:
কোটলিন
fun openDirectory(pickerInitialUri: Uri) { // Choose a directory using the system's file picker. val intent = Intent(Intent.ACTION_OPEN_DOCUMENT_TREE).apply { // Optionally, specify a URI for the directory that should be opened in // the system file picker when it loads. putExtra(DocumentsContract.EXTRA_INITIAL_URI, pickerInitialUri) } startActivityForResult(intent, your-request-code) }
জাভা
public void openDirectory(Uri uriToLoad) { // Choose a directory using the system's file picker. Intent intent = new Intent(Intent.ACTION_OPEN_DOCUMENT_TREE); // Optionally, specify a URI for the directory that should be opened in // the system file picker when it loads. intent.putExtra(DocumentsContract.EXTRA_INITIAL_URI, uriToLoad); startActivityForResult(intent, your-request-code); }
অ্যাক্সেস সীমাবদ্ধতা
অ্যান্ড্রয়েড ১১ (এপিআই লেভেল ৩০) এবং তার উপরে, আপনি নিম্নলিখিত ডিরেক্টরিগুলিতে অ্যাক্সেসের অনুরোধ করার জন্য ACTION_OPEN_DOCUMENT_TREE ইন্টেন্ট অ্যাকশন ব্যবহার করতে পারবেন না:
- অভ্যন্তরীণ স্টোরেজ ভলিউমের রুট ডিরেক্টরি।
- প্রতিটি SD কার্ড ভলিউমের রুট ডিরেক্টরি যা ডিভাইস প্রস্তুতকারক নির্ভরযোগ্য বলে মনে করে, কার্ডটি অনুকরণ করা হোক বা অপসারণযোগ্য হোক না কেন। একটি নির্ভরযোগ্য ভলিউম হল এমন একটি ভলিউম যা একটি অ্যাপ বেশিরভাগ সময় সফলভাবে অ্যাক্সেস করতে পারে।
-
Downloadডিরেক্টরি।
অধিকন্তু, Android 11 (API লেভেল 30) এবং তার উচ্চতর সংস্করণগুলিতে, আপনি ACTION_OPEN_DOCUMENT_TREE ইন্টেন্ট অ্যাকশন ব্যবহার করে ব্যবহারকারীকে নিম্নলিখিত ডিরেক্টরিগুলি থেকে পৃথক ফাইল নির্বাচন করার অনুরোধ করতে পারবেন না:
-
Android/data/ডিরেক্টরি এবং সমস্ত সাবডিরেক্টরি। -
Android/obb/ডিরেক্টরি এবং সমস্ত সাবডিরেক্টরি।
নির্বাচিত স্থানে অপারেশন সম্পাদন করুন
সিস্টেমের ফাইল পিকার ব্যবহার করে ব্যবহারকারী কোনও ফাইল বা ডিরেক্টরি নির্বাচন করার পরে, আপনি onActivityResult() তে নিম্নলিখিত কোড ব্যবহার করে নির্বাচিত আইটেমের URI পুনরুদ্ধার করতে পারেন:
কোটলিন
override fun onActivityResult( requestCode: Int, resultCode: Int, resultData: Intent?) { if (requestCode == your-request-code && resultCode == Activity.RESULT_OK) { // The result data contains a URI for the document or directory that // the user selected. resultData?.data?.also { uri -> // Perform operations on the document using its URI. } } }
জাভা
@Override public void onActivityResult(int requestCode, int resultCode, Intent resultData) { if (requestCode == your-request-code && resultCode == Activity.RESULT_OK) { // The result data contains a URI for the document or directory that // the user selected. Uri uri = null; if (resultData != null) { uri = resultData.getData(); // Perform operations on the document using its URI. } } }
নির্বাচিত আইটেমের URI-এর রেফারেন্স পেয়ে, আপনার অ্যাপটি আইটেমটির উপর বেশ কয়েকটি ক্রিয়াকলাপ সম্পাদনা করতে পারে। উদাহরণস্বরূপ, আপনি আইটেমটির মেটাডেটা অ্যাক্সেস করতে পারেন, আইটেমটি যথাস্থানে সম্পাদনা করতে পারেন এবং আইটেমটি মুছে ফেলতে পারেন।
নিম্নলিখিত বিভাগগুলিতে ব্যবহারকারীর নির্বাচিত ফাইলগুলিতে কীভাবে ক্রিয়া সম্পন্ন করতে হয় তা দেখানো হয়েছে।
সরবরাহকারী কোন কোন কার্যক্রম সমর্থন করে তা নির্ধারণ করুন
বিভিন্ন কন্টেন্ট প্রদানকারীরা ডকুমেন্টে বিভিন্ন ক্রিয়াকলাপ সম্পাদনের অনুমতি দেয়—যেমন ডকুমেন্ট অনুলিপি করা বা ডকুমেন্টের থাম্বনেইল দেখা। প্রদত্ত প্রদানকারী কোন ক্রিয়াকলাপ সমর্থন করে তা নির্ধারণ করতে, Document.COLUMN_FLAGS এর মান পরীক্ষা করুন। আপনার অ্যাপের UI তখন কেবলমাত্র সেই বিকল্পগুলি দেখাতে পারে যা প্রদানকারী সমর্থন করে।
অনুমতিগুলি বজায় রাখুন
যখন আপনার অ্যাপটি পড়ার বা লেখার জন্য একটি ফাইল খোলে, তখন সিস্টেমটি আপনার অ্যাপটিকে সেই ফাইলের জন্য একটি URI অনুমতি প্রদান করে, যা ব্যবহারকারীর ডিভাইসটি পুনরায় চালু না হওয়া পর্যন্ত স্থায়ী হয়। তবে, ধরুন, আপনার অ্যাপটি একটি চিত্র-সম্পাদনা অ্যাপ, এবং আপনি চান যে ব্যবহারকারীরা আপনার অ্যাপ থেকে সরাসরি তাদের সাম্প্রতিক সম্পাদনা করা 5টি চিত্র অ্যাক্সেস করতে সক্ষম হন। যদি ব্যবহারকারীর ডিভাইসটি পুনরায় চালু হয়ে থাকে, তাহলে ফাইলগুলি খুঁজে পেতে আপনাকে ব্যবহারকারীকে সিস্টেম পিকারে ফেরত পাঠাতে হবে।
ডিভাইস রিস্টার্ট জুড়ে ফাইলগুলিতে অ্যাক্সেস সংরক্ষণ করতে এবং আরও ভালো ব্যবহারকারীর অভিজ্ঞতা তৈরি করতে, আপনার অ্যাপ সিস্টেমের অফার করা স্থায়ী URI অনুমতি "গ্রহণ" করতে পারে, যেমনটি নিম্নলিখিত কোড স্নিপেটে দেখানো হয়েছে:
কোটলিন
val contentResolver = applicationContext.contentResolver val takeFlags: Int = Intent.FLAG_GRANT_READ_URI_PERMISSION or Intent.FLAG_GRANT_WRITE_URI_PERMISSION // Check for the freshest data. contentResolver.takePersistableUriPermission(uri, takeFlags)
জাভা
final int takeFlags = intent.getFlags() & (Intent.FLAG_GRANT_READ_URI_PERMISSION | Intent.FLAG_GRANT_WRITE_URI_PERMISSION); // Check for the freshest data. getContentResolver().takePersistableUriPermission(uri, takeFlags);
ডকুমেন্ট মেটাডেটা পরীক্ষা করুন
যখন আপনার কাছে একটি ডকুমেন্টের URI থাকে, তখন আপনি এর মেটাডেটা অ্যাক্সেস করতে পারবেন। এই স্নিপেটটি URI দ্বারা নির্দিষ্ট করা একটি ডকুমেন্টের মেটাডেটা ধরে এবং এটি লগ করে:
কোটলিন
val contentResolver = applicationContext.contentResolver fun dumpImageMetaData(uri: Uri) { // The query, because it only applies to a single document, returns only // one row. There's no need to filter, sort, or select fields, // because we want all fields for one document. val cursor: Cursor? = contentResolver.query( uri, null, null, null, null, null) cursor?.use { // moveToFirst() returns false if the cursor has 0 rows. Very handy for // "if there's anything to look at, look at it" conditionals. if (it.moveToFirst()) { // Note it's called "Display Name". This is // provider-specific, and might not necessarily be the file name. val displayName: String = it.getString(it.getColumnIndex(OpenableColumns.DISPLAY_NAME)) Log.i(TAG, "Display Name: $displayName") val sizeIndex: Int = it.getColumnIndex(OpenableColumns.SIZE) // If the size is unknown, the value stored is null. But because an // int can't be null, the behavior is implementation-specific, // and unpredictable. So as // a rule, check if it's null before assigning to an int. This will // happen often: The storage API allows for remote files, whose // size might not be locally known. val size: String = if (!it.isNull(sizeIndex)) { // Technically the column stores an int, but cursor.getString() // will do the conversion automatically. it.getString(sizeIndex) } else { "Unknown" } Log.i(TAG, "Size: $size") } } }
জাভা
public void dumpImageMetaData(Uri uri) { // The query, because it only applies to a single document, returns only // one row. There's no need to filter, sort, or select fields, // because we want all fields for one document. Cursor cursor = getActivity().getContentResolver() .query(uri, null, null, null, null, null); try { // moveToFirst() returns false if the cursor has 0 rows. Very handy for // "if there's anything to look at, look at it" conditionals. if (cursor != null && cursor.moveToFirst()) { // Note it's called "Display Name". This is // provider-specific, and might not necessarily be the file name. String displayName = cursor.getString( cursor.getColumnIndex(OpenableColumns.DISPLAY_NAME)); Log.i(TAG, "Display Name: " + displayName); int sizeIndex = cursor.getColumnIndex(OpenableColumns.SIZE); // If the size is unknown, the value stored is null. But because an // int can't be null, the behavior is implementation-specific, // and unpredictable. So as // a rule, check if it's null before assigning to an int. This will // happen often: The storage API allows for remote files, whose // size might not be locally known. String size = null; if (!cursor.isNull(sizeIndex)) { // Technically the column stores an int, but cursor.getString() // will do the conversion automatically. size = cursor.getString(sizeIndex); } else { size = "Unknown"; } Log.i(TAG, "Size: " + size); } } finally { cursor.close(); } }
একটি নথি খুলুন
একটি ডকুমেন্টের URI-এর রেফারেন্স ব্যবহার করে, আপনি আরও প্রক্রিয়াকরণের জন্য একটি ডকুমেন্ট খুলতে পারেন। এই বিভাগে একটি বিটম্যাপ এবং একটি ইনপুট স্ট্রিম খোলার উদাহরণ দেখানো হয়েছে।
বিটম্যাপ
নিচের কোড স্নিপেটটি দেখায় যে কীভাবে একটি Bitmap ফাইলের URI দেওয়া হয়:
কোটলিন
val contentResolver = applicationContext.contentResolver @Throws(IOException::class) private fun getBitmapFromUri(uri: Uri): Bitmap { val parcelFileDescriptor: ParcelFileDescriptor = contentResolver.openFileDescriptor(uri, "r") val fileDescriptor: FileDescriptor = parcelFileDescriptor.fileDescriptor val image: Bitmap = BitmapFactory.decodeFileDescriptor(fileDescriptor) parcelFileDescriptor.close() return image }
জাভা
private Bitmap getBitmapFromUri(Uri uri) throws IOException { ParcelFileDescriptor parcelFileDescriptor = getContentResolver().openFileDescriptor(uri, "r"); FileDescriptor fileDescriptor = parcelFileDescriptor.getFileDescriptor(); Bitmap image = BitmapFactory.decodeFileDescriptor(fileDescriptor); parcelFileDescriptor.close(); return image; }
বিটম্যাপ খোলার পর, আপনি এটি একটি ImageView এ প্রদর্শন করতে পারেন।
ইনপুট স্ট্রিম
নিচের কোড স্নিপেটে দেখানো হয়েছে কিভাবে একটি InputStream অবজেক্ট খুলতে হয়, তার URI অনুযায়ী। এই স্নিপেটে, ফাইলের লাইনগুলি একটি স্ট্রিংয়ে পড়া হচ্ছে:
কোটলিন
val contentResolver = applicationContext.contentResolver @Throws(IOException::class) private fun readTextFromUri(uri: Uri): String { val stringBuilder = StringBuilder() contentResolver.openInputStream(uri)?.use { inputStream -> BufferedReader(InputStreamReader(inputStream)).use { reader -> var line: String? = reader.readLine() while (line != null) { stringBuilder.append(line) line = reader.readLine() } } } return stringBuilder.toString() }
জাভা
private String readTextFromUri(Uri uri) throws IOException { StringBuilder stringBuilder = new StringBuilder(); try (InputStream inputStream = getContentResolver().openInputStream(uri); BufferedReader reader = new BufferedReader( new InputStreamReader(Objects.requireNonNull(inputStream)))) { String line; while ((line = reader.readLine()) != null) { stringBuilder.append(line); } } return stringBuilder.toString(); }
একটি ডকুমেন্ট সম্পাদনা করুন
আপনি স্টোরেজ অ্যাক্সেস ফ্রেমওয়ার্ক ব্যবহার করে একটি টেক্সট ডকুমেন্ট সম্পাদনা করতে পারেন।
নিম্নলিখিত কোড স্নিপেটটি প্রদত্ত URI দ্বারা প্রতিনিধিত্ব করা ডকুমেন্টের বিষয়বস্তু ওভাররাইট করে:
কোটলিন
val contentResolver = applicationContext.contentResolver private fun alterDocument(uri: Uri) { try { contentResolver.openFileDescriptor(uri, "w")?.use { FileOutputStream(it.fileDescriptor).use { it.write( ("Overwritten at ${System.currentTimeMillis()}\n") .toByteArray() ) } } } catch (e: FileNotFoundException) { e.printStackTrace() } catch (e: IOException) { e.printStackTrace() } }
জাভা
private void alterDocument(Uri uri) { try { ParcelFileDescriptor pfd = getActivity().getContentResolver(). openFileDescriptor(uri, "w"); FileOutputStream fileOutputStream = new FileOutputStream(pfd.getFileDescriptor()); fileOutputStream.write(("Overwritten at " + System.currentTimeMillis() + "\n").getBytes()); // Let the document provider know you're done by closing the stream. fileOutputStream.close(); pfd.close(); } catch (FileNotFoundException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } }
একটি ডকুমেন্ট মুছে ফেলুন
যদি আপনার কাছে কোন ডকুমেন্টের URI থাকে এবং ডকুমেন্টের Document.COLUMN_FLAGS এ SUPPORTS_DELETE থাকে, তাহলে আপনি ডকুমেন্টটি মুছে ফেলতে পারেন। উদাহরণস্বরূপ:
কোটলিন
DocumentsContract.deleteDocument(applicationContext.contentResolver, uri)
জাভা
DocumentsContract.deleteDocument(applicationContext.contentResolver, uri);
একটি সমতুল্য মিডিয়া URI পুনরুদ্ধার করুন
getMediaUri() পদ্ধতিটি একটি মিডিয়া স্টোর URI প্রদান করে যা প্রদত্ত ডকুমেন্ট প্রদানকারী URI এর সমতুল্য। দুটি URI একই অন্তর্নিহিত আইটেমকে নির্দেশ করে। মিডিয়া স্টোর URI ব্যবহার করে, আপনি শেয়ার্ড স্টোরেজ থেকে মিডিয়া ফাইলগুলি আরও সহজেই অ্যাক্সেস করতে পারবেন।
getMediaUri() পদ্ধতিটি ExternalStorageProvider URI সমর্থন করে। Android 12 (API লেভেল 31) এবং উচ্চতর সংস্করণে, পদ্ধতিটি MediaDocumentsProvider URI সমর্থন করে।
একটি ভার্চুয়াল ফাইল খুলুন
অ্যান্ড্রয়েড ৭.০ (এপিআই লেভেল ২৫) এবং তার উচ্চতর সংস্করণে, আপনার অ্যাপ স্টোরেজ অ্যাক্সেস ফ্রেমওয়ার্ক দ্বারা উপলব্ধ ভার্চুয়াল ফাইলগুলি ব্যবহার করতে পারে। যদিও ভার্চুয়াল ফাইলগুলির বাইনারি উপস্থাপনা নেই, তবুও আপনার অ্যাপ তাদের বিষয়বস্তুগুলিকে একটি ভিন্ন ফাইল টাইপে জোর করে অথবা ACTION_VIEW ইনটেন্ট অ্যাকশন ব্যবহার করে সেই ফাইলগুলি দেখে খুলতে পারে।
ভার্চুয়াল ফাইল খোলার জন্য, আপনার ক্লায়েন্ট অ্যাপে বিশেষ লজিক ব্যবহার করতে হবে যাতে সেগুলি পরিচালনা করা যায়। যদি আপনি ফাইলটির একটি বাইট উপস্থাপনা পেতে চান - উদাহরণস্বরূপ, ফাইলটির পূর্বরূপ দেখতে - তাহলে আপনাকে ডকুমেন্ট প্রদানকারীর কাছ থেকে একটি বিকল্প MIME টাইপের জন্য অনুরোধ করতে হবে।
ব্যবহারকারী নির্বাচন করার পর, ফলাফল ডেটাতে URI ব্যবহার করে ফাইলটি ভার্চুয়াল কিনা তা নির্ধারণ করুন, যেমনটি নিম্নলিখিত কোড স্নিপেটে দেখানো হয়েছে:
কোটলিন
private fun isVirtualFile(uri: Uri): Boolean { if (!DocumentsContract.isDocumentUri(this, uri)) { return false } val cursor: Cursor? = contentResolver.query( uri, arrayOf(DocumentsContract.Document.COLUMN_FLAGS), null, null, null ) val flags: Int = cursor?.use { if (cursor.moveToFirst()) { cursor.getInt(0) } else { 0 } } ?: 0 return flags and DocumentsContract.Document.FLAG_VIRTUAL_DOCUMENT != 0 }
জাভা
private boolean isVirtualFile(Uri uri) { if (!DocumentsContract.isDocumentUri(this, uri)) { return false; } Cursor cursor = getContentResolver().query( uri, new String[] { DocumentsContract.Document.COLUMN_FLAGS }, null, null, null); int flags = 0; if (cursor.moveToFirst()) { flags = cursor.getInt(0); } cursor.close(); return (flags & DocumentsContract.Document.FLAG_VIRTUAL_DOCUMENT) != 0; }
ডকুমেন্টটি একটি ভার্চুয়াল ফাইল কিনা তা যাচাই করার পর, আপনি ফাইলটিকে "image/png" এর মতো একটি বিকল্প MIME টাইপে জোর করে রূপান্তর করতে পারেন। নিম্নলিখিত কোড স্নিপেটটি দেখায় যে কীভাবে একটি ভার্চুয়াল ফাইলকে একটি চিত্র হিসাবে উপস্থাপন করা যায় কিনা তা পরীক্ষা করতে হয় এবং যদি তাই হয়, তাহলে ভার্চুয়াল ফাইল থেকে একটি ইনপুট স্ট্রিম পায়:
কোটলিন
@Throws(IOException::class) private fun getInputStreamForVirtualFile( uri: Uri, mimeTypeFilter: String): InputStream { val openableMimeTypes: Array<String>? = contentResolver.getStreamTypes(uri, mimeTypeFilter) return if (openableMimeTypes?.isNotEmpty() == true) { contentResolver .openTypedAssetFileDescriptor(uri, openableMimeTypes[0], null) .createInputStream() } else { throw FileNotFoundException() } }
জাভা
private InputStream getInputStreamForVirtualFile(Uri uri, String mimeTypeFilter) throws IOException { ContentResolver resolver = getContentResolver(); String[] openableMimeTypes = resolver.getStreamTypes(uri, mimeTypeFilter); if (openableMimeTypes == null || openableMimeTypes.length < 1) { throw new FileNotFoundException(); } return resolver .openTypedAssetFileDescriptor(uri, openableMimeTypes[0], null) .createInputStream(); }
অতিরিক্ত সম্পদ
ডকুমেন্ট এবং অন্যান্য ফাইল কীভাবে সংরক্ষণ এবং অ্যাক্সেস করবেন সে সম্পর্কে আরও তথ্যের জন্য, নিম্নলিখিত সংস্থানগুলি দেখুন।
নমুনা
- ActionOpenDocument , GitHub-এ উপলব্ধ।
- ActionOpenDocumentTree , GitHub-এ উপলব্ধ।