גיבוי של נתוני משתמשים באמצעות גיבוי אוטומטי

הגיבוי האוטומטי של אפליקציות מגבה באופן אוטומטי את נתוני המשתמשים מאפליקציות שמטרגטות את Android 6.0 (רמת API‏ 23) ומעלה ופועלות במערכת ההפעלה הזו. מערכת Android שומרת את נתוני האפליקציה על ידי העלאה שלהם ל-Google Drive של המשתמש, שם הם מוגנים באמצעות פרטי הכניסה לחשבון Google של המשתמש. הגיבוי מוצפן מקצה לקצה במכשירים עם Android מגרסה 9 ואילך, באמצעות קוד האימות, קו ביטול הנעילה או הסיסמה של המכשיר. כל אפליקציה יכולה להקצות עד 25MB של נתוני גיבוי לכל משתמש באפליקציה. אין חיוב על אחסון נתוני הגיבוי. אתם יכולים להתאים אישית את תהליך הגיבוי באפליקציה או להשבית את הגיבויים.

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

קבצים שמגובים

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

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

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

מיקום הגיבוי

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

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

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

  • אם למשתמש יש שני מכשירים, יש קבוצת נתוני גיבוי לכל מכשיר.

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

לוח זמנים לגיבוי

הגיבויים מתבצעים באופן אוטומטי כשכל התנאים הבאים מתקיימים:

  • המשתמש הפעיל את הגיבוי במכשיר. ב-Android 9, ההגדרה הזו נמצאת בהגדרות > מערכת > גיבוי.
  • עברו לפחות 24 שעות מאז הגיבוי האחרון.
  • המכשיר לא פעיל.
  • המכשיר מחובר לרשת Wi-Fi (אם המשתמש במכשיר לא בחר לגבות באמצעות חבילת הגלישה).

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

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

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

שחזור לוח הזמנים

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

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

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

הפעלה והשבתה של הגיבוי

אפליקציות שמטרגטות ל-Android 6.0 (רמת API ‏23) ואילך משתתפות באופן אוטומטי בגיבוי האוטומטי. בקובץ המניפסט של האפליקציה, מגדירים את הערך הבוליאני android:allowBackup כדי להפעיל או להשבית את הגיבוי. ערך ברירת המחדל הוא true, אבל מומלץ להגדיר את המאפיין במפורש במניפסט, כמו בדוגמה הבאה:

<manifest ... >
    ...
    <application android:allowBackup="true" ... >
        ...
    </application>
</manifest>

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

הכללה והחרגה של קבצים

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

אתם יכולים לקבוע אילו נתונים ייכללו בגיבוי בהתאם לסוג ההעברה. הגיבוי האוטומטי תומך בגיבויים בענן ב-Google Drive ובהעברות ישירות ממכשיר למכשיר (D2D). שיטות ההגדרה משתנות בהתאם לגרסת Android ול-targetSdkVersion של האפליקציה.

שליטה בגיבוי ב-Android מגרסה 11 ומטה

כדי לקבוע אילו קבצים יגובו במכשירים עם Android בגרסה 11 (רמת API‏ 30) ומטה, פועלים לפי השלבים בקטע הזה.

  1. בקובץ AndroidManifest.xml, מוסיפים את המאפיין android:fullBackupContent לרכיב <application>, כמו בדוגמה הבאה. המאפיין הזה מצביע על קובץ XML שמכיל כללי גיבוי.

    <application ...
        android:fullBackupContent="@xml/backup_rules">
    </application>
    
  2. יוצרים קובץ XML בשם @xml/backup_rules בספרייה res/xml/. בקובץ הזה, מוסיפים כללים עם האלמנטים <include> ו-<exclude>. הדוגמה הבאה מגבה את כל ההעדפות המשותפות חוץ מ-device.xml:

    <?xml version="1.0" encoding="utf-8"?>
    <full-backup-content>
      <include domain="sharedpref" path="."/>
      <exclude domain="sharedpref" path="device.xml"/>
    </full-backup-content>
    

הגדרת התנאים במכשיר שנדרשים לגיבוי

אם האפליקציה שומרת מידע רגיש במכשיר, אתם יכולים לציין תנאים שבהם נתוני האפליקציה ייכללו בגיבוי של המשתמש. ב-Android מגרסה 9 (רמת API‏ 28) ואילך, אפשר להוסיף את התנאים הבאים:

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

כדי להצהיר על תנאי ההכללה, מגדירים את המאפיין requireFlags לערך או לערכים שנבחרו ברכיבי <include> בקבוצת כללי הגיבוי:

backup_rules.xml

<?xml version="1.0" encoding="utf-8"?>
<full-backup-content>
    <!-- App data isn't included in user's backup
         unless client-side encryption is enabled. -->
    <include domain="file" path="."
             requireFlags="clientSideEncryption" />
</full-backup-content>

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

בקטע הקוד הבא יש דוגמה לשימוש בשיטה הזו:

Kotlin

class CustomBackupAgent : BackupAgent() {
    override fun onBackup(
        oldState: ParcelFileDescriptor?,
        data: BackupDataOutput?,
        newState: ParcelFileDescriptor?
    ) {
        if (data != null) {
            if ((data.transportFlags and
                    FLAG_CLIENT_SIDE_ENCRYPTION_ENABLED) != 0) {
                // Client-side backup encryption is enabled.
            }

            if ((data.transportFlags and FLAG_DEVICE_TO_DEVICE_TRANSFER) != 0) {
                // Local device-to-device transfer is enabled.
            }
        }
    }

    // Implementation of onRestore() here.
}

Java

public class CustomBackupAgent extends BackupAgent {
    @Override
    public void onBackup(
        ParcelFileDescriptor oldState,
        BackupDataOutput data,
        ParcelFileDescriptor newState
    ) throws IOException {
        if ((data.getTransportFlags() &
                FLAG_CLIENT_SIDE_ENCRYPTION_ENABLED) != 0) {
            // Client-side backup encryption is enabled.
        }

        if ((data.getTransportFlags() &
                FLAG_DEVICE_TO_DEVICE_TRANSFER) != 0) {
            // Local device-to-device transfer is enabled.
        }
    }

    // Implementation of onRestore() here.
}

שליטה בגיבוי ב-Android מגרסה 12 ואילך

אם האפליקציה מטרגטת את Android 12 (רמת API‏ 31) ומעלה, צריך לפעול לפי השלבים בקטע הזה כדי לקבוע אילו קבצים יגובו במכשירים עם Android 12 ומעלה.

  1. בקובץ AndroidManifest.xml, מוסיפים את המאפיין android:dataExtractionRules לרכיב <application>, כמו בדוגמה הבאה. המאפיין הזה מפנה לקובץ XML שמכיל כללי גיבוי.

    <application ...
        android:dataExtractionRules="backup_rules.xml">
    </application>
    
  2. יוצרים קובץ XML בשם backup_rules.xml בספרייה res/xml/. בקובץ הזה, מוסיפים כללים עם האלמנטים <include> ו-<exclude>. הדוגמה הבאה מגבה את כל ההעדפות המשותפות חוץ מ-device.xml:

    <?xml version="1.0" encoding="utf-8"?>
    <data-extraction-rules>
      <cloud-backup [disableIfNoEncryptionCapabilities="true|false"]>
        <include domain="sharedpref" path="."/>
        <exclude domain="sharedpref" path="device.xml"/>
      </cloud-backup>
    </data-extraction-rules>
    

תחביר של הגדרות XML

תחביר ה-XML של קובץ התצורה משתנה בהתאם לגרסת Android שהאפליקציה מטרגטת ופועלת בה.

‫Android מגרסה 11 ומטה

משתמשים בתחביר ה-XML הבא לקובץ התצורה ששולט בגיבוי למכשירים עם Android בגרסה 11 ומטה.

<full-backup-content>
    <include domain=["file" | "database" | "sharedpref" | "external" |
                     "root" | "device_file" | "device_database" |
                     "device_sharedpref" | "device_root" ] path="string"
    requireFlags=["clientSideEncryption" | "deviceToDeviceTransfer"] />
    <exclude domain=["file" | "database" | "sharedpref" | "external" |
                     "root" | "device_file" | "device_database" |
                     "device_sharedpref" | "device_root" ] path="string" />
</full-backup-content>

‫Android מגרסה 12 ואילך

אם האפליקציה מטרגטת את Android 12 (רמת API‏ 31) ומעלה, צריך להשתמש בתחביר ה-XML הבא בקובץ התצורה ששולט בגיבוי במכשירים עם Android 12 ומעלה.

