حالات استخدام مساحة التخزين على Android وأفضل الممارسات المتعلِّقة بها

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

للتعرّف على مزيد من المعلومات حول طريقة تخزين الملفات والوصول إليها على Android، يمكنك الاطّلاع على أدلة التدريب على مساحة التخزين.

التعامل مع ملفات الوسائط

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

حالة الاستخدام الملخّص
عرض كل ملفات الصور أو الفيديو استخدم النهج نفسه مع جميع إصدارات Android.
عرض صور أو فيديوهات من مجلد معيّن استخدم النهج نفسه مع جميع إصدارات Android.
الوصول إلى معلومات الموقع الجغرافي من الصور استخدِم طريقة واحدة إذا كان تطبيقك يستخدم مساحة تخزين محدَّدة النطاق. ويمكنك اتّباع نهج مختلف إذا أوقف تطبيقك مساحة التخزين المخصّصة له.
تحديد مكان تخزين المحتوى الذي تنزّله جديدة استخدِم طريقة واحدة إذا كان تطبيقك يستخدم مساحة تخزين محدَّدة النطاق. ويمكنك اتّباع نهج مختلف إذا أوقف تطبيقك مساحة التخزين المخصّصة له.
تصدير ملفات وسائط المستخدم إلى جهاز استخدم النهج نفسه مع جميع إصدارات Android.
تعديل ملفات وسائط متعددة أو حذفها في عملية واحدة استخدِم طريقة واحدة لنظام التشغيل Android 11. بالنسبة إلى نظام التشغيل Android 10، يمكنك إيقاف مساحة التخزين ذات النطاق واستخدام أسلوب Android 9 والإصدارات الأقدم بدلاً من ذلك.
استيراد صورة واحدة متوفّرة حاليًا استخدم النهج نفسه مع جميع إصدارات Android.
التقاط صورة واحدة استخدم النهج نفسه مع جميع إصدارات Android.
مشاركة ملفات الوسائط مع تطبيقات أخرى استخدم النهج نفسه مع جميع إصدارات Android.
مشاركة ملفات الوسائط مع تطبيق محدّد استخدم النهج نفسه مع جميع إصدارات Android.
الوصول إلى الملفات من الرموز البرمجية أو المكتبات التي تستخدم المسارات المباشرة للملفات استخدِم طريقة واحدة لنظام التشغيل Android 11. بالنسبة إلى نظام التشغيل Android 10، يمكنك إيقاف مساحة التخزين ذات النطاق واستخدام أسلوب Android 9 والإصدارات الأقدم بدلاً من ذلك.

عرض ملفات صور أو فيديو من مجلدات متعددة

يمكنك الاستعلام عن مجموعة وسائط باستخدام واجهة برمجة تطبيقات query(). لفلترة ملفات الوسائط أو ترتيبها، عليك ضبط المَعلمات projection وselection وselectionArgs وsortOrder.

عرض صور أو فيديوهات من مجلد معيّن

استخدم هذا النهج:

  1. باتّباع أفضل الممارسات الموضّحة في قسم طلب أذونات التطبيق، يمكنك طلب إذن READ_EXTERNAL_STORAGE.
  2. يمكنك استرداد ملفات الوسائط استنادًا إلى قيمة MediaColumns.DATA، التي تحتوي على مسار نظام الملفات المطلق لعنصر الوسائط على القرص.

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

لإنشاء ملف وسائط أو تعديله، لا تستخدِم العمود DATA. بدلاً من ذلك، استخدِم العمودَين DISPLAY_NAME وRELATIVE_PATH.

الوصول إلى معلومات الموقع الجغرافي من الصور

إذا كان تطبيقك يستخدم مساحة تخزين واسعة النطاق، يُرجى اتّباع الخطوات الواردة في قسم معلومات الموقع الجغرافي في الصور الفوتوغرافية من دليل تخزين الوسائط.

تحديد مكان التخزين لعمليات التنزيل الجديدة

إذا كان تطبيقك يستخدم مساحة تخزين محدَّدة النطاق، انتبه إلى المكان الذي تختار فيه تخزين ملفات الوسائط التي تنزِّلها.

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

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

تصدير ملفات وسائط المستخدم إلى جهاز

حدِّد موقعًا تلقائيًا مناسبًا لتخزين ملفات وسائط المستخدم:

تعديل ملفات وسائط متعددة أو حذفها في عملية واحدة

تضمين منطق يستند إلى إصدارات Android التي يعمل عليها تطبيقك.

يعمل على نظام التشغيل Android 11

