Android 4.4 (एपीआई लेवल 19) और इसके बाद के वर्शन वाले डिवाइसों पर, आपका ऐप्लिकेशन दस्तावेज़ उपलब्ध कराने वाली सेवा के साथ इंटरैक्ट कर सकता है. इसमें, बाहरी स्टोरेज वॉल्यूम और क्लाउड-आधारित स्टोरेज भी शामिल है. इसके लिए, ऐप्लिकेशन को स्टोरेज ऐक्सेस फ़्रेमवर्क का इस्तेमाल करना होगा. इस फ़्रेमवर्क की मदद से, उपयोगकर्ता किसी दस्तावेज़ उपलब्ध कराने वाली सेवा चुनने के लिए, सिस्टम पिकर के साथ इंटरैक्ट कर सकते हैं. साथ ही, आपके ऐप्लिकेशन के लिए खास दस्तावेज़ और अन्य फ़ाइलें चुन सकते हैं, ताकि उन्हें बनाया जा सके, खोला जा सके या उनमें बदलाव किया जा सके.
इस प्रोसेस में, उपयोगकर्ता उन फ़ाइलों या डायरेक्ट्री को चुनता है जिन्हें आपका ऐप्लिकेशन ऐक्सेस कर सकता है. इसलिए, इस प्रोसेस के लिए किसी भी सिस्टम की अनुमति की ज़रूरत नहीं होती. साथ ही, उपयोगकर्ता का कंट्रोल और निजता बेहतर होती है. इसके अलावा, ये फ़ाइलें ऐप्लिकेशन की डायरेक्ट्री और मीडिया स्टोर के बाहर सेव की जाती हैं. इसलिए, ऐप्लिकेशन को अनइंस्टॉल करने के बाद भी ये फ़ाइलें डिवाइस में बनी रहती हैं.
फ़्रेमवर्क का इस्तेमाल करने के लिए, यह तरीका अपनाएं:
- कोई ऐप्लिकेशन, स्टोरेज से जुड़ी कार्रवाई वाले इंटेंट को ट्रिगर करता है. यह कार्रवाई, इस्तेमाल के किसी खास उदाहरण से जुड़ी होती है, जिसे फ़्रेमवर्क उपलब्ध कराता है.
- उपयोगकर्ता को एक सिस्टम पिकर दिखता है. इसकी मदद से, वह दस्तावेज़ों की सेवा देने वाली कंपनी को ब्राउज़ कर सकता है और वह जगह या दस्तावेज़ चुन सकता है जहां स्टोरेज से जुड़ी कार्रवाई की जानी है.
- ऐप्लिकेशन को उस यूआरआई का पढ़ने और उसमें बदलाव करने का ऐक्सेस मिल जाता है जो उपयोगकर्ता की चुनी गई जगह या दस्तावेज़ को दिखाता है. इस यूआरआई का इस्तेमाल करके, ऐप्लिकेशन चुनी गई जगह पर काम कर सकता है.
Android 9 (एपीआई लेवल 28) या उससे पहले के वर्शन वाले डिवाइसों पर मीडिया फ़ाइल को ऐक्सेस करने की सुविधा देने के लिए, READ_EXTERNAL_STORAGE
अनुमति का एलान करें और maxSdkVersion
को 28
पर सेट करें.
इस गाइड में, फ़ाइलों और अन्य दस्तावेज़ों के साथ काम करने के लिए, फ़्रेमवर्क के अलग-अलग इस्तेमाल के उदाहरणों के बारे में बताया गया है. इसमें यह भी बताया गया है कि उपयोगकर्ता की चुनी गई जगह पर, कार्रवाइयां कैसे की जा सकती हैं.
दस्तावेज़ों और अन्य फ़ाइलों को ऐक्सेस करने के उदाहरण
स्टोरेज ऐक्सेस फ़्रेमवर्क, फ़ाइलों और अन्य दस्तावेज़ों को ऐक्सेस करने के लिए, इस्तेमाल के इन उदाहरणों के साथ काम करता है.
- नई फ़ाइल बनाना
ACTION_CREATE_DOCUMENT
के ज़रिए, उपयोगकर्ता किसी फ़ाइल को किसी खास जगह पर सेव कर सकते हैं.- दस्तावेज़ या फ़ाइल खोलना
ACTION_OPEN_DOCUMENT
के लिए इंटेंट ऐक्शन की मदद से, उपयोगकर्ता किसी खास दस्तावेज़ या फ़ाइल को खोल सकते हैं.- किसी डायरेक्ट्री के कॉन्टेंट का ऐक्सेस देना
- Android 5.0 (एपीआई लेवल 21) और उसके बाद के वर्शन पर उपलब्ध,
ACTION_OPEN_DOCUMENT_TREE
Intent ऐक्शन की मदद से, उपयोगकर्ता किसी डायरेक्ट्री को चुन सकते हैं. इससे आपके ऐप्लिकेशन को उस डायरेक्ट्री में मौजूद सभी फ़ाइलों और सब-डायरेक्ट्री का ऐक्सेस मिल जाता है.
यहां दिए गए सेक्शन में, इस्तेमाल के हर उदाहरण को कॉन्फ़िगर करने का तरीका बताया गया है.
नई फ़ाइल बनाना
सिस्टम फ़ाइल पिकर को लोड करने के लिए, ACTION_CREATE_DOCUMENT
इंटेंट ऐक्शन का इस्तेमाल करें. साथ ही, उपयोगकर्ता को वह जगह चुनने की अनुमति दें जहां फ़ाइल का कॉन्टेंट लिखना है. यह प्रोसेस, "इस रूप में सेव करें" डायलॉग बॉक्स में इस्तेमाल की जाने वाली प्रोसेस से मिलती-जुलती है.
ध्यान दें: ACTION_CREATE_DOCUMENT
किसी मौजूदा फ़ाइल को ओवरराइट नहीं कर सकता. अगर आपका ऐप्लिकेशन उसी नाम वाली फ़ाइल को सेव करने की कोशिश करता है, तो सिस्टम
फ़ाइल के नाम के आखिर में ब्रैकेट में एक नंबर जोड़ देता है.
उदाहरण के लिए, अगर आपका ऐप्लिकेशन किसी ऐसी डायरेक्ट्री में confirmation.pdf
नाम की फ़ाइल सेव करने की कोशिश करता है जिसमें पहले से ही उस नाम की फ़ाइल मौजूद है, तो सिस्टम नई फ़ाइल को confirmation(1).pdf
नाम से सेव करता है.
इंटेंट को कॉन्फ़िगर करते समय, फ़ाइल का नाम और MIME टाइप बताएं. इसके अलावा, अगर ज़रूरी हो, तो उस फ़ाइल या डायरेक्ट्री का यूआरआई बताएं जिसे फ़ाइल पिकर को पहली बार लोड होने पर दिखाना चाहिए. इसके लिए, EXTRA_INITIAL_URI
के तौर पर इंटेंट एक्सट्रा का इस्तेमाल करें.
नीचे दिया गया कोड स्निपेट, फ़ाइल बनाने के लिए इंटेंट बनाने और उसे ट्रिगर करने का तरीका दिखाता है:
Kotlin
// 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) }
Java
// 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
इंटेंट एक्सट्रा का इस्तेमाल करके, फ़ाइल पिकर के पहली बार लोड होने पर दिखने वाली फ़ाइल का यूआरआई भी दिया जा सकता है.
नीचे दिए गए कोड स्निपेट में, PDF दस्तावेज़ खोलने के लिए इंटेंट बनाने और उसे लागू करने का तरीका बताया गया है:
Kotlin
// 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) }
Java
// 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); }
ऐक्सेस से जुड़ी पाबंदियां
Android 11 (एपीआई लेवल 30) और उसके बाद के वर्शन पर, ACTION_OPEN_DOCUMENT
इंटेंट ऐक्शन का इस्तेमाल करके, उपयोगकर्ता से इन डायरेक्ट्री से अलग-अलग फ़ाइलें चुनने का अनुरोध नहीं किया जा सकता:
Android/data/
डायरेक्ट्री और सभी सबडायरेक्ट्री.Android/obb/
डायरेक्ट्री और सभी सबडायरेक्ट्री.
डायरेक्ट्री के कॉन्टेंट का ऐक्सेस देना
फ़ाइल मैनेजमेंट और मीडिया बनाने वाले ऐप्लिकेशन, आम तौर पर डायरेक्ट्री के क्रम में फ़ाइलों के ग्रुप मैनेज करते हैं. अपने ऐप्लिकेशन में यह सुविधा देने के लिए, ACTION_OPEN_DOCUMENT_TREE
इंटेंट ऐक्शन का इस्तेमाल करें. इससे उपयोगकर्ता को पूरी डायरेक्ट्री ट्री का ऐक्सेस देने की अनुमति मिलती है. हालांकि, Android 11 (एपीआई लेवल 30) से कुछ अपवाद लागू होंगे. इसके बाद, आपका ऐप्लिकेशन चुने गए डायरेक्ट्री और उसकी किसी भी सब-डायरेक्ट्री में मौजूद किसी भी फ़ाइल को ऐक्सेस कर सकता है.
ACTION_OPEN_DOCUMENT_TREE
का इस्तेमाल करने पर, आपके ऐप्लिकेशन को सिर्फ़ उस डायरेक्ट्री में मौजूद फ़ाइलों का ऐक्सेस मिलता है जिसे उपयोगकर्ता चुनता है. आपके पास उन अन्य ऐप्लिकेशन की फ़ाइलों का ऐक्सेस नहीं होता जो उपयोगकर्ता की चुनी गई डायरेक्ट्री के बाहर मौजूद होती हैं. उपयोगकर्ता के कंट्रोल वाले इस ऐक्सेस की मदद से, उपयोगकर्ता यह चुन सकते हैं कि उन्हें आपके ऐप्लिकेशन के साथ कौनसा कॉन्टेंट शेयर करना है.
इसके अलावा, EXTRA_INITIAL_URI
के ज़रिए, उस डायरेक्ट्री का यूआरआई भी दिया जा सकता है जिसे फ़ाइल पिकर को पहली बार लोड होने पर दिखाना है.
नीचे दिए गए कोड स्निपेट में, डायरेक्ट्री खोलने के लिए इंटेंट बनाने और उसे शुरू करने का तरीका बताया गया है:
Kotlin
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) }
Java
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); }
ऐक्सेस से जुड़ी पाबंदियां
Android 11 (एपीआई लेवल 30) और उसके बाद के वर्शन पर, इन डायरेक्ट्री को ऐक्सेस करने का अनुरोध करने के लिए, ACTION_OPEN_DOCUMENT_TREE
इंटेंट ऐक्शन का इस्तेमाल नहीं किया जा सकता:
- डिवाइस के स्टोरेज वॉल्यूम की रूट डायरेक्ट्री.
- हर उस एसडी कार्ड वॉल्यूम की रूट डायरेक्ट्री जिसे डिवाइस बनाने वाली कंपनी भरोसेमंद मानती है. भले ही, कार्ड को एमुलेट किया गया हो या उसे हटाया जा सकता हो. भरोसेमंद वॉल्यूम वह होता है जिसे ऐप्लिकेशन ज़्यादातर समय ऐक्सेस कर सकता है.
Download
डायरेक्ट्री.
इसके अलावा, Android 11 (एपीआई लेवल 30) और इसके बाद के वर्शन पर, ACTION_OPEN_DOCUMENT_TREE
इंटेंट ऐक्शन का इस्तेमाल करके, उपयोगकर्ता से इन डायरेक्ट्री से अलग-अलग फ़ाइलें चुनने का अनुरोध नहीं किया जा सकता:
Android/data/
डायरेक्ट्री और सभी सबडायरेक्ट्री.Android/obb/
डायरेक्ट्री और सभी सबडायरेक्ट्री.
चुनी गई जगह पर कार्रवाइयां करना
जब उपयोगकर्ता सिस्टम के फ़ाइल पिकर का इस्तेमाल करके कोई फ़ाइल या डायरेक्ट्री चुन लेता है, तो onActivityResult()
में दिए गए कोड का इस्तेमाल करके, चुने गए आइटम का यूआरआई वापस पाया जा सकता है:
Kotlin
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. } } }
Java
@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. } } }
चुने गए आइटम के यूआरआई का रेफ़रंस पाकर, आपका ऐप्लिकेशन उस आइटम पर कई कार्रवाइयां कर सकता है. उदाहरण के लिए, आइटम का मेटाडेटा ऐक्सेस किया जा सकता है, आइटम में बदलाव किया जा सकता है, और आइटम को मिटाया जा सकता है.
यहां दिए गए सेक्शन में, उन फ़ाइलों पर कार्रवाइयां करने का तरीका बताया गया है जिन्हें उपयोगकर्ता चुनता है.
यह तय करना कि सेवा देने वाली कंपनी कौनसी कार्रवाइयां करती है
कॉन्टेंट की सेवा देने वाली अलग-अलग कंपनियां, दस्तावेज़ों पर अलग-अलग कार्रवाइयां करने की अनुमति देती हैं. जैसे, दस्तावेज़ को कॉपी करना या दस्तावेज़ का थंबनेल देखना. यह पता करने के लिए कि कोई प्रोवाइडर किन ऑपरेशन के साथ काम करता है, Document.COLUMN_FLAGS
की वैल्यू देखें.
इसके बाद, आपके ऐप्लिकेशन का यूज़र इंटरफ़ेस (यूआई) सिर्फ़ वे विकल्प दिखा सकता है जो सेवा देने वाली कंपनी के साथ काम करते हैं.
अनुमतियां सेव करना
जब आपका ऐप्लिकेशन किसी फ़ाइल को पढ़ने या उसमें बदलाव करने के लिए खोलता है, तो सिस्टम उस फ़ाइल के लिए आपके ऐप्लिकेशन को यूआरआई की अनुमति देता है. यह अनुमति तब तक रहती है, जब तक उपयोगकर्ता का डिवाइस रीस्टार्ट नहीं हो जाता. हालांकि, मान लें कि आपका ऐप्लिकेशन इमेज में बदलाव करने वाला ऐप्लिकेशन है और आपको उपयोगकर्ताओं को उन पांच इमेज को ऐक्सेस करने की अनुमति देनी है जिनमें उन्होंने हाल ही में बदलाव किया है. इसके लिए, उन्हें सीधे आपके ऐप्लिकेशन से इमेज ऐक्सेस करनी होंगी. अगर उपयोगकर्ता का डिवाइस रीस्टार्ट हो गया है, तो फ़ाइलें ढूंढने के लिए, आपको उपयोगकर्ता को सिस्टम पिकर पर वापस भेजना होगा.
डिवाइस को रीस्टार्ट करने के बाद भी फ़ाइलों का ऐक्सेस बनाए रखने और उपयोगकर्ताओं को बेहतर अनुभव देने के लिए, आपका ऐप्लिकेशन सिस्टम से मिलने वाली, यूआरआई को सेव करने की अनुमति "ले सकता है". इसकी जानकारी, नीचे दिए गए कोड स्निपेट में दी गई है:
Kotlin
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)
Java
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);
दस्तावेज़ के मेटाडेटा की जांच करना
किसी दस्तावेज़ का यूआरआई होने पर, आपके पास उसके मेटाडेटा का ऐक्सेस होता है. यह स्निपेट, यूआरआई से तय किए गए दस्तावेज़ का मेटाडेटा लेता है और उसे लॉग करता है:
Kotlin
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") } } }
Java
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(); } }
दस्तावेज़ खोलना
किसी दस्तावेज़ के यूआरआई का रेफ़रंस होने पर, उसे आगे प्रोसेस करने के लिए खोला जा सकता है. इस सेक्शन में, बिटमैप और इनपुट स्ट्रीम खोलने के उदाहरण दिए गए हैं.
बिटमैप
नीचे दिए गए कोड स्निपेट में, यूआरआई की मदद से Bitmap
फ़ाइल खोलने का तरीका बताया गया है:
Kotlin
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 }
Java
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 ऑब्जेक्ट को उसके यूआरआई के हिसाब से खोलने का तरीका बताया गया है. इस स्निपेट में, फ़ाइल की लाइनों को स्ट्रिंग में पढ़ा जा रहा है:
Kotlin
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() }
Java
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(); }
दस्तावेज़ में बदलाव करना
किसी टेक्स्ट दस्तावेज़ में बदलाव करने के लिए, स्टोरेज ऐक्सेस फ़्रेमवर्क का इस्तेमाल किया जा सकता है.
यहां दिया गया कोड स्निपेट, दिए गए यूआरआई से दिखाए गए दस्तावेज़ के कॉन्टेंट को ओवरराइट करता है:
Kotlin
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() } }
Java
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(); } }
दस्तावेज़ मिटाना
अगर आपके पास किसी दस्तावेज़ का यूआरआई है और दस्तावेज़ के Document.COLUMN_FLAGS
में SUPPORTS_DELETE
है, तो दस्तावेज़ को मिटाया जा सकता है. उदाहरण के लिए:
Kotlin
DocumentsContract.deleteDocument(applicationContext.contentResolver, uri)
Java
DocumentsContract.deleteDocument(applicationContext.contentResolver, uri);
मिलता-जुलता मीडिया यूआरआई वापस पाना
getMediaUri()
वाला तरीका, मीडिया स्टोर का ऐसा यूआरएल उपलब्ध कराता है जो दस्तावेज़ उपलब्ध कराने वाले के दिए गए यूआरएल से मेल खाता है. दोनों यूआरआई, एक ही आइटम पर ले जाते हैं. मीडिया स्टोर के यूआरआई का इस्तेमाल करके, शेयर किए गए स्टोरेज से मीडिया फ़ाइलों को आसानी से ऐक्सेस किया जा सकता है.
getMediaUri()
तरीका, ExternalStorageProvider
यूआरआई के साथ काम करता है. Android 12 (एपीआई लेवल 31) और उसके बाद के वर्शन पर, यह तरीका MediaDocumentsProvider
यूआरआई के साथ भी काम करता है.
वर्चुअल फ़ाइल खोलना
Android 7.0 (एपीआई लेवल 25) और उसके बाद के वर्शन पर, आपका ऐप्लिकेशन उन वर्चुअल फ़ाइलों का इस्तेमाल कर सकता है जिन्हें स्टोरेज ऐक्सेस फ़्रेमवर्क उपलब्ध कराता है. भले ही, वर्चुअल फ़ाइलों का बाइनरी वर्शन न हो, लेकिन आपका ऐप्लिकेशन उनके कॉन्टेंट को खोल सकता है. इसके लिए, उन्हें किसी दूसरे फ़ाइल टाइप में बदलना होगा या ACTION_VIEW
इंटेंट ऐक्शन का इस्तेमाल करके उन्हें देखना होगा.
वर्चुअल फ़ाइलें खोलने के लिए, आपके क्लाइंट ऐप्लिकेशन में उन्हें मैनेज करने के लिए खास लॉजिक शामिल होना चाहिए. अगर आपको फ़ाइल की झलक देखने के लिए, फ़ाइल का बाइट रेप्रज़ेंटेशन चाहिए, तो आपको दस्तावेज़ों की सेवा देने वाली कंपनी से किसी अन्य एमआईएम टाइप का अनुरोध करना होगा.
उपयोगकर्ता के किसी विकल्प को चुनने के बाद, नतीजों के डेटा में यूआरआई का इस्तेमाल करके यह तय करें कि फ़ाइल वर्चुअल है या नहीं. इसके लिए, नीचे दिए गए कोड स्निपेट का इस्तेमाल करें:
Kotlin
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 }
Java
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 टाइप में बदला जा सकता है. नीचे दिए गए कोड स्निपेट में, यह जांचने का तरीका बताया गया है कि किसी वर्चुअल फ़ाइल को इमेज के तौर पर दिखाया जा सकता है या नहीं. अगर ऐसा किया जा सकता है, तो वर्चुअल फ़ाइल से इनपुट स्ट्रीम कैसे मिलती है:
Kotlin
@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() } }
Java
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 पर उपलब्ध है.