Anahtar/değer çiftlerini Android Backup Service ile yedekleme

Android Backup Service, Android uygulamanızdaki anahtar/değer çifti verileri için bulutta yedekleme ve geri yükleme sağlar. Anahtar/değer çifti yedekleme işlemi sırasında, uygulamanın yedek verileri cihazın yedek aktarımına aktarılır. Cihaz, varsayılan Google yedek aktarımını kullanıyorsa veriler arşivleme için Android Yedekleme Hizmeti'ne iletilir.

Veriler, uygulamanızın kullanıcısı başına 5 MB ile sınırlıdır. Yedek verileri depolamak için ücret alınmaz.

Android'in yedekleme seçeneklerine genel bir bakış ve hangi verileri yedekleyip geri yüklemeniz gerektiği konusunda yol gösterici bilgi için Veri yedeklemesine genel bakış bölümüne bakın.

Anahtar/değer çifti yedeği uygulayın

Uygulama verilerinizi yedeklemek için bir yedek aracı uygulamanız gerekir. Yedekleme aracınız, hem yedekleme hem de geri yükleme sırasında Yedekleme Yöneticisi tarafından çağrılır.

Bir yedek aracı uygulamak için yapmanız gerekenler:

  1. Manifest dosyanızda yedek aracınızı android:backupAgent özelliğiyle tanımlayın.

  2. Aşağıdakilerden birini yaparak bir yedek aracı tanımlayın:

    • BackupAgent uzatılıyor

      BackupAgent sınıfı, uygulamanızın Yedekleme Yöneticisi ile iletişim kurmak için kullandığı merkezi arayüzü sunar. Bu sınıfı doğrudan genişletirseniz verilerinizin yedekleme ve geri yükleme işlemlerini işlemek için onBackup() ve onRestore() ayarlarını geçersiz kılmanız gerekir.

    • BackupAgentHelper uzatılıyor

      BackupAgentHelper sınıfı, BackupAgent sınıfı için kullanışlı bir sarmalayıcı sunarak yazmanız gereken kod miktarını en aza indirir. BackupAgentHelper alanınızda bir veya daha fazla yardımcı nesne kullanmanız gerekir. Bu yardımcı nesneler belirli veri türlerini otomatik olarak yedekleyip geri yükler. Böylece onBackup() ve onRestore() öğelerini uygulamanıza gerek kalmaz. Uygulamanızın yedeklemeleri üzerinde tam kontrole ihtiyaç duymadığınız sürece, uygulamanızın yedeklemelerini işlemek için BackupAgentHelper kullanmanızı öneririz.

      Android şu anda SharedPreferences ve dahili depolama alanındaki eksiksiz dosyaları yedekleyip geri yükleyecek yedekleme yardımcıları sunar.

Manifest'inizde yedek aracıyı bildirme

Yedek aracınızın sınıf adına karar verdikten sonra, <application> etiketindeki android:backupAgent özelliğini kullanarak manifest dosyanızda bildirin.

Örneğin:

<manifest ... >
    ...
    <application android:label="MyApplication"
                 android:backupAgent="MyBackupAgent">
        <meta-data android:name="com.google.android.backup.api_key"
            android:value="unused" />
        <activity ... >
            ...
        </activity>
    </application>
</manifest>

Eski cihazları desteklemek için Android manifest dosyanıza <meta-data> API anahtarını eklemenizi öneririz. Android Yedekleme Hizmeti artık bir hizmet anahtarı gerektirmez ancak bazı eski cihazlar yedekleme sırasında hâlâ anahtar olup olmadığını kontrol edebilir. android:name öğesini com.google.android.backup.api_key ve android:value öğesini unused olarak ayarlayın.

android:restoreAnyVersion özelliği, yedekleme verilerini oluşturan sürümle karşılaştırıldığında geçerli uygulama sürümünden bağımsız olarak uygulama verilerini geri yüklemek isteyip istemediğinizi belirtmek için bir boole değeri alır. Varsayılan değer: false. Daha fazla bilgi için Geri yükleme verilerinin sürümünü kontrol etme bölümüne bakın.

BackupAgentHelper'ı genişletin

Dosyaları SharedPreferences veya dahili depolama alanındaki eksiksiz bir şekilde yedeklemek istiyorsanız yedek aracınızı BackupAgentHelper kullanarak oluşturmanız gerekir. onBackup() ve onRestore() öğelerini uygulamak zorunda kalmadığınızdan, BackupAgentHelper ile yedek aracınızı oluşturmak BackupAgent öğesini genişletmekten çok daha az kod gerektirir.

