Android Backup Service की मदद से, की-वैल्यू पेयर का बैक अप लेना

Android की बैकअप सेवा, मुख्य वैल्यू के लिए क्लाउड स्टोरेज का बैकअप लेने और उसे वापस पाने की सुविधा देती है डेटा शामिल है. की-वैल्यू वाली बैकअप कार्रवाई के दौरान, ऐप्लिकेशन का बैकअप डेटा को डिवाइस के बैकअप ट्रांसपोर्ट में भेज दिया जाता है. अगर डिवाइस डिफ़ॉल्ट Google बैकअप ट्रांसपोर्ट, फिर डेटा Android बैकअप को भेज दिया जाता है संग्रहित करने की सेवा.

आपके ऐप्लिकेशन के हर उपयोगकर्ता का डेटा 5 एमबी तक सीमित होता है. स्टोर करने के लिए कोई शुल्क नहीं है बैकअप डेटा.

Android के बैकअप विकल्पों की खास जानकारी और इस बारे में दिशा-निर्देश पाने के लिए कि कौनसा डेटा का बैक अप लेना और उसे वापस लाना है, तो डेटा का बैकअप देखें खास जानकारी पर टैप करें.

की-वैल्यू बैकअप लागू करना

अपने ऐप्लिकेशन डेटा का बैकअप लेने के लिए, आपको बैकअप एजेंट लागू करना होगा. आपका बैकअप बैकअप लेने और डेटा वापस पाने के दौरान, बैकअप मैनेजर एजेंट को कॉल करता है.

बैकअप एजेंट लागू करने के लिए, आपको:

  1. अपनी मेनिफ़ेस्ट फ़ाइल में बैकअप एजेंट का एलान android:backupAgent एट्रिब्यूट की वैल्यू सबमिट करें.

  2. बैकअप एजेंट तय करने के लिए, इनमें से कोई एक तरीका अपनाएं:

    • BackupAgent की अवधि बढ़ाई जा रही है

      BackupAgent क्लास ऐप्लिकेशन, एक ऐसा सेंट्रल इंटरफ़ेस उपलब्ध कराता है जिसका इस्तेमाल आपका ऐप्लिकेशन, बैकअप मैनेजर पर क्लिक करें. अगर इस क्लास को सीधे तौर पर एक्सटेंड किया जाता है, तो आपको अपने डेटा के बैक अप और उसे वापस लाने की प्रोसेस को मैनेज करने के लिए, onBackup() और onRestore() को बदलना होगा.

    • BackupAgentHelper की अवधि बढ़ाई जा रही है

      BackupAgentHelper क्लास, BackupAgent क्लास के लिए एक आसान रैपर उपलब्ध कराती है. इससे, आपको कम से कम कोड लिखना पड़ता है. अपने BackupAgentHelper है, तो आपको एक या उससे ज़्यादा हेल्पर ऑब्जेक्ट का इस्तेमाल करना होगा, कुछ प्रकार के डेटा का अपने आप बैक अप ले लेगा और उसे पुनर्स्थापित कर सकेगा, ताकि आप onBackup() और onRestore() लागू करने की ज़रूरत होती है. जब तक आपको स्टोरेज की पूरी ज़रूरत न हो तो हमारा सुझाव है कि आप BackupAgentHelper का इस्तेमाल करें और बैकअप लेने की ज़रूरत नहीं होती.

      फ़िलहाल, Android में बैकअप लेने में मदद करने वाली सुविधाएं उपलब्ध हैं. इनकी मदद से, SharedPreferences और इंटरनल स्टोरेज में मौजूद सभी फ़ाइलों का बैकअप लिया जा सकता है और उन्हें वापस लाया जा सकता है.

अपनी मेनिफ़ेस्ट फ़ाइल में बैकअप एजेंट की जानकारी दें

बैकअप एजेंट के लिए क्लास का नाम तय करने के बाद, <application> टैग में android:backupAgent एट्रिब्यूट का इस्तेमाल करके, उसे अपने मेनिफ़ेस्ट में एलान करें.

उदाहरण के लिए:

<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>

