תרחישים לדוגמה ושיטות מומלצות בנוגע לאחסון ב-Android

כדי לתת למשתמשים יותר שליטה על הקבצים שלהם ולהפחית את העומס של הקבצים, הוספנו ל-Android 10 מודל אחסון חדש לאפליקציות שנקרא אחסון מוגבל. השימוש בנפח האחסון משנה את האופן שבו אפליקציות מאחסנים קבצים באחסון החיצוני של המכשיר וניגשים אליהם. כדי לעזור לכם להעביר את האפליקציה לתמיכה באחסון מוגבל, כדאי לפעול לפי השיטות המומלצות לתרחישים נפוצים של אחסון שמפורטות במדריך הזה. תרחישי השימוש מחולקים לשתי קטגוריות: טיפול בקבצי מדיה וטיפול בקבצים שאינם מדיה.

במקרים רבים, האפליקציה יוצרת קבצים שאפליקציות אחרות לא צריכות גישה אליהם, או שאין להן גישה אליהם. המערכת מספקת מיקומי אחסון ספציפיים לאפליקציות לניהול קבצים כאלה.

מידע נוסף על אחסון קבצים ב-Android וגישה אליהם זמין במדריכים בנושא אחסון.

טיפול בקובצי מדיה

בקטע הזה מתוארים כמה תרחישים לדוגמה לטיפול בקבצי מדיה (קבצי וידאו, תמונות ואודיו), ומוסבר על הגישה ברמה גבוהה שבה האפליקציה שלכם יכולה להשתמש. בטבלה הבאה מפורט סיכום של כל אחד מהתרחישים לדוגמה, ויש קישורים לכל אחד מהקטעים שמכילים פרטים נוספים.

תרחיש לדוגמה סיכום
הצגת כל קובצי התמונות או הסרטונים יש להשתמש באותה גישה בכל הגרסאות של Android.
הצגת תמונות או סרטונים מתיקייה מסוימת יש להשתמש באותה גישה בכל הגרסאות של Android.
גישה למידע על המיקום מהתמונות אם האפליקציה שלכם משתמשת בנפח האחסון הייעודי לאפליקציות, צריך להשתמש בגישה אחת. אם האפליקציה שלכם לא תשתמש בנפח האחסון הייעודי לאפליקציות, עליכם להשתמש בגישה אחרת.
הגדרת מיקום האחסון להורדות חדשות צריך להשתמש בגישה אחת אם האפליקציה משתמשת בנפח אחסון בהיקף. אם האפליקציה שלכם לא תשתמש בנפח האחסון הייעודי לאפליקציות, עליכם להשתמש בגישה אחרת.
ייצוא קבצי מדיה של משתמשים למכשיר יש להשתמש באותה גישה בכל הגרסאות של Android.
שינוי או מחיקה של כמה קובצי מדיה בפעולה אחת כדאי להשתמש בגישה אחת ל-Android 11. ב-Android 10, צריך לבטל את ההסכמה לאחסון מוגבל ולהשתמש במקום זאת בגישה שמתאימה ל-Android 9 ומטה.
ייבוא תמונה אחת שכבר קיימת יש להשתמש באותה גישה בכל הגרסאות של Android.
צילום תמונה אחת יש להשתמש באותה גישה בכל הגרסאות של Android.
שיתוף קובצי מדיה עם אפליקציות אחרות יש להשתמש באותה גישה בכל הגרסאות של Android.
שיתוף קובצי מדיה עם אפליקציה ספציפית יש להשתמש באותה גישה בכל הגרסאות של Android.
גישה לקבצים מקובצי קוד או מספריות שמשתמשים בנתיבים ישירים לקבצים כדאי להשתמש בגישה אחת ל-Android 11. ב-Android 10, צריך לבטל את ההסכמה לאחסון מוגבל ולהשתמש במקום זאת בגישה שמתאימה ל-Android 9 ומטה.

הצגת קובצי תמונות או סרטונים מכמה תיקיות