<data-extraction-rules>
  <cloud-backup [disableIfNoEncryptionCapabilities="true|false"]>
    ...
    <include domain=["file" | "database" | "sharedpref" | "external" |
                     "root" | "device_file" | "device_database" |
                     "device_sharedpref" | "device_root" ] path="string"/>
    ...
    <exclude domain=["file" | "database" | "sharedpref" | "external" |
                     "root" | "device_file" | "device_database" |
                     "device_sharedpref" | "device_root" ] path="string"/>
    ...
  </cloud-backup>
  <device-transfer>
    ...
    <include domain=["file" | "database" | "sharedpref" | "external" |
                     "root" | "device_file" | "device_database" |
                     "device_sharedpref" | "device_root" ] path="string"/>
    ...
    <exclude domain=["file" | "database" | "sharedpref" | "external" |
                     "root" | "device_file" | "device_database" |
                     "device_sharedpref" | "device_root" ] path="string"/>
    ...
  </device-transfer>
  <cross-platform-transfer platform="ios">
    ...
    <include domain=["file" | "database" | "sharedpref" | "external" |
                     "root" | "device_file" | "device_database" |
                     "device_sharedpref" | "device_root" ] path="string"/>
    ...
    <exclude domain=["file" | "database" | "sharedpref" | "external" |
                     "root" | "device_file" | "device_database" |
                     "device_sharedpref" | "device_root" ] path="string"/>
    ...
    <platform-specific-params bundleId="string" teamId="string" contentVersion="string"/>
    ...
  </cross-platform-transfer>
</data-extraction-rules>

כל קטע בהגדרות (<cloud-backup>, <device-transfer>, <cross-platform-transfer>) מכיל כללים שחלים רק על סוג ההעברה הזה. ההפרדה הזו מאפשרת, לדוגמה, להחריג קובץ או ספרייה מגיבויים ב-Google Drive, אבל עדיין להעביר אותם במהלך העברות ממכשיר למכשיר (D2D) או העברות בפלטפורמות שונות. זה שימושי אם יש לכם קבצים שגדולים מדי לגיבוי בענן, אבל אפשר להעביר אותם בין מכשירים בלי בעיה.

אם אין כללים למצב גיבוי מסוים, למשל אם הקטע <device-transfer> חסר, המצב הזה מופעל באופן מלא לכל התוכן, חוץ מהספריות no-backup ו-cache, כפי שמתואר בקטע קבצים שמגובים.

האפליקציה יכולה להגדיר את הדגל disableIfNoEncryptionCapabilities בקטע <cloud-backup> כדי לוודא שהגיבוי יתבצע רק אם אפשר להצפין אותו, למשל כשלמשתמש יש מסך נעילה. הגדרת האילוץ הזה מונעת שליחת גיבויים לענן אם המכשיר של המשתמש לא תומך בהצפנה, אבל מכיוון שהעברות D2D לא נשלחות לשרת, הן ממשיכות לפעול גם במכשירים שלא תומכים בהצפנה.

תחביר לרכיבי הכללה והחרגה

בתוך התגים <full-backup-content>,‏ <cloud-backup> ו-<device-transfer> (בהתאם לגרסת Android של המכשיר ול-targetSDKVersion של האפליקציה), אפשר להגדיר את הרכיבים <include> ו-<exclude>:

<include>

מציינת קובץ או תיקייה לגיבוי. כברירת מחדל, הגיבוי האוטומטי כולל כמעט את כל קובצי האפליקציות. אם מציינים רכיב <include>, המערכת לא כוללת יותר קבצים כברירת מחדל ומגבה רק את הקבצים שצוינו. כדי לכלול כמה קבצים, צריך להשתמש בכמה רכיבי <include>.

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

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

<exclude>

מציינת קובץ או תיקייה שיוחרגו במהלך הגיבוי. הנה כמה קבצים שבדרך כלל לא נכללים בגיבוי:

  • קבצים עם מזהים ספציפיים למכשיר, שהונפקו על ידי שרת או נוצרו במכשיר. לדוגמה, העברת הודעות בענן ב-Firebase ‏(FCM) צריכה ליצור אסימון רישום בכל פעם שמשתמש מתקין את האפליקציה במכשיר חדש. אם משחזרים את אסימון הרישום הישן, יכול להיות שהאפליקציה תתנהג באופן בלתי צפוי.

  • קבצים שקשורים לניפוי באגים באפליקציה.

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

כל רכיב <include> ו-<exclude> חייב לכלול את שני המאפיינים הבאים:

domain