استخدم هذا النهج:

  1. أنشِئ طلبًا في انتظار المراجعة لطلب كتابة أو حذف لتطبيقك باستخدام MediaStore.createWriteRequest() أو MediaStore.createTrashRequest() ثم اطلب من المستخدم الإذن بتعديل مجموعة من الملفات من خلال استدعاء تلك النية.
  2. تقييم رد المستخدم:

    • إذا تم منح الإذن، يمكنك متابعة عملية التعديل أو الحذف.
    • إذا لم يتم منح الإذن، وضِّح للمستخدم سبب احتياج الميزة في تطبيقك إلى هذا الإذن.

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

يعمل بنظام التشغيل Android 10

إذا كان تطبيقك يستهدف Android 10 (المستوى 29 من واجهة برمجة التطبيقات)، عليك إيقاف مساحة التخزين ذات النطاق ومواصلة اتّباع أسلوب Android 9 والإصدارات الأقدم لتنفيذ هذه العملية.

يعمل بنظام التشغيل Android 9 أو الإصدارات الأقدم

استخدم هذا النهج:

  1. باتّباع أفضل الممارسات الموضّحة في قسم طلب أذونات التطبيق، يمكنك طلب إذن WRITE_EXTERNAL_STORAGE.
  2. يمكنك استخدام MediaStore API لتعديل ملفات الوسائط أو حذفها.

استيراد صورة واحدة موجودة من قبل

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

قدِّم واجهة المستخدم الخاصة بك.

استخدم هذا النهج:

  1. باتّباع أفضل الممارسات الموضّحة في قسم طلب أذونات التطبيق، يمكنك طلب إذن READ_EXTERNAL_STORAGE.
  2. يمكنك استخدام واجهة برمجة تطبيقات query() للبحث عن مجموعة وسائط.
  3. يمكنك عرض النتائج في واجهة المستخدم المخصّصة لتطبيقك.

استخدام أداة اختيار النظام

يمكنك استخدام نية ACTION_GET_CONTENT التي تطلب من المستخدم اختيار صورة لاستيرادها.

إذا كنت تريد فلترة أنواع الصور التي تعرضها أداة اختيار النظام للمستخدِم للاختيار من بينها، يمكنك استخدام setType() أو EXTRA_MIME_TYPES.

التقاط صورة واحدة

عندما تريد التقاط صورة واحدة لاستخدامها في تطبيقك (على سبيل المثال، لاستخدامها كصورة لملف شخصي للمستخدم)، اطلب من المستخدم التقاط صورة باستخدام كاميرا الجهاز ACTION_IMAGE_CAPTURE. يخزِّن النظام الصورة التي تم التقاطها في جدول MediaStore.Images.

مشاركة ملفات الوسائط مع التطبيقات الأخرى

استخدِم الطريقة insert() لإضافة السجلات مباشرةً إلى MediaStore. لمزيد من المعلومات، يمكنك الاطّلاع على القسم إضافة عنصر في دليل مساحة تخزين الوسائط.

مشاركة ملفات الوسائط مع تطبيق محدّد

استخدِم مكوِّن FileProvider لنظام التشغيل Android على النحو الموضَّح في دليل إعداد مشاركة الملفات.

الوصول إلى الملفات من الرموز أو المكتبات التي تستخدم مسارات الملفات المباشرة

تضمين منطق يستند إلى إصدارات Android التي يعمل عليها تطبيقك.

يعمل على نظام التشغيل Android 11

استخدم هذا النهج:

  1. باتّباع أفضل الممارسات الموضّحة في قسم طلب أذونات التطبيق، يمكنك طلب إذن READ_EXTERNAL_STORAGE.
  2. الوصول إلى الملفات باستخدام مسارات الملفات المباشرة

للحصول على مزيد من المعلومات، يمكنك الاطّلاع على القسم المتعلق بكيفية فتح ملفات الوسائط باستخدام مسارات الملفات المباشرة.

يعمل بنظام التشغيل Android 10

إذا كان تطبيقك يستهدف Android 10 (المستوى 29 من واجهة برمجة التطبيقات)، عليك إيقاف مساحة التخزين ذات النطاق ومواصلة اتّباع أسلوب Android 9 والإصدارات الأقدم لتنفيذ هذه العملية.

يعمل بنظام التشغيل Android 9 أو الإصدارات الأقدم

استخدم هذا النهج:

  1. باتّباع أفضل الممارسات الموضّحة في قسم طلب أذونات التطبيق، يمكنك طلب إذن WRITE_EXTERNAL_STORAGE.
  2. الوصول إلى الملفات باستخدام مسارات الملفات المباشرة

التعامل مع ملفات غير الوسائط