हमारा सुझाव है कि पुराने डिवाइसों के साथ काम करने के लिए, एपीआई पासकोड <meta-data> जोड़ें को अपलोड करने की ज़रूरत नहीं पड़ेगी. Android Backup Service के लिए अब सेवा कुंजी की ज़रूरत नहीं है. हालांकि, हो सकता है कि कुछ पुराने डिवाइसों पर बैकअप लेने के दौरान, अब भी कुंजी की जांच की जाए. android:name को com.google.android.backup.api_key पर और android:value से unused.

कॉन्टेंट बनाने android:restoreAnyVersion एट्रिब्यूट की बूलियन वैल्यू का इस्तेमाल करके यह पता चलता है कि आपको ऐप्लिकेशन को वापस लाना है या नहीं डेटा भले ही ऐप्लिकेशन के मौजूदा वर्शन की तुलना में डेटा का बैकअप लिया है. डिफ़ॉल्ट वैल्यू false है. ज़्यादा जानकारी के लिए, डेटा का वह वर्शन देखें जिसे वापस पाना है लेख पढ़ें.

Extend BackupAgentHelper

अगर आप चाहें, तो आपको BackupAgentHelper का इस्तेमाल करके अपना बैकअप एजेंट बनाना चाहिए SharedPreferences या डिवाइस के स्टोरेज से पूरी फ़ाइलों का बैक अप लें. BackupAgentHelper के साथ बैकअप एजेंट बनाने के लिए इससे कम कोड की ज़रूरत होती है एक्सटेंशन BackupAgent को बढ़ाया जा रहा है, क्योंकि आपको onBackup() और onRestore().

BackupAgentHelper को लागू करने के लिए, एक या उससे ज़्यादा बैकअप हेल्पर का इस्तेमाल करना ज़रूरी है. बैकअप हेल्पर एक खास कॉम्पोनेंट होता है, जिसे BackupAgentHelper इकट्ठा करता है किसी खास तरह के डेटा का बैकअप लेने और उसे रीस्टोर करने का काम करता है. कॉन्टेंट बनाने Android फ़्रेमवर्क, फ़िलहाल दो अलग-अलग हेल्पर उपलब्ध कराता है:

  • SharedPreferences फ़ाइलों का बैक अप लेने के लिए, SharedPreferencesBackupHelper को चुनें.
  • पीछे जाने के लिए FileBackupHelper डिवाइस के स्टोरेज में सेव की गई फ़ाइलें मिटा दें.

BackupAgentHelper में एक से ज़्यादा हेल्पर शामिल किए जा सकते हैं, लेकिन सिर्फ़ एक ही मदद ली जा सकती है हर डेटा टाइप के लिए हेल्पर की ज़रूरत होती है. इसका मतलब है कि अगर आपके पास एक से ज़्यादा SharedPreferences फ़ाइलें हैं, तो आपको सिर्फ़ एक SharedPreferencesBackupHelper फ़ाइल की ज़रूरत है.

हर उस हेल्पर के लिए जिसे आपको अपने BackupAgentHelper में जोड़ना है, आपको ये काम करने होंगे फ़ॉलो कर रहे हैं, onCreate() तरीका:

  1. मनचाहे हेल्पर क्लास का इंस्टेंस इंस्टैंशिएट करें. क्लास के कंस्ट्रक्टर में, आपको उन फ़ाइलों के बारे में बताना होगा जिनका बैक अप लेना है.
  2. कॉल करें addHelper() अपने BackupAgentHelper में हेल्पर को जोड़ने के लिए.

नीचे दिए सेक्शन में बताया गया है कि उपलब्ध हेल्पर.

SharedPreferences का बैक अप लें

SharedPreferencesBackupHelper को इंस्टैंशिएट करते समय, आपको एक या ज़्यादा SharedPreferences फ़ाइलों का नाम डालें.

उदाहरण के लिए, user_preferences नाम की SharedPreferences फ़ाइल का बैक अप लेने के लिए, BackupAgentHelper का इस्तेमाल करने वाला पूरा बैकअप एजेंट ऐसा दिखता है:

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 में वे सभी कोड मौजूद हैं जिनका बैक अप लेना है और SharedPreferences फ़ाइल को वापस लाएं.

जब Backup Manager, onBackup() और onRestore() को कॉल करता है, तो BackupAgentHelper आपके बैकअप हेल्पर को कॉल करता है, ताकि आपने जिन फ़ाइलों का बैक अप लेने के लिए कहा है उनका बैक अप लिया जा सके और उन्हें वापस लाया जा सके.