מציין את המיקום של המשאב. אפשר להזין במאפיין הזה את הערכים הבאים:

  • ‫root: הספרייה במערכת הקבצים שבה מאוחסנים כל הקבצים הפרטיים ששייכים לאפליקציה הזו.
  • ‫file: ספריות שהוחזרו על ידי getFilesDir().
  • ‫database: ספריות שהוחזרו על ידי getDatabasePath(). מסדי נתונים שנוצרו באמצעות SQLiteOpenHelper מאוחסנים כאן.
  • ‫sharedpref: הספרייה שבה מאוחסנים SharedPreferences.
  • ‫external: הספרייה שמוחזרת על ידי getExternalFilesDir().
  • ‫device_root: כמו root אבל לאחסון שמוגן על ידי המכשיר.
  • ‫device_file: כמו file אבל לאחסון שמוגן על ידי המכשיר.
  • ‫device_database: כמו database אבל לאחסון שמוגן על ידי המכשיר.
  • ‫device_sharedpref: כמו sharedpref, אבל לאחסון שמוגן על ידי המכשיר.
path

מציינת קובץ או תיקייה שצריך לכלול בגיבוי או להחריג ממנו. חשוב לזכור:

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

הגדרת העברות בין פלטפורמות שונות

החל מ-Android 16 QPR2 (רמת API‏ 36.1), אתם יכולים להגדיר גיבוי אוטומטי להעברות נתונים ממכשירים שאינם Android ואליהם. כדי לעשות את זה, מוסיפים את הרכיב <cross-platform-transfer> להגדרות של <data-extraction-rules>, כמו שמוצג בתחביר של Android בגרסה 12 ואילך. אתם צריכים לציין את פלטפורמת היעד באמצעות מאפיין החובה platform. הערך הנתמך היחיד הוא ios.

בקטע הזה, אתם יכולים להשתמש ברכיבים הרגילים <include> ו-<exclude>, כמו שמתואר בקטע תחביר לרכיבי הכללה והחרגה, כדי לציין אילו נתונים להעביר.

בנוסף, צריך לכלול את הרכיב <platform-specific-params> כדי לעזור למערכת להתאים את האפליקציה לאפליקציה המקבילה בפלטפורמת היעד. המאפיינים הבאים נדרשים ברכיב הזה:

  • ‫bundleId: מזהה החבילה של האפליקציה בפלטפורמה האחרת (למשל, מזהה החבילה של האפליקציה ל-iOS).
  • ‫teamId: מזהה הצוות של האפליקציה בפלטפורמה האחרת (למשל, מזהה הצוות של האפליקציה ל-iOS).
  • ‫contentVersion: מחרוזת גרסה שאתם מגדירים, שמשויכת לפורמט הנתונים שמיוצא.

המאפיינים bundleId ו-teamId משמשים לאימות תקינות הנתונים ולהתאמה תקינה בין אפליקציות. הם מבטיחים שהנתונים יועברו רק לאפליקציה שצוינה בפלטפורמה האחרת במהלך הייצוא, ושאפליקציית Android הזו תייבא נתונים רק מהאפליקציה הספציפית הזו במהלך הייבוא.

כדי לקבל שליטה מדויקת יותר על תהליך הטרנספורמציה וההעברה של הנתונים, מעבר למה שכללי ה-XML מספקים, אתם יכולים להטמיע BackupAgent בהתאמה אישית ולהשתמש בממשקי ה-API להעברה בפלטפורמות שונות.

מיפוי קבצים להעברות מ-iOS

כשמעבירים קבצים ל-iOS, הערכים של domain ו-path ב-Android שציינתם בכללי <include> ממופים למבנה ספציפי של ספרייה. בטבלה הבאה מוצגים נתיבי היעד ב-iOS ביחס לשורש של יעד ההעברה, על סמך domain ב-Android:

Android domain הנתיב ב-iOS (יחסית לשורש ההעברה)
root app/
file app/files/
database app/databases/
sharedpref app/shared_prefs/
external external/files/
device_root device/app/
device_file device/app/files/
device_database device/app/databases/
device_sharedpref device/app/shared_prefs/

לדוגמה, קובץ שנכלל ב-<include domain="file" path="my_settings.txt"/> יהיה זמין בצד של iOS ב-app/files/my_settings.txt ביחס לשורש של יעד ההעברה.

הטמעה של BackupAgent

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

  • אתם רוצים לקבל התראות על אירועי גיבוי, כמו onRestoreFinished() ו-onQuotaExceeded(). שיטות הקריאה החוזרת האלה מופעלות גם אם האפליקציה לא פועלת.

  • קשה להגדיר את קבוצת הקבצים שרוצים לגבות באמצעות כללי XML. במקרים הנדירים האלה, אפשר להטמיע BackupAgent שמחליף את onFullBackup(FullBackupDataOutput) כדי לאחסן את מה שרוצים. כדי לשמור על הטמעת ברירת המחדל של המערכת, צריך להפעיל את השיטה המתאימה במחלקה הראשית באמצעות super.onFullBackup().

