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

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

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

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

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

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

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

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

שליחת שאילתה לאוסף מדיה באמצעות query() API. כדי לסנן או למיין את קובצי המדיה, משנים את הפרמטרים projection, selection, selectionArgs ו-sortOrder.

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

כך עושים זאת:

  1. פועלים לפי השיטות המומלצות שמפורטות במאמר בקשת הרשאות לאפליקציה ומבקשים את ההרשאה READ_EXTERNAL_STORAGE.
  2. אחזור קובצי מדיה על סמך הערך של MediaColumns.DATA, שמכיל את הנתיב המוחלט במערכת הקבצים לפריט המדיה בדיסק.

הערה: כשניגשים לקובץ מדיה קיים, אפשר להשתמש בערך של העמודה DATA בלוגיקה שלכם. הסיבה לכך היא שהערך הזה כולל נתיב קובץ תקין. עם זאת, אל תניחו שהקובץ תמיד זמין. צריך להיות מוכנים לטפל בשגיאות קלט/פלט (I/O) שעלולות להתרחש בקבצים.

לעומת זאת, כדי ליצור או לעדכן קובץ מדיה, לא משתמשים בעמודה DATA. במקום זאת, צריך להשתמש בעמודות DISPLAY_NAME ו-RELATIVE_PATH.

גישה לפרטי מיקום מתמונות

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

הגדרת מיקום האחסון להורדות חדשות

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

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

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

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

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

שינוי או מחיקה של כמה קובצי מדיה בפעולה אחת

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

פועל ב-Android 11

כך עושים זאת:

  1. יוצרים intent בהמתנה לבקשת כתיבה או מחיקה של האפליקציה באמצעות MediaStore.createWriteRequest() או MediaStore.createTrashRequest() ואז מבקשים מהמשתמש הרשאה לערוך קבוצת קבצים על ידי הפעלת ה-intent הזה.
  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. משתמשים ב-query() API כדי לשאול שאילתה על אוסף מדיה.
  3. הצגת התוצאות בממשק משתמש מותאם אישית של האפליקציה.

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

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

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

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

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

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

משתמשים בשיטה 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.
ייצוא קבצים שאינם קובצי מדיה למכשיר אם האפליקציה משתמשת בנפח אחסון ייעודי לאפליקציות, צריך להשתמש באחת מהגישות האלה. אם האפליקציה לא משתמשת בנפח אחסון ייעודי לאפליקציות, צריך להשתמש בגישה אחרת.

פתיחת קובץ מסמך

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

ביטול ההצטרפות לבדיקות

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

אם בדיקה יוצרת קבצים עבור המארח – כמו צילומי מסך, נתוני ניפוי באגים, נתוני כיסוי או מדדי ביצועים – אפשר לכתוב את הקבצים האלה בספריות גלובליות. כדי לעשות זאת, מוסיפים את הדגל הבא לרתמה הרלוונטית שמפעילה את 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 זמין במקורות המידע הבאים:

פוסטים בבלוג