अन्य फ़ाइलों का बैक अप लें

FileBackupHelper का इंस्टेंस बनाते समय, आपको एक या उससे ज़्यादा फ़ाइलों का नाम शामिल करना होगा. ये फ़ाइलें, आपके ऐप्लिकेशन के इंटरनल स्टोरेज में सेव होनी चाहिए. इन फ़ाइलों के नाम, getFilesDir() में बताए गए हैं. यह वही जगह है जहां openFileOutput() फ़ाइलें लिखता है.

उदाहरण के लिए, scores और stats नाम की दो फ़ाइलों का बैक अप लेने के लिए, जो एक बैकअप एजेंट हैं BackupAgentHelper का उपयोग करने पर यह ऐसा दिखेगा:

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 में, आपके ऐप्लिकेशन के इंटरनल स्टोरेज में सेव की गई फ़ाइलों का बैक अप लेने और उन्हें वापस लाने के लिए ज़रूरी सारा कोड शामिल होता है.

हालांकि, डिवाइस के स्टोरेज में मौजूद फ़ाइलों को पढ़ने और लिखने की सुविधा नहीं है थ्रेड सुरक्षित है. यह पक्का करने के लिए कि आपका बैकअप एजेंट, आपकी गतिविधियों के दौरान आपकी फ़ाइलों को न पढ़े या उनमें न लिखे, आपको हर बार पढ़ने या लिखने के लिए सिंक किए गए स्टेटमेंट का इस्तेमाल करना होगा. उदाहरण के लिए, ऐसी किसी भी गतिविधि में जहां आपने पढ़ने और लिखने के लिए, आपको एक ऑब्जेक्ट की ज़रूरत होगी, जिसका इस्तेमाल सिंक किए गए स्टेटमेंट:

Kotlin

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

Java

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

इसके बाद, हर बार फ़ाइलों को पढ़ने या उनमें बदलाव करने पर, इस लॉक के साथ सिंक किया गया स्टेटमेंट बनाएं. उदाहरण के लिए, यहां किसी गेम में सबसे नया स्कोर, फ़ाइल में लिखने के लिए सिंक किया गया स्टेटमेंट दिया गया है:

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");
}

आपको अपने पढ़े गए स्टेटमेंट एक ही लॉक से सिंक करने चाहिए.

इसके बाद, अपने BackupAgentHelper में, आपको onBackup() और onRestore() को बदलना होगा, ताकि बैकअप और वापस पाने की प्रोसेस को एक ही अंतरिक्ष लॉक के साथ सिंक किया जा सके. उदाहरण के लिए, ऊपर दिए गए MyFileBackupAgent उदाहरण के लिए, इन तरीकों की ज़रूरत है:

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);
    }
}

बैक अप एजेंट को लंबे समय तक बढ़ाएं

ज़्यादातर ऐप्लिकेशन को BackupAgent क्लास को सीधे तौर पर बढ़ाने की ज़रूरत नहीं होनी चाहिए. हालांकि, ऐसा करना चाहिए इसके बजाय, फ़ायदा पाने के लिए BackupAgentHelper की अवधि बढ़ाएं पहले से मौजूद हेल्पर क्लास की सुविधा का इस्तेमाल करें. ये आपकी फ़ाइलों का अपने-आप बैक अप लेती हैं और उन्हें वापस लाती हैं. हालांकि, इन कामों के लिए BackupAgent को सीधे तौर पर एक्सटेंड किया जा सकता है:

  • अपने डेटा फ़ॉर्मैट का वर्शन बनाएं. उदाहरण के लिए, अगर आपको जिस फ़ॉर्मैट में ऐप्लिकेशन का डेटा लिखा जाता है उसमें बदलाव किया जा सकता है, बैकअप लिया जा सकता है को वापस करने की कार्रवाई के दौरान, एजेंट को आपके ऐप्लिकेशन के वर्शन की दोबारा जांच करनी चाहिए. डिवाइस का वर्शन अलग होने पर किसी भी ज़रूरी काम करने के लिए सुझाव दें 30% से कम नहीं है. ज़्यादा जानकारी के लिए, बहाल किए गए डेटा का वर्शन देखना लेख पढ़ें.
  • यह तय करें कि बैक अप के लिए डेटा का कौनसा हिस्सा इस्तेमाल करना है. पूरे डेटा का बैक अप लेने के बजाय फ़ाइल है, तो आप डेटा के उन हिस्सों को तय कर सकते है जिनका बैक अप लेना है और फिर डिवाइस पर बहाल किया गया. इससे आपको अलग-अलग वर्शन मैनेज करने में भी मदद मिल सकती है. ऐसा इसलिए, क्योंकि डेटा को पूरी फ़ाइलों के बजाय, यूनीक इकाइयों के तौर पर पढ़ा और लिखा जाता है.
  • डेटाबेस में मौजूद डेटा का बैक अप लेना. अगर आपके पास अपनी पसंद का SQLite डेटाबेस है उपयोगकर्ता के आपके ऐप्लिकेशन को पुनः इंस्टॉल करने पर उसे पुनर्स्थापित करने के लिए, आपको एक कस्टम BackupAgent जो बैकअप कार्रवाई के दौरान सही डेटा पढ़ता है, इसके बाद अपनी टेबल बनाएं और वापस लाने की कार्रवाई के दौरान डेटा शामिल करें.