אם מטמיעים BackupAgent, המערכת מצפה כברירת מחדל שהאפליקציה תבצע גיבוי ושחזור של מפתח/ערך. כדי להשתמש בגיבוי אוטומטי מבוסס-קובץ, צריך להגדיר את המאפיין android:fullBackupOnly לערך true במניפסט של האפליקציה.

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

ה-BackupAgent צריך להטמיע את ה-methods המופשטים onBackup() ו-onRestore(), שמשמשים לגיבוי של מפתח/ערך. אם אתם לא רוצים לבצע גיבוי של מפתח/ערך, אתם יכולים להשאיר את ההטמעה של השיטות האלה ריקה.

מידע נוסף זמין במאמר הרחבת BackupAgent.

טיפול בהעברות בפלטפורמות שונות ב-BackupAgent

החל מגרסת Android 16 QPR2 (רמת API‏ 36.1), יש כמה ממשקי API חדשים ב-BackupAgent שתומכים טוב יותר בהעברת נתונים בפלטפורמות שונות.

דגל חדש של Transport:

  • ‫FLAG_CROSS_PLATFORM_TRANSFER_IOS: הדגל הזה נוסף ל-transportFlags שסופק ל-BackupAgent.
    • ב-onFullBackup, הדגל הזה מוגדר אם פעולת הגיבוי הנוכחית היא חלק מייצוא נתונים למכשיר iOS.
    • ב-overload החדש של onRestoreFile, הדגל הזה מוגדר אם הנתונים מיובאים ממכשיר iOS.

שיטת onRestoreFile חדשה:

נוספה עומס יתר חדש של onRestoreFile, שמקבל פרמטר FullRestoreDataInput יחיד. האובייקט הזה מספק הקשר נוסף לגבי פעולת השחזור:

  • ‫FullRestoreDataInput.getTransportFlags(): מחזירה את דגלי ההעברה של פעולת השחזור הנוכחית, שיכולים לכלול את FLAG_CROSS_PLATFORM_TRANSFER_IOS.
  • FullRestoreDataInput.getContentVersion(): מחזירה את מחרוזת גרסת התוכן שסופקה על ידי אפליקציית המקור בפלטפורמה האחרת במהלך העברה בפלטפורמות שונות. הערך הזה הוא מחרוזת ריקה אם הוא לא סופק על ידי המקור.

שיטה חדשה להערכת גודל:

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

דוגמה לשימוש:

Kotlin

// In your custom BackupAgent class

override fun onFullBackup(out: FullBackupDataOutput) {
    // Check if this is a cross-platform export to iOS
    if ((out.transportFlags and FLAG_CROSS_PLATFORM_TRANSFER_IOS) != 0) {
        Log.d(TAG, "onFullBackup for iOS transfer")
        // Your custom export logic here
        // Call fullBackupFile() for files to include
    }
}

override fun onRestoreFile(input: FullRestoreDataInput) {
    if ((input.transportFlags and FLAG_CROSS_PLATFORM_TRANSFER_IOS) != 0) {
        val sourceContentVersion = input.contentVersion
        Log.d(TAG, "onRestoreFile from iOS, content version: $sourceContentVersion")
        // Your custom import logic here, using input.data, input.destination, etc.
    }
}

// Optional: Provide an estimate of the backup size
override fun onEstimateFullBackupBytes(): Long {
    return calculateEstimatedBackupSize()
}

Java

// In your custom BackupAgent class

@Override
public void onFullBackup(FullBackupDataOutput out) throws IOException {
    // Check if this is a cross-platform export to iOS
    if ((out.getTransportFlags() & FLAG_CROSS_PLATFORM_TRANSFER_IOS) != 0) {
        Log.d(TAG, "onFullBackup for iOS transfer");
        // Your custom export logic here
        // Call fullBackupFile() for files to include
    }
}

@Override
public void onRestoreFile(FullRestoreDataInput input) {
    if ((input.getTransportFlags() & FLAG_CROSS_PLATFORM_TRANSFER_IOS) != 0) {
        String sourceContentVersion = input.getContentVersion();
        Log.d(TAG, "onRestoreFile from iOS, content version: " + sourceContentVersion);
        // Your custom import logic here, using input.getData(), input.getDestination(), etc.
    }
}

// Optional: Provide an estimate of the backup size
@Override
public long onEstimateFullBackupBytes() {
    return calculateEstimatedBackupSize();
}