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

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

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

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

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

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

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

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

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

משתמשים ברכיב 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. פורסים קוד שמשתמש ב-API של File כדי להעביר קבצים מהמיקום הנוכחי שלהם ב-/sdcard/ למיקום שאפשר לגשת אליו באמצעות נפח אחסון ייעודי לאפליקציות:

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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