BackupAgentHelper uygulamanızda bir veya daha fazla yedek yardımcı kullanılmalıdır. Yedek yardımcı, BackupAgentHelper tarafından belirli bir veri türü için yedekleme ve geri yükleme işlemleri gerçekleştirmek amacıyla toplanan özel bir bileşendir. Android çerçevesi şu anda iki farklı yardımcı sunmaktadır:

BackupAgentHelper öğenize birden fazla yardımcı ekleyebilirsiniz ancak her veri türü için yalnızca bir yardımcı gerekir. Yani birden fazla SharedPreferences dosyanız varsa yalnızca bir SharedPreferencesBackupHelper dosyasına ihtiyacınız vardır.

BackupAgentHelper cihazınıza eklemek istediğiniz her yardımcı için onCreate() yönteminiz sırasında aşağıdakileri yapmanız gerekir:

  1. İstenen yardımcı sınıfın bir örneğini örneklendirin. Sınıf oluşturucuda, yedeklemek istediğiniz dosyaları belirtmeniz gerekir.
  2. Yardımcıyı BackupAgentHelper cihazınıza eklemek için addHelper() numaralı telefonu arayın.

Aşağıdaki bölümlerde, mevcut yardımcıların her birini kullanarak nasıl yedek aracı oluşturulacağı açıklanmaktadır.

SharedPreferences'ı yedekle

Bir SharedPreferencesBackupHelper örneği oluştururken bir veya daha fazla SharedPreferences dosyasının adını eklemeniz gerekir.

Örneğin, user_preferences adlı bir SharedPreferences dosyasını yedeklemek için BackupAgentHelper kullanan eksiksiz bir yedekleme aracısı aşağıdaki gibi görünür:

Kotlin

// The name of the SharedPreferences file
const val PREFS = "user_preferences"

// A key to uniquely identify the set of backup data
const val PREFS_BACKUP_KEY = "prefs"

class MyPrefsBackupAgent : BackupAgentHelper() {
    override fun onCreate() {
        // Allocate a helper and add it to the backup agent
        SharedPreferencesBackupHelper(this, PREFS).also {
            addHelper(PREFS_BACKUP_KEY, it)
        }
    }
}

Java

public class MyPrefsBackupAgent extends BackupAgentHelper {
    // The name of the SharedPreferences file
    static final String PREFS = "user_preferences";

    // A key to uniquely identify the set of backup data
    static final String PREFS_BACKUP_KEY = "prefs";

    // Allocate a helper and add it to the backup agent
    @Override
    public void onCreate() {
        SharedPreferencesBackupHelper helper =
                new SharedPreferencesBackupHelper(this, PREFS);
        addHelper(PREFS_BACKUP_KEY, helper);
    }
}

SharedPreferencesBackupHelper, bir SharedPreferences dosyasını yedeklemek ve geri yüklemek için gereken tüm kodları içerir.

Yedekleme Yöneticisi onBackup() ve onRestore() çağrılarını yaptığında BackupAgentHelper, belirttiğiniz dosyaları yedeklemek ve geri yüklemek için yedek yardımcılarınızı arar.

Diğer dosyaları yedekleme

Bir FileBackupHelper örneği oluştururken, openFileOutput() dosyaları yazdığı konum olan getFilesDir() tarafından belirtildiği gibi uygulamanızın dahili depolama alanına kaydedilen bir veya daha fazla dosyanın adını eklemeniz gerekir.

Örneğin, scores ve stats adlı iki dosyayı yedeklemek için BackupAgentHelper kullanan yedek aracı şu şekilde görünür:

Kotlin

// The name of the file
const val TOP_SCORES = "scores"
const val PLAYER_STATS = "stats"
// A key to uniquely identify the set of backup data
const val FILES_BACKUP_KEY = "myfiles"

class MyFileBackupAgent : BackupAgentHelper() {
    override fun onCreate() {
        // Allocate a helper and add it to the backup agent
        FileBackupHelper(this, TOP_SCORES, PLAYER_STATS).also {
            addHelper(FILES_BACKUP_KEY, it)
        }
    }
}

Java

public class MyFileBackupAgent extends BackupAgentHelper {
    // The name of the file
    static final String TOP_SCORES = "scores";
    static final String PLAYER_STATS = "stats";

    // A key to uniquely identify the set of backup data
    static final String FILES_BACKUP_KEY = "myfiles";

