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

לעומת זאת, כדי ליצור או לעדכן קובץ מדיה, אין להשתמש בעמודה 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 זמין במאמרים הבאים:

פוסטים בבלוג