अगर आपको ऊपर दिए गए किसी भी काम की ज़रूरत नहीं है और आपको SharedPreferences या डिवाइस के स्टोरेज में मौजूद सभी फ़ाइलों का बैक अप लेना है, तो BackupAgentHelper को बड़ा करना लेख पढ़ें.

ज़रूरी तरीके

BackupAgent बनाते समय, आपको ये कॉलबैक तरीके लागू करने होंगे:

onBackup()
बैकअप मैनेजर इस विधि को आपके अनुरोध करने के बाद कॉल करता है बैक अप लें. इस तरीके में, डिवाइस से ऐप्लिकेशन का डेटा पढ़ा जाता है और उस डेटा को बैकअप मैनेजर को भेजा जाता है जिसका बैक अप लेना है. इस बारे में बैक अप लेने का तरीका में बताया गया है.
onRestore()

बैकअप मैनेजर इस तरीके को पहले जैसा करने की कार्रवाई के दौरान कॉल करता है. यह तरीका आपका बैकअप डेटा डिलीवर करता है. ऐप्लिकेशन इसका इस्तेमाल करके, पुराना डेटा वापस ला सकता है जैसा कि डेटा वापस पाने की सुविधा में बताया गया है.

सिस्टम इस तरीके को, बैकअप डेटा को वापस लाने के लिए कॉल करता है. ऐसा तब होता है, जब उपयोगकर्ता आपके ऐप्लिकेशन को फिर से इंस्टॉल करता है, लेकिन आपका ऐप्लिकेशन किसी वापस लाएं.

बैक अप लेना

बैकअप के अनुरोध करने पर, आपके onBackup() पेमेंट के तरीके पर तुरंत कॉल नहीं किया जाता. इसके बजाय, बैकअप मैनेजर सही समय का इंतज़ार करता है. इसके बाद, वह उन सभी ऐप्लिकेशन का बैकअप लेता है जिन्होंने पिछली बार बैकअप लेने के बाद से बैकअप का अनुरोध किया है. यहां पर आपको अपने ऐप्लिकेशन का डेटा देना होगा से लिंक करना होगा, ताकि इसे क्लाउड स्टोरेज में सेव किया जा सके.

सिर्फ़ बैकअप मैनेजर आपके बैकअप एजेंट के onBackup() तरीके को कॉल कर सकता है. हर जब आपको ऐप्लिकेशन के डेटा में बदलाव करना हो और आपको बैकअप लेना हो, तो ऐसा करना ज़रूरी है. कॉल करके बैकअप कार्रवाई का अनुरोध करें dataChanged(). ज़्यादा जानकारी के लिए बैकअप का अनुरोध करें देखें.

सलाह: अपना ऐप्लिकेशन डेवलप करते समय, तुरंत बैकअप लेने की प्रोसेस शुरू की जा सकती है bmgr के साथ बैकअप मैनेजर की ओर से कार्रवाई टूल.

जब बैकअप मैनेजर आपके onBackup() तरीके को कॉल करता है, तो यह तीन से ज़्यादा हो जाता है पैरामीटर:

oldState
ओपन, रीड-ओनली ParcelFileDescriptor पॉइंटिंग आपके ऐप्लिकेशन से मिली पिछली बैकअप स्थिति तक. यह बैकअप डेटा नहीं है क्लाउड स्टोरेज से लिया गया है, लेकिन उस डेटा का स्थानीय प्रतिनिधित्व जिसका बैक अप लिया गया था पिछली बार onBackup() को कॉल किया गया था, जैसा कि newState या onRestore(). onRestore() के बारे में अगले सेक्शन में बताया गया है. onBackup() की मदद से, क्लाउड स्टोरेज में मौजूद बैकअप डेटा को नहीं पढ़ा जा सकता. इसलिए, इस लोकल डेटा का इस्तेमाल करके यह पता लगाया जा सकता है कि पिछले बैकअप के बाद आपके डेटा में बदलाव हुआ है या नहीं.
data
एक BackupDataOutput ऑब्जेक्ट की मदद से बनाया जाता है, जिसका इस्तेमाल बैकअप मैनेजर को बैकअप डेटा देने के लिए किया जाता है.
newState
उस फ़ाइल के बारे में बताने वाला एक खुला, पढ़ें/लिखें ParcelFileDescriptor, जिसमें आप आपको उस डेटा का प्रतिनिधित्व लिखना होगा जो आपने data को डिलीवर किया था. ऐप्लिकेशन यह आपकी फ़ाइल के लिए, आखिरी बार बदलाव किए गए टाइमस्टैंप जितना आसान हो सकता है. अगली बार जब Backup Manager आपके onBackup() तरीके को कॉल करेगा, तो यह ऑब्जेक्ट oldState के तौर पर दिखाया जाएगा. अगर आपने newState में बैकअप डेटा नहीं डाला है, तो अगली बार जब Backup Manager onBackup() को कॉल करेगा, तब oldState खाली फ़ाइल पर ले जाएगा.

इन पैरामीटर का इस्तेमाल करके, अपना onBackup() तरीका लागू करें और ये काम करें:

  1. पिछले बैकअप के बाद से डेटा में बदलाव हुआ है या नहीं, इसकी तुलना करके देखें आपके मौजूदा डेटा में oldState. oldState में डेटा को पढ़ने का तरीका, इस बात पर निर्भर करता है कि आपने इसे newState में कैसे लिखा था (तीसरा चरण देखें). सबसे आसान तरीका फ़ाइल की स्थिति को उसके आखिरी बदलाव किए गए टाइमस्टैंप के साथ रिकॉर्ड करें. उदाहरण के लिए, oldState के टाइमस्टैंप को पढ़ने और उसकी तुलना करने का तरीका यहां बताया गया है:

    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
    }

    अगर कोई बदलाव नहीं हुआ है और आपको बैक अप लेने की ज़रूरत नहीं है, तो सीधे तीसरे चरण पर जाएं.

  2. अगर oldState की तुलना में आपका डेटा बदल गया है, तो मौजूदा डेटा को क्लाउड स्टोरेज पर इसका बैक अप लेने के लिए data.

    आपको BackupDataOutput में डेटा के हर हिस्से को इकाई के तौर पर लिखना होगा. इकाई, एक फ़्लैट किया गया बाइनरी डेटा रिकॉर्ड होता है. इसकी पहचान, एक यूनीक पासकोड स्ट्रिंग से की जाती है. इस प्रकार, आप जिस डेटा सेट का बैक अप लेते हैं, वह सैद्धांतिक रूप से की-वैल्यू पेयर.

    अपने बैकअप डेटा सेट में कोई इकाई जोड़ने के लिए, आपको ये काम करने होंगे:

    1. कॉल करें writeEntityHeader(), जो डेटा आप लिखने वाले हैं उसके लिए एक अद्वितीय स्ट्रिंग कुंजी पास करना और डेटा साइज़.

    2. writeEntityData() को कॉल करें. इसके लिए, बाइट बफ़र को पास करें. इसमें आपका डेटा और बफ़र से लिखे जाने वाले बाइट की संख्या शामिल होनी चाहिए. यह संख्या, writeEntityHeader() को पास किए गए साइज़ से मेल खानी चाहिए.

    उदाहरण के लिए, यह कोड कुछ डेटा को बाइट स्ट्रीम में फ़्लैट करता है और उसे एक एंटिटी में लिखता है:

    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);

    आपको जिस डेटा का बैक अप लेना है उसके लिए यह तरीका अपनाएं. बांटने का तरीका आपका डेटा इकाइयों में शामिल होना चाहिए या नहीं. यहां तक कि आप केवल एक इकाई का उपयोग भी कर सकते हैं.

  3. दूसरे चरण में बैकअप लेने के बाद भी, newState ParcelFileDescriptor में मौजूदा डेटा की जानकारी लिखें. द बैकअप मैनेजर इस ऑब्जेक्ट को स्थानीय तौर पर, उस डेटा के प्रतिनिधि के तौर पर बनाए रखता है जो फ़िलहाल, बैक अप लिया जा चुका है. अगली बार onBackup() को कॉल करने पर, यह वैल्यू आपको oldState के तौर पर वापस भेजती है, ताकि आप यह तय कर सकें कि पहला बैकअप लेने के बाद, क्या कोई और बैकअप लेना ज़रूरी है. यह तय करने का तरीका, पहले चरण में बताया गया है. अगर इस फ़ाइल में मौजूदा डेटा की स्थिति नहीं लिखी जाती है, तो अगले कॉलबैक के दौरान oldState खाली रहेगा.

    यहां दिए गए उदाहरण में, फ़ाइल में पिछली बार बदलाव करने के टाइमस्टैंप का इस्तेमाल करके, मौजूदा डेटा को newState में सेव किया गया है:

    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);