    // Allocate a helper and add it to the backup agent
    @Override
    public void onCreate() {
        FileBackupHelper helper = new FileBackupHelper(this,
                TOP_SCORES, PLAYER_STATS);
        addHelper(FILES_BACKUP_KEY, helper);
    }
}

FileBackupHelper, uygulamanızın dahili depolama alanına kaydedilen dosyaları yedeklemek ve geri yüklemek için gereken tüm kodu içerir.

Ancak dahili depolama alanındaki dosyaları okuma ve yazma işlemleri thread-safe değildir. Yedekleme aracınızın, dosyalarınızı etkinliklerinizle aynı anda okumamasını veya yazmamasını sağlamak için her okuma veya yazma işleminizde senkronize ifadeler kullanmanız gerekir. Örneğin, dosyayı okuyup yazdığınız herhangi bir etkinlikte, senkronize edilmiş ifadeler için iç kilit olarak kullanılacak bir nesneye ihtiyacınız vardır:

Kotlin

// Object for intrinsic lock
companion object {
    val sDataLock = Any()
}

Java

// Object for intrinsic lock
static final Object sDataLock = new Object();

Daha sonra, dosyaları her okuduğunuzda veya yazdığınızda bu kilitle senkronize bir ifade oluşturun. Örneğin, bir oyundaki son skoru dosyaya yazmak için senkronize edilmiş bir ifadeyi aşağıda görebilirsiniz:

Kotlin

try {
    synchronized(MyActivity.sDataLock) {
        val dataFile = File(filesDir, TOP_SCORES)
        RandomAccessFile(dataFile, "rw").apply {
            writeInt(score)
        }
    }
} catch (e: IOException) {
    Log.e(TAG, "Unable to write to file")
}

Java

try {
    synchronized (MyActivity.sDataLock) {
        File dataFile = new File(getFilesDir(), TOP_SCORES);
        RandomAccessFile raFile = new RandomAccessFile(dataFile, "rw");
        raFile.writeInt(score);
    }
} catch (IOException e) {
    Log.e(TAG, "Unable to write to file");
}

Okunan ifadelerinizi aynı kilitle senkronize etmeniz gerekir.

Ardından, yedekleme ve geri yükleme işlemlerini aynı iç kilitle senkronize etmek için BackupAgentHelper içinde onBackup() ve onRestore() değerlerini geçersiz kılmanız gerekir. Örneğin, yukarıdaki MyFileBackupAgent örneğinde aşağıdaki yöntemler gerekir:

Kotlin

@Throws(IOException::class)
override fun onBackup(
        oldState: ParcelFileDescriptor,
        data: BackupDataOutput,
        newState: ParcelFileDescriptor
) {
    // Hold the lock while the FileBackupHelper performs back up
    synchronized(MyActivity.sDataLock) {
        super.onBackup(oldState, data, newState)
    }
}

@Throws(IOException::class)
override fun onRestore(
        data: BackupDataInput,
        appVersionCode: Int,
        newState: ParcelFileDescriptor
) {
    // Hold the lock while the FileBackupHelper restores the file
    synchronized(MyActivity.sDataLock) {
        super.onRestore(data, appVersionCode, newState)
    }
}

Java

@Override
public void onBackup(ParcelFileDescriptor oldState, BackupDataOutput data,
          ParcelFileDescriptor newState) throws IOException {
    // Hold the lock while the FileBackupHelper performs back up
    synchronized (MyActivity.sDataLock) {
        super.onBackup(oldState, data, newState);
    }
}

@Override
public void onRestore(BackupDataInput data, int appVersionCode,
        ParcelFileDescriptor newState) throws IOException {
    // Hold the lock while the FileBackupHelper restores the file
    synchronized (MyActivity.sDataLock) {
        super.onRestore(data, appVersionCode, newState);
    }
}

Yedekleme Aracısını Genişletme

