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

פוסטים בבלוג