يصف هذا القسم بعض حالات الاستخدام الشائعة للتعامل مع ملفات غير وسائط، ويشرح الأسلوب العالي المستوى الذي يمكن أن يستخدمه تطبيقك. يلخص الجدول التالي كل حالة من حالات الاستخدام هذه، ويربط بكل قسم من الأقسام التي تحتوي على مزيد من التفاصيل.

حالة الاستخدام الملخّص
فتح ملف مستند استخدم النهج نفسه مع جميع إصدارات Android.
الكتابة في الملفات ذات أحجام التخزين الثانوية استخدِم طريقة واحدة لنظام التشغيل Android 11. يُرجى استخدام أسلوب مختلف مع الإصدارات السابقة من Android.
نقل الملفات الحالية من موقع تخزين قديم انقل ملفاتك إلى مساحة تخزين محدَّدة النطاق إن أمكن. يمكنك إيقاف ميزة "التخزين الفرعي" في Android 10 عند الضرورة.
مشاركة المحتوى مع التطبيقات الأخرى استخدم النهج نفسه مع جميع إصدارات Android.
تخزين ملفات غير الوسائط في ذاكرة التخزين المؤقت استخدم النهج نفسه مع جميع إصدارات Android.
تصدير ملفات غير الوسائط إلى جهاز استخدِم طريقة واحدة إذا كان تطبيقك يستخدم مساحة تخزين محدَّدة النطاق. ويمكنك اتّباع نهج مختلف إذا أوقف تطبيقك مساحة التخزين المخصّصة له.

فتح ملف مستند

استخدِم نية ACTION_OPEN_DOCUMENT لتطلب من المستخدم اختيار ملف لفتحه باستخدام أداة اختيار النظام. إذا كنت تريد فلترة أنواع الملفات التي ستعرضها أداة اختيار النظام على المستخدم للاختيار من بينها، يمكنك استخدام setType() أو EXTRA_MIME_TYPES.

على سبيل المثال، يمكنك العثور على جميع ملفات PDF وODT وTXT باستخدام الرمز التالي:

Kotlin

startActivityForResult(
        Intent(Intent.ACTION_OPEN_DOCUMENT).apply {
            addCategory(Intent.CATEGORY_OPENABLE)
            type = "*/*"
            putExtra(Intent.EXTRA_MIME_TYPES, arrayOf(
                    "application/pdf", // .pdf
                    "application/vnd.oasis.opendocument.text", // .odt
                    "text/plain" // .txt
            ))
        },
        REQUEST_CODE
      )

Java

Intent intent = new Intent(Intent.ACTION_OPEN_DOCUMENT);
        intent.addCategory(Intent.CATEGORY_OPENABLE);
        intent.setType("*/*");
        intent.putExtra(Intent.EXTRA_MIME_TYPES, new String[] {
                "application/pdf", // .pdf
                "application/vnd.oasis.opendocument.text", // .odt
                "text/plain" // .txt
        });
        startActivityForResult(intent, REQUEST_CODE);

الكتابة في الملفات على وحدات تخزين ثانوية

تشتمل مساحات التخزين الثانوية على بطاقات SD. يمكنك الاطّلاع على معلومات حول حجم مساحة تخزين معيّنة باستخدام الفئة StorageVolume.

تضمين منطق استنادًا إلى إصدار Android الذي يعمل عليه تطبيقك.

يعمل بنظام التشغيل Android 11

استخدم هذا النهج:

  1. استخدِم نموذج مساحة التخزين ضمن النطاق.
  2. استهداف الإصدار 10 من نظام التشغيل Android (المستوى 29 من واجهة برمجة التطبيقات) أو الإصدارات الأقدم
  3. يرجى تقديم بيان لإذن WRITE_EXTERNAL_STORAGE.
  4. أجرِ أحد أنواع الوصول التالية:
    • الوصول إلى الملفات باستخدام واجهة برمجة تطبيقات MediaStore
    • الوصول مباشرةً إلى مسارات الملفات باستخدام واجهات برمجة التطبيقات، مثل File أو fopen()

تعمل على إصدارات قديمة

استخدِم إطار عمل الوصول إلى مساحة التخزين، الذي يسمح للمستخدمين بتحديد مكان الملف في وحدة تخزين ثانوية يمكن لتطبيقك كتابة الملف فيه.

نقل الملفات الحالية من موقع تخزين قديم

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

الاحتفاظ بإمكانية الوصول إلى موقع التخزين القديم لنقل البيانات

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