Çoğu uygulamanın BackupAgent sınıfını doğrudan genişletmesi gerekmez. Bunun yerine, dosyalarınızı otomatik olarak yedekleyip geri yükleyen yerleşik yardımcı sınıflardan yararlanmak için BackupAgentHelper sınıfını genişletmelidir. Ancak aşağıdakileri yapmak için doğrudan BackupAgent kapsamını genişletebilirsiniz:

  • Veri biçiminize sürüm oluşturma. Örneğin, uygulama verilerinizi yazdığınız biçimi gözden geçirmeniz gerektiğini düşünüyorsanız geri yükleme işlemi sırasında uygulama sürümünüzü karşılaştırmalı olarak kontrol etmek için bir yedek aracı oluşturabilir ve cihazdaki sürüm, yedekleme verilerininkinden farklıysa gerekli uyumluluk çalışmalarını gerçekleştirebilirsiniz. Daha fazla bilgi için Veri geri yükleme sürümünü kontrol etme bölümüne bakın.
  • Verilerin yedeklenecek bölümlerini belirtin. Bir dosyanın tamamını yedeklemek yerine verilerin yedeklenecek bölümlerini ve her bölümün cihaza nasıl geri yükleneceğini belirleyebilirsiniz. Verilerinizi eksiksiz dosyalar yerine benzersiz varlıklar olarak okuyup yazdığınız için bu, farklı sürümleri yönetmenize de yardımcı olabilir.
  • Verileri veritabanına yedekleyin. Kullanıcı uygulamanızı yeniden yüklediğinde geri yüklemek istediğiniz bir SQLite veritabanınız varsa yedekleme işlemi sırasında uygun verileri okuyan özel bir BackupAgent oluşturmanız, ardından tablonuzu oluşturup geri yükleme işlemi sırasında bu verileri eklemeniz gerekir.

Yukarıdaki görevlerden herhangi birini gerçekleştirmeniz gerekmiyor ve SharedPreferences ya da dahili depolama alanındaki eksiksiz dosyaları yedeklemek istiyorsanız UzatmaBackupAgentHelper bölümünü inceleyin.

Gerekli yöntemler

BackupAgent oluşturduğunuzda aşağıdaki geri çağırma yöntemlerini uygulamanız gerekir:

onBackup()
Bir yedek isteğinde bulunmanız durumunda Yedekleme Yöneticisi bu yöntemi çağırır. Bu yöntemde, Yedekleme gerçekleştirme bölümünde açıklandığı gibi, cihazdan uygulama verilerinizi okur ve yedeklemek istediğiniz verileri Yedekleme Yöneticisi'ne aktarırsınız.
onRestore()

Yedekleme Yöneticisi, bir geri yükleme işlemi sırasında bu yöntemi çağırır. Bu yöntem, Geri yükleme gerçekleştirme bölümünde açıklandığı gibi uygulamanızın önceki durumunu geri yüklemek için kullanabileceği yedek verilerinizi sağlar.

Sistem, kullanıcı uygulamanızı yeniden yüklediğinde tüm yedek verileri geri yüklemek için bu yöntemi çağırır ancak uygulamanız geri yükleme isteğinde de bulunabilir.

Yedekleme işlemi gerçekleştirme

Yedekleme isteği, onBackup() yönteminize hemen çağrı gönderilmesiyle sonuçlanmaz. Bunun yerine, Yedekleme Yöneticisi uygun bir süre bekler, ardından son yedeklemeden sonra yedekleme isteğinde bulunan tüm uygulamalar için bir yedekleme gerçekleştirir. Uygulama verilerinizin bulut depolama alanına kaydedilebilmesi için bu noktada Yedekleme Yöneticisi'ne sağlamanız gerekir.

Yedek temsilcinizin onBackup() yöntemini yalnızca Yedekleme Yöneticisi çağırabilir. Uygulama verileriniz her değiştiğinde ve yedekleme yapmak istediğinizde, dataChanged() yöntemini çağırarak yedekleme işlemi isteğinde bulunmanız gerekir. Daha fazla bilgi için Yedek isteme sayfasına göz atın.

İpucu: Uygulamanızı geliştirirken bmgr aracını kullanarak Yedekleme Yöneticisi'nden anında bir yedekleme işlemi başlatabilirsiniz.

Yedekleme Yöneticisi onBackup() yönteminizi çağırdığında üç parametre iletir:

oldState
Uygulamanızın sağladığı son yedekleme durumunu gösteren açık, salt okunur bir ParcelFileDescriptor. Bu, bulut depolama alanındaki yedekleme verileri değildir. Bunlar yerine onBackup() en son çağrıldığında yedeklenen verilerin newState veya onRestore() tarafından tanımlandığı şekilde yerel temsilidir. onRestore() konusu bir sonraki bölümde ele alınmıştır. onBackup(), bulut depolama alanındaki mevcut yedekleme verilerini okumanıza izin vermediğinden verilerinizin son yedeklemeden sonra değişip değişmediğini belirlemek için bu yerel temsili kullanabilirsiniz.
data
Yedekleme verilerinizi Yedekleme Yöneticisi'ne iletmek için kullandığınız bir BackupDataOutput nesnesi.
newState
data web sitesine gönderdiğiniz verilerin temsilini yazmanız gereken bir dosyayı işaret eden açık, okuma/yazma ParcelFileDescriptor. Beyan, dosyanızın son değiştirilme zamanı damgası kadar basit olabilir. Yedekleme Yöneticisi, onBackup() yönteminizi tekrar çağırdığında bu nesne oldState olarak döndürülür. Yedekleme verilerinizi newState adlı operatöre yazmazsanız oldState, Yedekleme Yöneticisi'nin bir sonraki aramasında boş bir dosyayı işaret eder onBackup().