डेटा को वापस लाना

जब आपके ऐप्लिकेशन के डेटा को वापस लाने का समय आता है, तो Backup Manager आपके बैकअप एजेंट के onRestore() तरीके को कॉल करता है. इस तरीके को कॉल करने पर, Backup Manager आपके बैकअप डेटा को डिलीवर करता है, ताकि आप उसे डिवाइस पर वापस ला सकें.

सिर्फ़ बैकअप मैनेजर onRestore() को कॉल कर सकता है, जो अपने-आप होता है जब सिस्टम आपका ऐप्लिकेशन इंस्टॉल करता है और उसे मौजूदा बैकअप डेटा मिलता है.

जब बैकअप मैनेजर आपके onRestore() तरीके को कॉल करता है, तो यह तीन से ज़्यादा हो जाता है पैरामीटर:

data
एक BackupDataInput ऑब्जेक्ट, इसकी मदद से, बैकअप में मौजूद डेटा को पढ़ा जा सकता है.
appVersionCode
आपके ऐप्लिकेशन की वैल्यू दिखाने वाला पूर्णांक android:versionCode मेनिफ़ेस्ट विशेषता में दी गई जानकारी इस्तेमाल करें, जैसा कि इस डेटा का बैक अप लेने पर किया गया था. इसका इस्तेमाल करके, ऐप्लिकेशन के मौजूदा वर्शन की पुष्टि की जा सकती है. साथ ही, यह भी पता लगाया जा सकता है कि डेटा फ़ॉर्मैट काम करता है या नहीं. अलग-अलग मैसेज को हैंडल करने के लिए इसका इस्तेमाल करने के बारे में डेटा वापस पाने का विकल्प चुनने पर, डेटा वापस पाने की प्रोसेस से जुड़ा डेटा देखें वर्शन के तौर पर उपलब्ध है.
newState
उस फ़ाइल के बारे में बताने वाला एक खुला, पढ़ें/लिखें ParcelFileDescriptor, जिसमें आप को data के साथ उपलब्ध कराई गई बैकअप की आखिरी स्थिति लिखनी होगी. यह ऑब्जेक्ट अगली बार onBackup() को कॉल करने पर, oldState के तौर पर दिखेगा. याद रखें कि आपको onBackup() कॉलबैक में भी वही newState ऑब्जेक्ट लिखना होगा. ऐसा करने से यह भी पक्का होता है कि डिवाइस को वापस लाने के बाद, onBackup() को पहली बार कॉल करने पर भी onBackup() को दिया गया oldState ऑब्जेक्ट मान्य हो.