שאילתות על אוסף מדיה באמצעות ה-API של 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 (רמת API ‏29), עליכם לבטל את ההסכמה לאחסון מוגבל ולהמשיך להשתמש בגישה ל-Android 9 וגרסאות קודמות כדי לבצע את הפעולה הזו.

מערכת Android מגרסה 9 ומטה

כדאי להשתמש בגישה הזו:

  1. בהתאם לשיטות המומלצות שמפורטות במאמר בקשה להרשאות לאפליקציה, מבקשים את ההרשאה WRITE_EXTERNAL_STORAGE.
  2. משתמשים ב-API MediaStore כדי לשנות או למחוק את קובצי המדיה.

ייבוא של תמונה אחת שכבר קיימת

כשרוצים לייבא תמונה אחת שכבר קיימת (לדוגמה, כדי להשתמש בה כתמונה בפרופיל של משתמש), האפליקציה יכולה להשתמש בממשק המשתמש שלה לצורך הפעולה, או להשתמש בבורר של המערכת.

הצגת ממשק משתמש משלכם

כדאי להשתמש בגישה הזו:

  1. בהתאם לשיטות המומלצות שמפורטות במאמר בקשה להרשאות לאפליקציה, מבקשים את ההרשאה READ_EXTERNAL_STORAGE.
  2. אתם יכולים להשתמש ב-API query() כדי לבצע שאילתות באוסף מדיה.
  3. להציג את התוצאות בממשק המשתמש המותאם אישית של האפליקציה.

שימוש בכלי לבחירת תיקיות של מערכת ההפעלה

משתמשים בכוונה ACTION_GET_CONTENT, שבה המשתמש מתבקש לבחור תמונה לייבוא.

אם רוצים לסנן את סוגי התמונות שכלי הבחירה של המערכת מציג למשתמש לבחירה, אפשר להשתמש ב-setType() או ב-EXTRA_MIME_TYPES.

צילום תמונה אחת

אם אתם רוצים לצלם תמונה אחת לשימוש באפליקציה (לדוגמה, לשימוש כתמונה בפרופיל של משתמש), תוכלו להשתמש בכוונה ACTION_IMAGE_CAPTURE כדי לבקש מהמשתמש לצלם תמונה באמצעות מצלמת המכשיר. המערכת שומרת את התמונה שצולמה בטבלה MediaStore.Images.

שיתוף קובצי מדיה עם אפליקציות אחרות

משתמשים ב-method‏ insert() כדי להוסיף רשומות ישירות ל-MediaStore. מידע נוסף זמין בקטע הוספת פריט במדריך לאחסון מדיה.

שיתוף קובצי מדיה עם אפליקציה ספציפית

משתמשים ברכיב FileProvider של Android, כפי שמתואר במדריך הגדרת שיתוף קבצים.

גישה לקבצים מקוד או מספריות שמשתמשות בנתיבים ישירים של קבצים

לשלב לוגיקה על סמך גרסאות Android שבהן האפליקציה פועלת.

פועלת ב-Android 11

כדאי להשתמש בגישה הזו:

  1. בהתאם לשיטות המומלצות שמתוארות בקטע בקשת הרשאות לאפליקציה, מבקשים את ההרשאה READ_EXTERNAL_STORAGE.
  2. לגשת לקבצים באמצעות נתיבים ישירים לקבצים.

מידע נוסף זמין בקטע בנושא פתיחת קובצי מדיה באמצעות נתיבי קבצים ישירים.

פועלת ב-Android 10