Aşağıdakileri yapmak için bu parametreleri kullanarak onBackup() yönteminizi uygulayın:

  1. oldState verilerini mevcut verilerinizle karşılaştırarak verilerinizin son yedeklemeden sonra değişip değişmediğini kontrol edin. oldState ürününde verileri nasıl okuyacağınız, verileri başlangıçta newState ürününe nasıl yazdığınıza bağlıdır (3. adıma bakın). Bir dosyanın durumunu kaydetmenin en kolay yolu, dosyanın son değiştirildiği zaman damgasını kullanmaktır. Örneğin, oldState alanındaki bir zaman damgasını nasıl okuyup karşılaştırabileceğiniz aşağıda açıklanmıştır:

    Kotlin

    val instream = FileInputStream(oldState.fileDescriptor)
    val dataInputStream = DataInputStream(instream)
    try {
       // Get the last modified timestamp from the state file and data file
       val stateModified = dataInputStream.readLong()
       val fileModified: Long = dataFile.lastModified()
       if (stateModified != fileModified) {
           // The file has been modified, so do a backup
           // Or the time on the device changed, so be safe and do a backup
       } else {
           // Don't back up because the file hasn't changed
           return
       }
    } catch (e: IOException) {
       // Unable to read state file... be safe and do a backup
    }
    

    Java

    // Get the oldState input stream
    FileInputStream instream = new FileInputStream(oldState.getFileDescriptor());
    DataInputStream in = new DataInputStream(instream);
    
    try {
       // Get the last modified timestamp from the state file and data file
       long stateModified = in.readLong();
       long fileModified = dataFile.lastModified();
    
       if (stateModified != fileModified) {
           // The file has been modified, so do a backup
           // Or the time on the device changed, so be safe and do a backup
       } else {
           // Don't back up because the file hasn't changed
           return;
       }
    } catch (IOException e) {
       // Unable to read state file... be safe and do a backup
    }
    

    Hiçbir değişiklik olmadıysa ve yedeklemeniz gerekmiyorsa 3. adıma geçin.

  2. Verileriniz oldState ile karşılaştırıldığında değiştiyse, bulut depolama alanında yedeklemek için mevcut verileri data ürününe yazın.

    Her veri parçasını BackupDataOutput içinde bir varlık olarak yazmanız gerekir. Varlık, benzersiz bir anahtar dizesiyle tanımlanan, birleştirilmiş bir ikili program veri kaydıdır. Bu nedenle, yedeklediğiniz veri kümesi kavramsal olarak bir dizi anahtar/değer çiftidir.

    Yedek veri kümenize varlık eklemek için:

    1. Yazmak üzere olduğunuz veriler ve veri boyutu için benzersiz bir dize anahtarı ileterek writeEntityHeader() yöntemini çağırın.

    2. Verilerinizi içeren bir bayt arabelleği ileterek arabelleğe aktarılacak bayt sayısını ve writeEntityHeader() öğesine iletilen boyutla eşleşmesi gereken writeEntityData() yöntemini çağırın.

    Örneğin, aşağıdaki kod bazı verileri bayt akışına dönüştürür ve tek bir varlığa yazar:

    Kotlin

    val buffer: ByteArray = ByteArrayOutputStream().run {
       DataOutputStream(this).apply {
           writeInt(playerName)
           writeInt(playerScore)
       }
       toByteArray()
    }
    val len: Int = buffer.size
    data.apply {
       writeEntityHeader(TOPSCORE_BACKUP_KEY, len)
       writeEntityData(buffer, len)
    }
    

    Java

    // Create buffer stream and data output stream for our data
    ByteArrayOutputStream bufStream = new ByteArrayOutputStream();
    DataOutputStream outWriter = new DataOutputStream(bufStream);
    // Write structured data
    outWriter.writeUTF(playerName);
    outWriter.writeInt(playerScore);
    // Send the data to the Backup Manager via the BackupDataOutput
    byte[] buffer = bufStream.toByteArray();
    int len = buffer.length;
    data.writeEntityHeader(TOPSCORE_BACKUP_KEY, len);
    data.writeEntityData(buffer, len);
    

    Yedeklemek istediğiniz her veri parçası için bu işlemi gerçekleştirin. Verilerinizi varlıklara nasıl böleceğiniz size bağlıdır. Hatta tek bir varlık bile kullanabilirsiniz.

  3. Yedekleme yapıp yapmamanızdan bağımsız olarak (2. adımda) mevcut verilerin bir temsilini newState ParcelFileDescriptor öğesine yazın. Yedekleme Yöneticisi, şu anda yedeklenmiş olan verilerin temsili olarak bu nesneyi yerel olarak saklar. 1. adımda açıklandığı gibi, başka bir yedeklemenin gerekip gerekmediğini belirleyebilmeniz için onBackup() çağrısında bulunan bir sonraki sefer oldState olarak bunu size geri gönderir. Mevcut veri durumunu bu dosyaya yazmazsanız bir sonraki geri çağırma sırasında oldState boş olur.

    Aşağıdaki örnek, dosyanın son değiştirilme zamanı damgası kullanılarak mevcut verilerin bir temsilini newState dosyasına kaydeder:

    Kotlin

    val modified = dataFile.lastModified()
    FileOutputStream(newState.fileDescriptor).also {
       DataOutputStream(it).apply {
           writeLong(modified)
       }
    }
    

    Java

    FileOutputStream outstream = new FileOutputStream(newState.getFileDescriptor());
    DataOutputStream out = new DataOutputStream(outstream);
    
    long modified = dataFile.lastModified();
    out.writeLong(modified);
    