onRestore() को लागू करते समय, आपको डेटा सेट में मौजूद सभी इकाइयों को दोहराने के लिए, data पर readNextHeader() को कॉल करना चाहिए. हर इकाई के लिए मिला है, तो ये काम करें:

  1. getKey() की मदद से, इकाई की कुंजी पाएं.
  2. इकाई कुंजी की तुलना, उन कुंजी वैल्यू की सूची से करें जिन्हें आपको अपनी BackupAgent क्लास में स्टैटिक फ़ाइनल स्ट्रिंग के तौर पर घोषित करना चाहिए. जब कुंजी, आपकी किसी जानी-पहचानी कुंजी स्ट्रिंग से मैच करती है, तो इकाई का डेटा निकालने और उसे डिवाइस में सेव करने के लिए स्टेटमेंट डालें:

    1. इसके साथ इकाई डेटा का आकार पाएं getDataSize() और उस साइज़ की बाइट अरे बनाएं.
    2. readEntityData() को कॉल करें और उसे बाइट कलेक्शन पास करें. यह वह जगह है जहां डेटा सेव होगा. साथ ही, शुरू करने के ऑफ़सेट और पढ़ने के साइज़ की जानकारी दें.
    3. आपका बाइट कलेक्शन अब भर गया है. डेटा पढ़ें और उसे डिवाइस पर लिखें जैसे आप चाहें.
  3. डिवाइस पर अपना डेटा वापस पढ़ने और लिखने के बाद, newState पैरामीटर में अपना डेटा उसी तरह से शामिल करना जैसा आप onBackup().

उदाहरण के लिए, पिछले सेक्शन में दिए गए उदाहरण के आधार पर, बैक अप लिए गए डेटा को वापस लाने का तरीका यहां बताया गया है:

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);
}

इस उदाहरण में, onRestore() में पास किए गए appVersionCode पैरामीटर का इस्तेमाल नहीं किया गया है. हालांकि, अगर आपने बैकअप लेने का विकल्प चुना है, तो हो सकता है कि आप इसका इस्तेमाल करना चाहें जब ऐप्लिकेशन का उपयोगकर्ता वर्शन वाकई में पीछे चला जाता है (उदाहरण के लिए, उपयोगकर्ता आपके ऐप्लिकेशन के 1.5 वर्शन से 1.0 पर चला गया है). ज़्यादा जानकारी के लिए, अगला सेक्शन देखें.

डेटा वापस लाने का वर्शन देखें

जब बैक अप मैनेजर आपके डेटा को क्लाउड स्टोरेज में सेव करता है, तब वह अपने-आप क्लाउड स्टोरेज में सेव हो जाता है में आपके ऐप्लिकेशन का वर्शन शामिल होता है, जैसा कि आपकी मेनिफ़ेस्ट फ़ाइल में बताया गया है android:versionCode एट्रिब्यूट की वैल्यू सबमिट करें. Backup Manager आपके डेटा को वापस लाने के लिए, बैकअप एजेंट को कॉल करने से पहले, इंस्टॉल किए गए ऐप्लिकेशन के android:versionCode को देखता है और उसकी तुलना, डेटा वापस लाने के लिए सेट किए गए डेटा से की जाती है. अगर पहले जैसा करने के लिए सेव किए गए डेटा में रिकॉर्ड किया गया वर्शन, डिवाइस पर मौजूद ऐप्लिकेशन के वर्शन से नया है, तो इसका मतलब है कि उपयोगकर्ता ने अपने ऐप्लिकेशन को डाउनग्रेड कर दिया है. इस मामले में, Backup Manager आपके ऐप्लिकेशन को पहले जैसा करने की प्रोसेस को रोक देगा और आपके onRestore() तरीके को कॉल नहीं करेगा. ऐसा इसलिए, क्योंकि पुराने वर्शन के लिए, पहले जैसा करने के लिए सेव किए गए डेटा का कोई मतलब नहीं है.

android:restoreAnyVersion एट्रिब्यूट की मदद से, इस व्यवहार को बदला जा सकता है. इस एट्रिब्यूट को true पर सेट करें, ताकि यह पता चल सके कि आपको ऐप्लिकेशन को पहले जैसा करना है, फिर चाहे वह सेट किए गए वर्शन पर हो या नहीं. डिफ़ॉल्ट वैल्यू false है. अगर आपको इसे true पर सेट करें, तो बैकअप मैनेजर android:versionCode और सभी मामलों में अपने onRestore() तरीके को कॉल करें. ऐसा करने पर, अपने onRestore() तरीके में वर्शन के अंतर की मैन्युअल तौर पर जांच की जा सकती है. साथ ही, अगर वर्शन मैच नहीं करते हैं, तो डेटा को काम करने लायक बनाने के लिए ज़रूरी कदम उठाए जा सकते हैं.