אם האפליקציה מטרגטת את Android 10 (רמת API 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. משתמשים במודל scoped storage.
  2. טירגוט ל-Android 10 (רמת API 29) ומטה.
  3. מצהירים על ההרשאה WRITE_EXTERNAL_STORAGE.
  4. מבצעים את אחד מסוגי הגישה הבאים:
    • גישה לקובץ באמצעות ה-API של MediaStore.
    • גישה ישירה לנתיב הקובץ באמצעות ממשקי API כמו File או fopen().

הפעלה בגרסאות ישנות יותר

להשתמש ב-Storage Access Framework, שמאפשר למשתמשים לבחור את המיקום בנפח אחסון משני שבו האפליקציה יכולה לכתוב את הקובץ.

העברת קבצים קיימים ממיקום אחסון קודם

ספרייה נחשבת למיקום אחסון מדור קודם אם היא לא ספרייה ספציפית לאפליקציה או ספרייה ציבורית משותפת. אם האפליקציה יוצרת קבצים או משתמשת בהם במיקום אחסון מדור קודם, מומלץ להעביר את הקבצים של האפליקציה למיקומים שאפשר לגשת אליהם באמצעות אחסון מוגבל, ולבצע את השינויים הנדרשים באפליקציה כדי שתעבוד עם קבצים באחסון מוגבל.

שמירה על הגישה למיקום האחסון הקודם לצורך העברת נתונים

לאפליקציה צריכה להיות גישה למיקום האחסון הקודם כדי להעביר את קובצי האפליקציה למיקומים שאפשר לגשת אליהם באמצעות אחסון מוגדר-היקף. הגישה שבה צריך להשתמש תלויה ברמת ה-API לטירגוט של האפליקציה.

אם האפליקציה שלכם מטרגטת ל-Android 11
  1. כדי לשמור על מודל האחסון הקודם, מגדירים את הדגל preserveLegacyExternalStorage לערך true כדי שהאפליקציה תוכל להעביר את הנתונים של המשתמש כשהוא משדרג לגרסה החדשה של האפליקציה שמטרגטת את Android 11.

  2. ממשיכים לבטל את ההסכמה לאחסון מוגבל כדי שהאפליקציה תמשיך לגשת לקבצים במיקום האחסון הקודם במכשירי Android 10.

אם האפליקציה שלכם מטרגטת ל-Android 10

לבטל את ההסכמה לאחסון מוגבל כדי שיהיה קל יותר לשמור על התנהגות האפליקציה בגרסאות השונות של Android.

העברת נתוני האפליקציה

כשהאפליקציה מוכנה להעברה, יש להשתמש בשיטה הבאה:

  1. טירגוט ל-Android מגרסה 10 ומטה.
  2. לבטל את ההסכמה לנפח אחסון בהיקף כדי שלאפליקציה תהיה גישה לקבצים שצריך להעביר.
  3. פורסים קוד שמשתמש ב-API של File כדי להעביר קבצים מהמיקום הנוכחי שלהם ב-/sdcard/ למיקום שאפשר לגשת אליו באמצעות אחסון מוגדר-היקף:

    1. מעבירים את כל קבצי האפליקציה הפרטיים לספרייה שמוחזרת על ידי השיטה getExternalFilesDir().
    2. מעבירים קבצים משותפים שאינם מדיה לתיקיית משנה ייעודית לאפליקציה בספרייה Downloads/.
  4. צריך להסיר את ספריות האחסון הקודמות של האפליקציה מהספרייה /sdcard/.

אחרי שהמשתמשים מתקינים את הגרסה החדשה של האפליקציה, הם משלימים את תהליך העברת הנתונים במכשירים שלהם. אפשר לעקוב אחרי תהליך ההעברה בין בסיס המשתמשים על ידי יצירת אירוע לניתוח נתונים.

אחרי שהמשתמשים יעבירו את הנתונים שלהם, תוכלו לפרסם עדכון נוסף לאפליקציה שבו תגדירו את Android 11 כיעד.

שיתוף תוכן עם אפליקציות אחרות

כדי לשתף את הקבצים של האפליקציה עם אפליקציה אחת אחרת, משתמשים ב-FileProvider. באפליקציות שצריך לשתף ביניהם קבצים, מומלץ להשתמש בספק תוכן לכל אפליקציה, ולאחר מכן לסנכרן את הנתונים כשאפליקציות נוספות מתווספות לאוסף.

שמירת קבצים שאינם קובצי מדיה במטמון

הגישה שצריך להשתמש בה תלויה בסוג הקבצים שרוצים לשמור במטמון.

  • קבצים קטנים או קבצים שמכילים מידע אישי רגיש: משתמשים ב-Context#getCacheDir().
  • קבצים גדולים או קבצים שלא מכילים מידע רגיש: משתמשים ב-Context#getExternalCacheDir().

ייצוא קבצים שאינם מדיה למכשיר

מגדירים מיקום ברירת מחדל מתאים לאחסון קבצים שאינם מדיה. לאפשר למשתמשים לייצא קבצים מספריות ספציפיות לאפליקציה למיקום שגלוי לכולם. אפשר להשתמש בהורדות או בקולקציות מסמכים של MediaStore כדי לייצא למכשיר קבצים שאינם מדיה.

טיפול בקבצים ספציפיים לאפליקציה

אם האפליקציה יוצרת קבצים שאפליקציות אחרות לא צריכות גישה אליהם, או שאין להן גישה אליהם, אפשר לאחסן את הקבצים האלה במיקומי אחסון ספציפיים לאפליקציה.

ספריות אחסון פנימי

המערכת מונעת מאפליקציות אחרות לגשת למיקומים האלה, וב-Android 10 (רמת API 29) ואילך המיקומים האלה מוצפנים. המיקומים האלה הם מקום טוב לאחסון מידע אישי רגיש שרק לאפליקציה שלכם יש גישה אליו.

ספריות אחסון חיצוניות

אם האחסון הפנימי לא מספק מספיק מקום לאחסון קבצים ספציפיים לאפליקציה, כדאי להשתמש במקום זאת באחסון חיצוני. אמנם אפליקציה אחרת יכולה לגשת לספריות האלה אם יש לה את ההרשאות המתאימות, אבל הקבצים שמאוחסנים בספריות האלה מיועדים לשימוש רק באפליקציה שלכם.

ב-Android 4.4 (רמת API 19) ואילך, האפליקציה לא צריכה לבקש הרשאות שקשורות לאחסון כדי לגשת לספריות ספציפיות לאפליקציה באחסון החיצוני.

כשהמשתמש מסיר את האפליקציה, הקבצים שנשמרו באחסון הייעודי לאפליקציה נמחקים. לכן, אל תשתמשו באחסון הזה כדי לשמור משהו שהמשתמש מצפה שיישמר בנפרד מהאפליקציה.

ביטול ההסכמה לשימוש באחסון מוגבל זמנית

לפני שהאפליקציה תעמוד בדרישות לשימוש מלא בנפח אחסון, תוכלו להפסיק את השימוש באופן זמני גם בבדיקות שלכם וגם באפליקציית הייצור.

ביטול ההסכמה בבדיקות

ב-Android 10 (רמת API ‏29) ואילך, הבדיקות של האפליקציה פועלות כברירת מחדל בסביבת חול לאחסון. ארגז החול הזה מונע מהאפליקציה לגשת לקבצים מחוץ לספרייה הספציפית לאפליקציה ולתיקיות ששותפו באופן ציבורי.

אם הבדיקה מניבה קובצי פלט למארח – כמו צילומי מסך, נתוני ניפוי באגים, נתוני כיסוי או מדדי ביצועים – אפשר לכתוב את הקובצים האלה לספריות גלובליות. כדי לעשות זאת, מוסיפים את הדגל הבא לערכת הכלי הרלוונטית שמפעילה את am instrument:

-e no-isolated-storage 1

הדגל הזה משפיע על כל ההתנהגות של תיק הבדיקה המתווסף, ועל כל קוד הבדיקה שהופעל. לכן כשמשתמשים בדגל הזה אי אפשר לאמת את התאימות של האפליקציה לנפח אחסון בהיקף מוגבל. לפלט הבדיקה, עדיף לכתוב לאחסון ברמת האפליקציה שהמעטפת יכולה לקרוא. לאחר מכן תוכלו למשוך את הספרייה ברמת האפליקציה. כדי לקבוע מתוך איזו ספרייה רוצים לשלוף, קוראים ל-getExternalMediaDirs().

ביטול ההסכמה באפליקציה בסביבת הייצור

אם האפליקציה שלכם מטרגטת את Android 10 (רמת API 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 זמין במאמרים הבאים:

פוסטים בבלוגים