Geri yükleme gerçekleştir

Uygulama verilerinizi geri yükleme zamanı geldiğinde Yedekleme Yöneticisi, yedek temsilcinizin onRestore() yöntemini çağırır. Bu yöntemi çağırdığında, Yedekleme Yöneticisi yedek verilerinizi teslim eder. Böylece bu verileri cihaza geri yükleyebilirsiniz.

onRestore() numaralı telefonu yalnızca Yedekleme Yöneticisi çağırabilir. Bu işlem, sistem uygulamanızı yüklediğinde ve mevcut yedek verileri bulduğunda otomatik olarak gerçekleşir.

Yedekleme Yöneticisi onRestore() yönteminizi çağırdığında üç parametre iletir:

data
Yedekleme verilerinizi okumanızı sağlayan bir BackupDataInput nesnesi.
appVersionCode
Uygulamanızın android:versionCode manifest özelliğinin (bu veriler yedeklendiği zamandaki) değerini temsil eden tam sayı. Mevcut uygulama sürümünü karşılaştırmalı olarak kontrol etmek ve veri biçiminin uyumlu olup olmadığını belirlemek için bunu kullanabilirsiniz. Geri yükleme verilerinin farklı sürümlerini işlemek üzere bu yöntemi kullanma hakkında daha fazla bilgi için Veri geri yükleme sürümünü kontrol etme bölümüne bakın.
newState
data ile sağlanan son yedekleme durumunu yazmanız gereken bir dosyayı işaret eden açık, okuma/yazma ParcelFileDescriptor. onBackup() bir sonraki çağrıldığında bu nesne oldState olarak döndürülür. Aynı newState nesnesini onBackup() geri çağırmasına da yazmanız gerektiğini unutmayın. Burada ayrıca yapılması, onBackup() öğesine verilen oldState nesnesinin, cihaz geri yüklendikten sonra onBackup() ilk çağrıldığında bile geçerli olmasını sağlar.

onRestore() uygulamanızda, veri kümesindeki tüm varlıkları yinelemek için data tarihinde readNextHeader() yöntemini çağırmanız gerekir. Bulunan her varlık için aşağıdakileri yapın:

  1. getKey() ile varlık anahtarını alın.
  2. Varlık anahtarını, BackupAgent sınıfınızda statik nihai dize olarak bildirmeniz gereken bilinen anahtar değerlerin bir listesiyle karşılaştırın. Anahtar, bilinen anahtar dizelerinizden biriyle eşleştiğinde varlık verilerini çıkarmak ve cihaza kaydetmek için bir ifade girin:

    1. getDataSize() ile varlık veri boyutunu alın ve bu boyutta bir bayt dizisi oluşturun.
    2. readEntityData() yöntemini çağırın ve verilerin ekleneceği bayt dizisini ileterek başlangıç ofsetini ve okunacak boyutu belirtin.
    3. Bayt diziniz artık dolu. Verileri istediğiniz gibi okuyun ve cihaza yazın.
  3. Verilerinizi cihaza okuyup yazdıktan sonra, onBackup() işlemini yaptığınız gibi newState parametresine verilerinizin durumunu yazın.