onRestore() तरीका, appVersionCode पैरामीटर के तौर पर, वापस लाने के लिए सेट किए गए डेटा में शामिल वर्शन कोड को पास करता है. इससे, डेटा को वापस लाने के दौरान अलग-अलग वर्शन को मैनेज करने में मदद मिलती है. इसके बाद, PackageInfo.versionCode फ़ील्ड की मदद से, ऐप्लिकेशन के मौजूदा वर्शन कोड के बारे में क्वेरी की जा सकती है. उदाहरण के लिए:

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;
}

इसके बाद, यहां से मिले version की तुलना करें PackageInfo से appVersionCode को onRestore() में पास किया गया.

बैकअप का अनुरोध करें

किसी भी समय dataChanged() पर कॉल करके, बैकअप कार्रवाई का अनुरोध किया जा सकता है. यह यह तरीका, बैकअप मैनेजर को सूचना देता है कि उसका इस्तेमाल करके, आपका बैकअप एजेंट है. इसके बाद, बैकअप मैनेजर आपके बैकअप एजेंट के onBackup() तरीके का इस्तेमाल करके, बैकअप लेता है. आम तौर पर, आपको डेटा में हर बार बदलाव होने पर (जैसे कि जब उपयोगकर्ता किसी ऐप्लिकेशन को बदलता है) चुनें, जिसका आप बैक अप लेना चाहते हैं. अगर Backup Manager आपके एजेंट से बैकअप का अनुरोध करने से पहले, dataChanged() को कई बार कॉल किया जाता है, तो भी आपके एजेंट को onBackup() पर सिर्फ़ एक कॉल मिलेगा.

डेटा वापस पाने का अनुरोध करना

ऐप्लिकेशन के सामान्य इस्तेमाल के दौरान, आपको डेटा को वापस लाने के लिए अनुरोध करने की ज़रूरत नहीं पड़ती. सिस्टम अपने-आप बैकअप डेटा की जांच करता है और ऐप्लिकेशन इंस्टॉल होने पर वापस लाएं.

ऑटो बैकअप पर माइग्रेट करना

अपने ऐप्लिकेशन को पूरे डेटा का बैकअप लेने की सुविधा चालू करें. ऐसा करने के लिए, android:fullBackupOnly मेनिफ़ेस्ट फ़ाइल में <application> एलिमेंट में true तक. Android 5.1 (एपीआई लेवल 22) या उससे पहले के वर्शन वाले डिवाइस पर चलने पर, आपका ऐप्लिकेशन मेनिफ़ेस्ट में मौजूद इस वैल्यू को अनदेखा कर देता है और कुंजी-वैल्यू के बैकअप लेना जारी रखता है. दौड़ते समय Android 6.0 (एपीआई लेवल 23) या उसके बाद के वर्शन वाले डिवाइस पर, आपका ऐप्लिकेशन अपने-आप काम करता है की-वैल्यू बैकअप के बजाय बैकअप.

उपयोगकर्ता की निजता

हम अच्छी तरह जानते हैं कि आपको हम पर भरोसा है और उपयोगकर्ताओं की निजता को सुरक्षित रखना हमारी ज़िम्मेदारी है. बैकअप लेने और डेटा वापस लाने की सुविधाएं देने के लिए, Google आपके बैकअप डेटा को सुरक्षित तरीके से Google के सर्वर पर भेजता है और वहां से वापस लाता है. Google के अनुसार, Google इस डेटा को निजी जानकारी मानता है. निजता नीति.

इसके अलावा, उपयोगकर्ता Android सिस्टम की बैकअप सेटिंग में जाकर, डेटा बैकअप की सुविधा बंद कर सकते हैं. जब कोई उपयोगकर्ता बैकअप लेने की सुविधा बंद करता है, तो Android Backup Service, सेव किए गए सभी बैकअप डेटा को मिटा देती है. उपयोगकर्ता, डिवाइस पर बैकअप की सुविधा को फिर से चालू कर सकता है. हालांकि, Android Backup Service, पहले मिटाए गए डेटा को वापस नहीं लाएगी.