إذا كان تطبيقك يستهدف نظام التشغيل Android 11
  1. يمكنك ضبط العلامة preserveLegacyExternalStorage على true من أجل الاحتفاظ بنموذج التخزين القديم لكي يتمكّن تطبيقك من نقل بيانات المستخدمين عند الترقية إلى الإصدار الجديد من تطبيقك الذي يستهدف الإصدار 11 من نظام التشغيل Android.

  2. يمكنك مواصلة إيقاف مساحة التخزين المخصّصة للنطاق كي يواصل تطبيقك الوصول إلى ملفاتك في موقع التخزين القديم على أجهزة Android 10.

إذا كان تطبيقك يستهدف نظام التشغيل Android 10

أوقِف ميزة "التخزين الفرعي" لتسهيل الحفاظ على سلوك تطبيقك في جميع إصدارات Android.

نقل بيانات التطبيق

عندما يكون تطبيقك جاهزًا لنقل البيانات، اتّبِع النهج التالي:

  1. استهداف الإصدار 10 من نظام التشغيل Android أو الإصدارات الأقدم
  2. أوقِف ميزة "التخزين الفرعي" حتى يتمكّن تطبيقك من الوصول إلى الملفات التي تحتاج إلى نقلها.
  3. نشر رمز يستخدم File API لنقل الملفات من مكانها الحالي ضمن /sdcard/ إلى موقع يمكن الوصول إليه من خلال مساحة تخزين محدَّدة النطاق:

    1. انقل أي ملفات تطبيقات خاصة إلى الدليل الذي تعرضه طريقة getExternalFilesDir().
    2. يمكنك نقل أي ملفات غير وسائط تمت مشاركتها إلى دليل فرعي خاص بالتطبيقات في دليل Downloads/.
  4. أزِل أدلة مساحة التخزين القديمة لتطبيقك من دليل /sdcard/.

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

بعد نقل المستخدمين لبياناتهم، انشر تحديثًا آخر على تطبيقك، حيث تستهدف Android 11.

مشاركة المحتوى مع التطبيقات الأخرى

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

ذاكرة التخزين المؤقت لملفات غير الوسائط

تعتمد الطريقة التي يجب عليك استخدامها على نوع الملفات التي تحتاج إلى تخزينها مؤقتًا.

  • الملفات الصغيرة أو الملفات التي تحتوي على معلومات حسّاسة: استخدِم Context#getCacheDir().
  • الملفات أو الملفات الكبيرة التي لا تحتوي على معلومات حسّاسة: استخدِم Context#getExternalCacheDir().

تصدير ملفات غير الوسائط إلى جهاز

حدِّد موقعًا تلقائيًا مناسبًا لتخزين الملفات التي ليست ضِمن ملفات الوسائط. يمكنك السماح للمستخدمين بتصدير الملفات من الأدلّة الخاصة بالتطبيقات إلى مكان يمكن الوصول إليه بشكلٍ عام. استخدِم عمليات التنزيل أو مجموعات المستندات في MediaStore لتصدير الملفات غير الوسائط إلى الجهاز.

إيقاف التخزين الفرعي مؤقتًا

قبل أن يصبح تطبيقك متوافقًا بالكامل مع مساحة التخزين ذات النطاق الواسع، يمكنك إيقاف الميزة مؤقتًا، سواء في اختباراتك أو في تطبيق الإنتاج.

الإيقاف في اختباراتك

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

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

-e no-isolated-storage 1

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

إيقاف الميزة في تطبيق الإنتاج

إذا كان تطبيقك يستهدف Android 10 (المستوى 29 من واجهة برمجة التطبيقات) أو الإصدارات الأقدم، يمكنك مؤقتًا إيقاف مساحة التخزين ذات النطاق الواسع في تطبيق الإنتاج. إذا كنت تستهدف Android 10، عليك مع ذلك ضبط القيمة requestLegacyExternalStorage على true في ملف البيان لتطبيقك:

<manifest ... >
  <!-- This attribute is "false" by default on apps targeting
       Android 10. -->
  <application android:requestLegacyExternalStorage="true" ... >
    ...
  </application>
</manifest>

لاختبار سلوك تطبيق يستهدف الإصدار Android 10 أو الإصدارات الأقدم عند استخدام مساحة التخزين ذات النطاق الواسع، يمكنك تفعيل السلوك من خلال ضبط قيمة requestLegacyExternalStorage على false. إذا كنت تختبر الأداء على جهاز يعمل بنظام التشغيل Android 11، يمكنك أيضًا استخدام علامات توافق التطبيق لاختبار سلوك تطبيقك مع مساحة تخزين على النطاق أو بدونها.

مصادر إضافية

للحصول على مزيد من المعلومات عن مساحة التخزين في Android، يمكنك الاطّلاع على المواد التالية:

مشاركات المدونة