Örneğin, önceki bölümde verilen örnekte yedeklenen verileri nasıl geri yükleyebileceğiniz aşağıda açıklanmıştır:

Kotlin

@Throws(IOException::class)
override fun onRestore(data: BackupDataInput, appVersionCode: Int,
                       newState: ParcelFileDescriptor) {
    with(data) {
        // There should be only one entity, but the safest
        // way to consume it is using a while loop
        while (readNextHeader()) {
            when(key) {
                TOPSCORE_BACKUP_KEY -> {
                    val dataBuf = ByteArray(dataSize).also {
                        readEntityData(it, 0, dataSize)
                    }
                    ByteArrayInputStream(dataBuf).also {
                        DataInputStream(it).apply {
                            // Read the player name and score from the backup data
                            playerName = readUTF()
                            playerScore = readInt()
                        }
                        // Record the score on the device (to a file or something)
                        recordScore(playerName, playerScore)
                    }
                }
                else -> skipEntityData()
            }
        }
    }

    // Finally, write to the state blob (newState) that describes the restored data
    FileOutputStream(newState.fileDescriptor).also {
        DataOutputStream(it).apply {
            writeUTF(playerName)
            writeInt(mPlayerScore)
        }
    }
}

Java

@Override
public void onRestore(BackupDataInput data, int appVersionCode,
                      ParcelFileDescriptor newState) throws IOException {
    // There should be only one entity, but the safest
    // way to consume it is using a while loop
    while (data.readNextHeader()) {
        String key = data.getKey();
        int dataSize = data.getDataSize();

        // If the key is ours (for saving top score). Note this key was used when
        // we wrote the backup entity header
        if (TOPSCORE_BACKUP_KEY.equals(key)) {
            // Create an input stream for the BackupDataInput
            byte[] dataBuf = new byte[dataSize];
            data.readEntityData(dataBuf, 0, dataSize);
            ByteArrayInputStream baStream = new ByteArrayInputStream(dataBuf);
            DataInputStream in = new DataInputStream(baStream);

            // Read the player name and score from the backup data
            playerName = in.readUTF();
            playerScore = in.readInt();

            // Record the score on the device (to a file or something)
            recordScore(playerName, playerScore);
        } else {
            // We don't know this entity key. Skip it. (Shouldn't happen.)
            data.skipEntityData();
        }
    }

    // Finally, write to the state blob (newState) that describes the restored data
    FileOutputStream outstream = new FileOutputStream(newState.getFileDescriptor());
    DataOutputStream out = new DataOutputStream(outstream);
    out.writeUTF(playerName);
    out.writeInt(mPlayerScore);
}

Bu örnekte, onRestore() öğesine iletilen appVersionCode parametresi kullanılmaz. Ancak, kullanıcı uygulama sürümü gerçekten geri taşındığında (örneğin, kullanıcı uygulamanızın 1.5 sürümünden 1.0 sürümüne geçtiğinde) yedekleme yapmayı tercih ettiyseniz bu aracı kullanmak isteyebilirsiniz. Daha fazla bilgi için sonraki bölüme bakın.

Veri geri yükleme sürümünü kontrol etme

Yedekleme Yöneticisi, verilerinizi bulut depolama alanına kaydettiğinde, manifest dosyanızın android:versionCode özelliği tarafından tanımlanan şekliyle uygulamanızın sürümünü otomatik olarak içerir. Yedekleme Yöneticisi, verilerinizi geri yüklemek için yedek aracınızı çağırmadan önce, yüklü uygulamanın android:versionCode değerine bakar ve bunu geri yükleme veri kümesinde kaydedilen değerle karşılaştırır. Geri yükleme veri kümesinde kaydedilen sürüm, cihazdaki uygulama sürümünden daha yeni ise kullanıcı, uygulamasını eski sürüme geçirmiştir. Bu durumda, geri yükleme kümesi daha eski bir sürüm için anlamsız kabul edildiğinden, Yedekleme Yöneticisi uygulamanızın geri yükleme işlemini iptal eder ve onRestore() yönteminizi çağırmaz.

Bu davranışı android:restoreAnyVersion özelliğiyle geçersiz kılabilirsiniz. Geri yükleme grubu sürümünden bağımsız olarak uygulamayı geri yüklemek istediğinizi belirtmek için bu özelliği true olarak ayarlayın. Varsayılan değer: false. Bunu true olarak ayarlarsanız Yedekleme Yöneticisi android:versionCode özelliğini yoksayar ve her durumda onRestore() yönteminizi çağırır. Bu sırada, onRestore() yönteminizdeki sürüm farkını manuel olarak kontrol edebilir ve sürümler eşleşmiyorsa verileri uyumlu hale getirmek için gereken adımları uygulayabilirsiniz.

onRestore() yöntemi, geri yükleme işlemi sırasında farklı sürümleri ele almanıza yardımcı olmak için geri yükleme verileri kümesine appVersionCode parametresi olarak eklenen sürüm kodunu size iletir. Daha sonra, geçerli uygulamanın sürüm kodunu PackageInfo.versionCode alanı ile sorgulayabilirsiniz. Örneğin:

Kotlin

val info: PackageInfo? = try {
    packageManager.getPackageInfo(packageName, 0)
} catch (e: PackageManager.NameNotFoundException) {
    null
}

val version: Int = info?.versionCode ?: 0

Java

PackageInfo info;
try {
    String name = getPackageName();
    info = getPackageManager().getPackageInfo(name, 0);
} catch (NameNotFoundException nnfe) {
    info = null;
}

int version;
if (info != null) {
    version = info.versionCode;
}

Ardından, PackageInfo kaynağından alınan version değerini, onRestore() öğesine aktarılan appVersionCode ile karşılaştırın.

Yedek isteme

İstediğiniz zaman dataChanged() numaralı telefonu arayarak yedekleme işlemi isteğinde bulunabilirsiniz. Bu yöntem, Yedekleme Yöneticisi'ne verilerinizi yedek aracınızı kullanarak yedeklemek istediğinizi bildirir. Daha sonra Yedekleme Yöneticisi, yedek temsilcinizin onBackup() yöntemini ileri bir zamanda çağırır. Genellikle, verileriniz her değiştiğinde (örneğin, kullanıcı yedeklemek istediğiniz bir uygulama tercihini değiştirdiğinde) bir yedekleme isteğinde bulunmanız gerekir. Yedekleme Yöneticisi, temsilcinizden yedek istemeden önce dataChanged() numaralı telefonu birkaç kez ararsanız temsilciniz onBackup() numaralı telefona yine tek bir arama alır.

Geri yükleme isteğinde bulun

Uygulamanızın normal ömrü boyunca geri yükleme işlemi isteğinde bulunmanız gerekmez. Sistem, otomatik olarak yedek verileri kontrol eder ve uygulamanız yüklendiğinde bir geri yükleme işlemi gerçekleştirir.

Otomatik Yedekleme'ye taşı

Manifest dosyasındaki <application> öğesinde android:fullBackupOnly öğesini true olarak ayarlayarak uygulamanızı tam veri yedeklemelerine geçirebilirsiniz. Uygulamanız, Android 5.1 (API düzeyi 22) veya önceki sürümleri çalıştıran bir cihazda çalışırken manifest dosyasında bu değeri yoksayar ve anahtar/değer yedeklemeleri gerçekleştirmeye devam eder. Uygulamanız, Android 6.0 (API düzeyi 23) veya sonraki sürümleri çalıştıran bir cihazda anahtar/değer çifti yedekleme yerine Otomatik Yedekleme gerçekleştirir.

Kullanıcı gizliliği

Google olarak kullanıcıların bize duyduğu güvenin ve kullanıcıların gizliliğini koruma sorumluluğumuzun farkındayız. Google, yedekleme ve geri yükleme özellikleri sunmak için yedekleme verilerini Google sunucularına ve bu sunuculardan güvenli bir şekilde iletir. Google bu verileri Google'ın Gizlilik Politikası'na uygun şekilde kişisel bilgi olarak işler.

Ayrıca kullanıcılar, Android sisteminin yedekleme ayarları üzerinden veri yedekleme işlevini devre dışı bırakabilir. Bir kullanıcı yedeklemeyi devre dışı bıraktığında, Android Backup Service kayıtlı tüm yedekleme verilerini siler. Kullanıcı, cihazda yedeklemeyi yeniden etkinleştirebilir, ancak Android Backup Service, daha önce silinmiş verileri geri yüklemez.