অ্যান্ড্রয়েড ব্যাকআপ পরিষেবা ক্লাউড স্টোরেজ ব্যাকআপ প্রদান করে এবং আপনার অ্যান্ড্রয়েড অ্যাপে মূল-মূল্যের ডেটা পুনরুদ্ধার করে। একটি মূল-মান ব্যাকআপ অপারেশন চলাকালীন, অ্যাপের ব্যাকআপ ডেটা ডিভাইসের ব্যাকআপ পরিবহনে পাঠানো হয়। ডিভাইসটি যদি ডিফল্ট Google ব্যাকআপ ট্রান্সপোর্ট ব্যবহার করে, তাহলে ডেটা সংরক্ষণের জন্য Android ব্যাকআপ পরিষেবাতে পাঠানো হয়।
আপনার অ্যাপের ব্যবহারকারী প্রতি 5MB ডেটা সীমাবদ্ধ। ব্যাকআপ ডেটা সংরক্ষণের জন্য কোন চার্জ নেই।
অ্যান্ড্রয়েডের ব্যাকআপ বিকল্পগুলির একটি ওভারভিউ এবং কোন ডেটা আপনার ব্যাক আপ এবং পুনরুদ্ধার করা উচিত সে সম্পর্কে নির্দেশিকা জন্য, ডেটা ব্যাকআপ ওভারভিউ দেখুন৷
কী-মান ব্যাকআপ প্রয়োগ করুন
আপনার অ্যাপ ডেটা ব্যাক আপ করতে, আপনাকে একটি ব্যাকআপ এজেন্ট প্রয়োগ করতে হবে৷ আপনার ব্যাকআপ এজেন্টকে ব্যাকআপ ম্যানেজার দ্বারা ব্যাকআপ এবং পুনরুদ্ধার উভয় সময়েই ডাকা হয়।
একটি ব্যাকআপ এজেন্ট বাস্তবায়ন করতে, আপনাকে অবশ্যই:
android:backupAgent
অ্যাট্রিবিউট সহ আপনার ম্যানিফেস্ট ফাইলে আপনার ব্যাকআপ এজেন্ট ঘোষণা করুন।নিম্নলিখিতগুলির মধ্যে একটি করে একটি ব্যাকআপ এজেন্টকে সংজ্ঞায়িত করুন:
BackupAgent
ক্লাস কেন্দ্রীয় ইন্টারফেস প্রদান করে যা আপনার অ্যাপ ব্যাকআপ ম্যানেজারের সাথে যোগাযোগ করতে ব্যবহার করে। আপনি যদি এই ক্লাসটি সরাসরি প্রসারিত করেন, তাহলে আপনাকে অবশ্যই ব্যাকআপ পরিচালনা করতে এবং আপনার ডেটার জন্য অপারেশন পুনরুদ্ধার করতেonBackup()
এবংonRestore()
ওভাররাইড করতে হবে।BackupAgentHelper
প্রসারিত করাBackupAgentHelper
ক্লাসBackupAgent
ক্লাসের চারপাশে একটি সুবিধাজনক মোড়ক প্রদান করে, আপনার লেখার জন্য প্রয়োজনীয় কোডের পরিমাণ কমিয়ে দেয়। আপনারBackupAgentHelper
এ, আপনাকে অবশ্যই এক বা একাধিক সাহায্যকারী বস্তু ব্যবহার করতে হবে, যা স্বয়ংক্রিয়ভাবে ব্যাক আপ করে এবং নির্দিষ্ট ধরণের ডেটা পুনরুদ্ধার করে, যাতে আপনাকেonBackup()
এবংonRestore()
প্রয়োগ করতে হবে না। আপনার অ্যাপের ব্যাকআপগুলির উপর আপনার সম্পূর্ণ নিয়ন্ত্রণের প্রয়োজন না হলে, আমরা আপনার অ্যাপের ব্যাকআপগুলি পরিচালনা করতেBackupAgentHelper
ব্যবহার করার পরামর্শ দিই।অ্যান্ড্রয়েড বর্তমানে ব্যাকআপ সাহায্যকারী সরবরাহ করে যেগুলি
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>
পুরানো ডিভাইসগুলিকে সমর্থন করার জন্য, আমরা আপনার Android ম্যানিফেস্ট ফাইলে API কী <meta-data>
যোগ করার পরামর্শ দিই। অ্যান্ড্রয়েড ব্যাকআপ পরিষেবার আর কোনও পরিষেবা কী প্রয়োজন নেই, তবে কিছু পুরানো ডিভাইস এখনও ব্যাক আপ করার সময় একটি কী পরীক্ষা করতে পারে৷ android:name
com.google.android.backup.api_key
তে এবং android:value
কে unused
এ সেট করুন।
android:restoreAnyVersion
বৈশিষ্ট্যটি ব্যাকআপ ডেটা তৈরি করা সংস্করণের তুলনায় বর্তমান অ্যাপ সংস্করণ নির্বিশেষে অ্যাপ ডেটা পুনরুদ্ধার করতে চান কিনা তা নির্দেশ করতে একটি বুলিয়ান মান নেয়। ডিফল্ট মান false
। আরও তথ্যের জন্য ডেটা পুনরুদ্ধার সংস্করণ দেখুন।
BackupAgentHelper প্রসারিত করুন
আপনি যদি SharedPreferences
বা অভ্যন্তরীণ স্টোরেজ থেকে সম্পূর্ণ ফাইল ব্যাক আপ করতে চান তাহলে BackupAgentHelper
ব্যবহার করে আপনার ব্যাকআপ এজেন্ট তৈরি করা উচিত। BackupAgentHelper
এর সাথে আপনার ব্যাকআপ এজেন্ট তৈরি করতে BackupAgent
প্রসারিত করার চেয়ে অনেক কম কোডের প্রয়োজন, কারণ আপনাকে onBackup()
এবং onRestore()
প্রয়োগ করতে হবে না।
আপনার BackupAgentHelper
বাস্তবায়নে এক বা একাধিক ব্যাকআপ সাহায্যকারী ব্যবহার করতে হবে। একটি ব্যাকআপ হেল্পার হল একটি বিশেষ উপাদান যা BackupAgentHelper
একটি নির্দিষ্ট ধরণের ডেটার জন্য ব্যাকআপ এবং ক্রিয়াকলাপগুলি পুনরুদ্ধার করতে আহ্বান করে৷ অ্যান্ড্রয়েড ফ্রেমওয়ার্ক বর্তমানে দুটি ভিন্ন সহায়ক প্রদান করে:
-
SharedPreferencesBackupHelper
SharedPreferences
ফাইল ব্যাক আপ করতে। - অভ্যন্তরীণ সঞ্চয়স্থান থেকে ফাইল ব্যাক আপ করতে
FileBackupHelper
.
আপনি আপনার BackupAgentHelper
এ একাধিক সাহায্যকারী অন্তর্ভুক্ত করতে পারেন, কিন্তু প্রতিটি ডেটা টাইপের জন্য শুধুমাত্র একজন সাহায্যকারী প্রয়োজন। অর্থাৎ, যদি আপনার একাধিক SharedPreferences
ফাইল থাকে, তাহলে আপনার শুধুমাত্র একটি SharedPreferencesBackupHelper
প্রয়োজন।
প্রতিটি সাহায্যকারীর জন্য আপনি আপনার BackupAgentHelper
এ যোগ করতে চান, আপনাকে আপনার onCreate()
পদ্ধতির সময় নিম্নলিখিতগুলি করতে হবে:
- পছন্দসই সাহায্যকারী শ্রেণীর একটি উদাহরণ তাত্ক্ষণিক করুন। ক্লাস কনস্ট্রাক্টরে, আপনি যে ফাইলটি ব্যাক আপ করতে চান তা অবশ্যই নির্দিষ্ট করতে হবে।
- আপনার
BackupAgentHelper
এ হেল্পার যোগ করতেaddHelper()
কল করুন।
নিম্নলিখিত বিভাগগুলি উপলব্ধ সাহায্যকারীদের প্রত্যেকটি ব্যবহার করে কীভাবে একটি ব্যাকআপ এজেন্ট তৈরি করতে হয় তা বর্ণনা করে৷
SharedPreferences ব্যাক আপ করুন
আপনি যখন একটি SharedPreferencesBackupHelper
ইনস্ট্যান্টিশিয়েট করেন, তখন আপনাকে অবশ্যই এক বা একাধিক SharedPreferences
ফাইলের নাম অন্তর্ভুক্ত করতে হবে।
উদাহরণ স্বরূপ, user_preferences
নামের একটি SharedPreferences
ফাইল ব্যাক আপ করার জন্য, BackupAgentHelper
ব্যবহার করে একটি সম্পূর্ণ ব্যাকআপ এজেন্ট দেখতে এইরকম:
কোটলিন
// 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) } } }
জাভা
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
ফাইল ব্যাক আপ এবং পুনরুদ্ধার করার জন্য প্রয়োজনীয় সমস্ত কোড অন্তর্ভুক্ত করে।
যখন ব্যাকআপ ম্যানেজার onBackup()
এবং onRestore()
কল করে, তখন BackupAgentHelper
আপনার ব্যাকআপ সাহায্যকারীদেরকে আপনার নির্দিষ্ট ফাইলগুলির ব্যাক আপ এবং পুনরুদ্ধার করার জন্য কল করে।
অন্যান্য ফাইল ব্যাক আপ
যখন আপনি একটি FileBackupHelper
ইনস্ট্যান্টিয়েট করেন, তখন আপনাকে অবশ্যই আপনার অ্যাপের অভ্যন্তরীণ সঞ্চয়স্থানে সংরক্ষিত এক বা একাধিক ফাইলের নাম অন্তর্ভুক্ত করতে হবে, যেমন getFilesDir()
দ্বারা নির্দিষ্ট করা হয়েছে, যেটি একই অবস্থান যেখানে openFileOutput()
ফাইলগুলি লেখে।
উদাহরণস্বরূপ, scores
এবং stats
নামের দুটি ফাইলের ব্যাক আপ করতে, BackupAgentHelper
ব্যবহার করে একটি ব্যাকআপ এজেন্ট এইরকম দেখায়:
কোটলিন
// 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) } } }
জাভা
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
আপনার অ্যাপের অভ্যন্তরীণ সঞ্চয়স্থানে সংরক্ষিত ফাইলগুলির ব্যাক আপ এবং পুনরুদ্ধার করার জন্য প্রয়োজনীয় সমস্ত কোড অন্তর্ভুক্ত করে৷
যাইহোক, অভ্যন্তরীণ সঞ্চয়স্থানে ফাইল পড়া এবং লেখা থ্রেড-নিরাপদ নয় । আপনার ব্যাকআপ এজেন্ট আপনার ক্রিয়াকলাপগুলির সাথে একই সময়ে আপনার ফাইলগুলি পড়তে বা লিখছে না তা নিশ্চিত করার জন্য, আপনি প্রতিবার পড়া বা লেখার সময় আপনাকে অবশ্যই সিঙ্ক্রোনাইজড বিবৃতি ব্যবহার করতে হবে। উদাহরণ স্বরূপ, যেকোন কার্যকলাপে যেখানে আপনি ফাইলটি পড়েন এবং লেখেন, আপনার সিঙ্ক্রোনাইজড বিবৃতিগুলির জন্য অন্তর্নিহিত লক হিসাবে ব্যবহার করার জন্য একটি বস্তুর প্রয়োজন:
কোটলিন
// Object for intrinsic lock companion object { val sDataLock = Any() }
জাভা
// Object for intrinsic lock static final Object sDataLock = new Object();
তারপর প্রতিবার যখন আপনি ফাইলগুলি পড়বেন বা লিখবেন তখন এই লক দিয়ে একটি সিঙ্ক্রোনাইজড স্টেটমেন্ট তৈরি করুন৷ উদাহরণস্বরূপ, একটি ফাইলে একটি গেমের সর্বশেষ স্কোর লেখার জন্য এখানে একটি সিঙ্ক্রোনাইজড বিবৃতি রয়েছে:
কোটলিন
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") }
জাভা
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
উদাহরণের নিম্নলিখিত পদ্ধতিগুলির প্রয়োজন:
কোটলিন
@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) } }
জাভা
@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 প্রসারিত করুন
বেশিরভাগ অ্যাপের সরাসরি BackupAgent
ক্লাস প্রসারিত করার দরকার নেই, কিন্তু এর পরিবর্তে বিল্ট-ইন হেল্পার ক্লাসের সুবিধা নিতে BackupAgentHelper
প্রসারিত করা উচিত যা স্বয়ংক্রিয়ভাবে আপনার ফাইলগুলির ব্যাক আপ এবং পুনরুদ্ধার করে। যাইহোক, আপনি নিম্নলিখিতগুলি করতে সরাসরি BackupAgent
প্রসারিত করতে পারেন:
- আপনার তথ্য বিন্যাস সংস্করণ. উদাহরণস্বরূপ, আপনি যে বিন্যাসে আপনার অ্যাপের ডেটা লেখেন সেটি সংশোধন করার প্রয়োজনীয়তা অনুমান করলে, আপনি একটি ব্যাকআপ এজেন্ট তৈরি করতে পারেন যাতে একটি পুনরুদ্ধার অপারেশন চলাকালীন আপনার অ্যাপের সংস্করণটি ক্রস-চেক করা যায় এবং ডিভাইসে সংস্করণটি হলে প্রয়োজনীয় কোনো সামঞ্জস্যপূর্ণ কাজ সম্পাদন করতে পারেন। ব্যাকআপ ডেটার চেয়ে আলাদা। আরও তথ্যের জন্য, ডেটা পুনরুদ্ধার সংস্করণ দেখুন।
- ব্যাক আপ করার জন্য ডেটার অংশগুলি নির্দিষ্ট করুন৷ একটি সম্পূর্ণ ফাইল ব্যাক আপ করার পরিবর্তে, আপনি ব্যাক আপ করার জন্য ডেটার অংশগুলি এবং কীভাবে প্রতিটি অংশ ডিভাইসে পুনরুদ্ধার করা হয় তা নির্দিষ্ট করতে পারেন৷ এটি আপনাকে বিভিন্ন সংস্করণ পরিচালনা করতেও সহায়তা করতে পারে, কারণ আপনি সম্পূর্ণ ফাইলের পরিবর্তে অনন্য সত্তা হিসাবে আপনার ডেটা পড়তে এবং লিখতে পারেন৷
- একটি ডাটাবেসে ডেটা ব্যাক আপ করুন। আপনার যদি একটি SQLite ডাটাবেস থাকে যা ব্যবহারকারী আপনার অ্যাপ পুনরায় ইনস্টল করার সময় আপনি পুনরুদ্ধার করতে চান, তাহলে আপনাকে একটি কাস্টম
BackupAgent
তৈরি করতে হবে যা ব্যাকআপ অপারেশনের সময় উপযুক্ত ডেটা পড়ে, তারপর আপনার টেবিল তৈরি করুন এবং একটি পুনরুদ্ধার অপারেশন চলাকালীন ডেটা সন্নিবেশ করুন৷
আপনার যদি উপরের কোনো কাজ করার প্রয়োজন না হয় এবং SharedPreferences
বা অভ্যন্তরীণ সঞ্চয়স্থান থেকে সম্পূর্ণ ফাইলের ব্যাকআপ নিতে চান, তাহলে Extending BackupAgentHelper
দেখুন।
প্রয়োজনীয় পদ্ধতি
যখন আপনি একটি BackupAgent
তৈরি করেন, আপনাকে অবশ্যই নিম্নলিখিত কলব্যাক পদ্ধতিগুলি প্রয়োগ করতে হবে:
-
onBackup()
- আপনি একটি ব্যাকআপ অনুরোধ করার পরে ব্যাকআপ ম্যানেজার এই পদ্ধতিটিকে কল করে৷ এই পদ্ধতিতে, আপনি ডিভাইস থেকে আপনার অ্যাপের ডেটা পড়েন এবং ব্যাকআপ ম্যানেজারে যে ডেটা ব্যাক আপ করতে চান তা পাস করেন, যেমন ব্যাক আপ সম্পাদন করুন ।
-
onRestore()
ব্যাকআপ ম্যানেজার একটি পুনরুদ্ধার অপারেশন চলাকালীন এই পদ্ধতিটিকে কল করে। এই পদ্ধতিটি আপনার ব্যাকআপ ডেটা সরবরাহ করে, যা আপনার অ্যাপটি তার পূর্বের অবস্থা পুনরুদ্ধার করতে ব্যবহার করতে পারে, যেমনটি পুনরুদ্ধার সম্পাদন করুন এ বর্ণিত।
ব্যবহারকারী যখন আপনার অ্যাপ পুনরায় ইনস্টল করেন তখন সিস্টেমটি যেকোনো ব্যাকআপ ডেটা পুনরুদ্ধার করতে এই পদ্ধতিটিকে কল করে, কিন্তু আপনার অ্যাপটি একটি পুনরুদ্ধারের অনুরোধও করতে পারে।
একটি ব্যাক আপ সঞ্চালন
একটি ব্যাকআপ অনুরোধের ফলে আপনার onBackup()
পদ্ধতিতে অবিলম্বে কল আসে না। পরিবর্তে, ব্যাকআপ ম্যানেজার একটি উপযুক্ত সময়ের জন্য অপেক্ষা করে, তারপরে শেষ ব্যাকআপ সঞ্চালিত হওয়ার পর থেকে ব্যাকআপের অনুরোধ করা সমস্ত অ্যাপগুলির জন্য একটি ব্যাকআপ সঞ্চালন করে৷ এটি সেই পয়েন্ট যেখানে আপনাকে অবশ্যই ব্যাকআপ ম্যানেজারকে আপনার অ্যাপ ডেটা প্রদান করতে হবে যাতে এটি ক্লাউড স্টোরেজে সংরক্ষণ করা যায়।
শুধুমাত্র ব্যাকআপ ম্যানেজার আপনার ব্যাকআপ এজেন্টের onBackup()
পদ্ধতিতে কল করতে পারেন। প্রতিবার যখন আপনার অ্যাপের ডেটা পরিবর্তিত হয় এবং আপনি একটি ব্যাকআপ করতে চান, আপনাকে অবশ্যই dataChanged()
কল করে একটি ব্যাকআপ অপারেশনের অনুরোধ করতে হবে। আরও তথ্যের জন্য একটি ব্যাকআপের অনুরোধ দেখুন।
টিপ : আপনার অ্যাপ ডেভেলপ করার সময়, আপনি bmgr
টুলের সাহায্যে ব্যাকআপ ম্যানেজার থেকে একটি তাৎক্ষণিক ব্যাকআপ অপারেশন শুরু করতে পারেন।
যখন ব্যাকআপ ম্যানেজার আপনার onBackup()
পদ্ধতিতে কল করে, তখন এটি তিনটি প্যারামিটার পাস করে:
-
oldState
- একটি খোলা, শুধুমাত্র পঠনযোগ্য
ParcelFileDescriptor
যা আপনার অ্যাপের দেওয়া শেষ ব্যাকআপ অবস্থার দিকে নির্দেশ করে। এটি ক্লাউড স্টোরেজ থেকে নেওয়া ব্যাকআপ ডেটা নয়, তবে সর্বশেষবারonBackup()
কল করার সময় ব্যাকআপ নেওয়া ডেটার একটি স্থানীয় উপস্থাপনা, যেমনnewState
বাonRestore()
দ্বারা সংজ্ঞায়িত করা হয়েছে।onRestore()
পরবর্তী বিভাগে কভার করা হয়েছে। যেহেতুonBackup()
আপনাকে ক্লাউড স্টোরেজে বিদ্যমান ব্যাকআপ ডেটা পড়ার অনুমতি দেয় না, আপনি শেষ ব্যাকআপের পর থেকে আপনার ডেটা পরিবর্তিত হয়েছে কিনা তা নির্ধারণ করতে এই স্থানীয় উপস্থাপনা ব্যবহার করতে পারেন। -
data
- একটি
BackupDataOutput
অবজেক্ট, যা আপনি ব্যাকআপ ম্যানেজারের কাছে আপনার ব্যাকআপ ডেটা সরবরাহ করতে ব্যবহার করেন। -
newState
- একটি খোলা, পড়া/লেখা
ParcelFileDescriptor
একটি ফাইলের দিকে নির্দেশ করে যেখানে আপনাকে অবশ্যই ডেটার একটি উপস্থাপনা লিখতে হবে যা আপনিdata
বিতরণ করেছেন৷ একটি উপস্থাপনা আপনার ফাইলের জন্য সর্বশেষ-সংশোধিত টাইমস্ট্যাম্পের মতো সহজ হতে পারে। পরের বার যখন ব্যাকআপ ম্যানেজার আপনারonBackup()
পদ্ধতিতে কল করবে তখন এই বস্তুটিoldState
হিসাবে ফেরত দেওয়া হবে। আপনি যদি আপনার ব্যাকআপ ডেটাnewState
এ না লেখেন, তাহলে পরের বার Backup ManageronBackup()
কল করলেoldState
একটি খালি ফাইলের দিকে নির্দেশ করবে।
এই পরামিতিগুলি ব্যবহার করে, নিম্নলিখিতগুলি করতে আপনার onBackup()
পদ্ধতিটি প্রয়োগ করুন:
আপনার বর্তমান ডেটার সাথে
oldState
তুলনা করে শেষ ব্যাকআপ থেকে আপনার ডেটা পরিবর্তিত হয়েছে কিনা তা পরীক্ষা করুন৷ আপনিoldState
কীভাবে ডেটা পড়েন তা নির্ভর করে আপনি কীভাবে এটিnewState
লিখেছেন (ধাপ 3 দেখুন)। একটি ফাইলের অবস্থা রেকর্ড করার সবচেয়ে সহজ উপায় হল এর শেষ-সংশোধিত টাইমস্ট্যাম্পের সাথে। উদাহরণস্বরূপ, এখানে আপনি কিভাবেoldState
থেকে একটি টাইমস্ট্যাম্প পড়তে এবং তুলনা করতে পারেন:কোটলিন
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 }
জাভা
// 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 }
যদি কিছুই পরিবর্তিত না হয় এবং আপনাকে ব্যাক আপ করার প্রয়োজন না হয়, তাহলে ধাপ 3 এ যান।
oldState
এর তুলনায় যদি আপনার ডেটা পরিবর্তিত হয়ে থাকে, তাহলে ক্লাউড স্টোরেজে ব্যাক আপ করতে বর্তমান ডেটাdata
লিখুন।আপনাকে
BackupDataOutput
এ একটি সত্তা হিসাবে ডেটার প্রতিটি অংশ লিখতে হবে। একটি সত্তা হল একটি সমতল বাইনারি ডেটা রেকর্ড যা একটি অনন্য কী স্ট্রিং দ্বারা চিহ্নিত করা হয়। সুতরাং, আপনি যে ডেটা সেটটি ব্যাক আপ করেন তা ধারণাগতভাবে কী-মান জোড়ার একটি সেট।আপনার ব্যাকআপ ডেটা সেটে একটি সত্তা যোগ করতে, আপনাকে অবশ্যই:
আপনি যে ডেটা লিখতে চলেছেন এবং ডেটা আকারের জন্য একটি অনন্য স্ট্রিং কী পাস করে
writeEntityHeader()
কল করুন।writeEntityData()
কল করুন, একটি বাইট বাফার পাস করে যাতে আপনার ডেটা এবং বাফার থেকে লেখার জন্য বাইটের সংখ্যা থাকে, যাwriteEntityHeader()
এ পাস করা আকারের সাথে মেলে।
উদাহরণস্বরূপ, নিম্নলিখিত কোডটি একটি বাইট স্ট্রীমে কিছু ডেটা সমতল করে এবং এটিকে একটি একক সত্তায় লেখে:
কোটলিন
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) }
জাভা
// 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);
আপনি ব্যাক আপ করতে চান এমন প্রতিটি ডেটার জন্য এটি সম্পাদন করুন। আপনি কীভাবে আপনার ডেটা সত্তায় ভাগ করবেন তা আপনার উপর নির্ভর করে। আপনি এমনকি শুধুমাত্র একটি সত্তা ব্যবহার করতে পারেন.
আপনি ব্যাকআপ করুন বা না করুন (ধাপে 2),
newState
ParcelFileDescriptor
এ বর্তমান ডেটার একটি উপস্থাপনা লিখুন। ব্যাকআপ ম্যানেজার বর্তমানে ব্যাক আপ করা ডেটার উপস্থাপনা হিসাবে এই বস্তুটিকে স্থানীয়ভাবে ধরে রাখে। পরের বার যখন এটিonBackup()
কল করে তখন এটি আপনার কাছে এটিকেoldState
হিসাবে ফিরিয়ে দেয় যাতে আপনি নির্ধারণ করতে পারেন যে অন্য একটি ব্যাকআপ প্রয়োজনীয় কিনা, যেমন ধাপ 1 এ পরিচালিত হয়েছে। আপনি যদি এই ফাইলটিতে বর্তমান ডেটার অবস্থা না লেখেন, তাহলেoldState
হবে পরবর্তী কলব্যাকের সময় খালি।নিম্নলিখিত উদাহরণটি ফাইলের সর্বশেষ-সংশোধিত টাইমস্ট্যাম্প ব্যবহার করে
newState
স্টেটে বর্তমান ডেটার একটি উপস্থাপনা সংরক্ষণ করে:কোটলিন
val modified = dataFile.lastModified() FileOutputStream(newState.fileDescriptor).also { DataOutputStream(it).apply { writeLong(modified) } }
জাভা
FileOutputStream outstream = new FileOutputStream(newState.getFileDescriptor()); DataOutputStream out = new DataOutputStream(outstream); long modified = dataFile.lastModified(); out.writeLong(modified);
একটি পুনরুদ্ধার সঞ্চালন
যখন আপনার অ্যাপ ডেটা পুনরুদ্ধার করার সময় হয়, তখন ব্যাকআপ ম্যানেজার আপনার ব্যাকআপ এজেন্টের onRestore()
পদ্ধতিতে কল করে৷ যখন এটি এই পদ্ধতিতে কল করে, তখন ব্যাকআপ ম্যানেজার আপনার ব্যাকআপ ডেটা সরবরাহ করে যাতে আপনি এটিকে ডিভাইসে পুনরুদ্ধার করতে পারেন।
শুধুমাত্র ব্যাকআপ ম্যানেজার onRestore()
কল করতে পারে, যা স্বয়ংক্রিয়ভাবে ঘটে যখন সিস্টেম আপনার অ্যাপ ইনস্টল করে এবং বিদ্যমান ব্যাকআপ ডেটা খুঁজে পায়।
যখন ব্যাকআপ ম্যানেজার আপনার onRestore()
পদ্ধতিতে কল করে, তখন এটি তিনটি পরামিতি পাস করে:
-
data
- একটি
BackupDataInput
অবজেক্ট, যা আপনাকে আপনার ব্যাকআপ ডেটা পড়তে দেয়। -
appVersionCode
- একটি পূর্ণসংখ্যা যা আপনার অ্যাপের
android:versionCode
ম্যানিফেস্ট অ্যাট্রিবিউটের মানকে উপস্থাপন করে, যেমনটি এই ডেটা ব্যাক আপ করার সময় ছিল৷ আপনি বর্তমান অ্যাপ সংস্করণ ক্রস-চেক করতে এবং ডেটা বিন্যাসটি সামঞ্জস্যপূর্ণ কিনা তা নির্ধারণ করতে এটি ব্যবহার করতে পারেন। ডেটা পুনরুদ্ধার করার বিভিন্ন সংস্করণ পরিচালনা করতে এটি ব্যবহার করার বিষয়ে আরও তথ্যের জন্য, ডেটা পুনরুদ্ধার সংস্করণ দেখুন দেখুন। -
newState
- একটি খোলা, পড়া/লিখুন
ParcelFileDescriptor
একটি ফাইলের দিকে নির্দেশ করে যেখানে আপনাকে অবশ্যই চূড়ান্ত ব্যাকআপ স্থিতি লিখতে হবে যাdata
দিয়ে দেওয়া হয়েছিল। পরের বার যখনonBackup()
কল করা হয় তখন এই অবজেক্টটিoldState
হিসাবে ফিরে আসে। মনে রাখবেন যে আপনাকে অবশ্যইonBackup()
কলব্যাকে একইnewState
অবজেক্ট লিখতে হবে—এছাড়াও এখানে এটি করা নিশ্চিত করে যেonBackup()
কে দেওয়াoldState
অবজেক্টটি বৈধ এমনকি ডিভাইসটি পুনরুদ্ধার করার পরে প্রথমবারonBackup()
কল করার পরেও।
আপনার onRestore()
এর বাস্তবায়নে, আপনাকে ডেটা সেটের সমস্ত সত্তার মাধ্যমে পুনরাবৃত্তি করতে data
readNextHeader()
কল করতে হবে। পাওয়া প্রতিটি সত্তার জন্য, নিম্নলিখিতগুলি করুন:
-
getKey()
দিয়ে সত্তা কী পান। আপনার
BackupAgent
ক্লাসের মধ্যে স্ট্যাটিক চূড়ান্ত স্ট্রিং হিসাবে ঘোষণা করা উচিত ছিল এমন পরিচিত কী মানগুলির একটি তালিকার সাথে সত্তা কী তুলনা করুন। যখন কীটি আপনার পরিচিত কী স্ট্রিংগুলির একটির সাথে মেলে, সত্তা ডেটা বের করতে এবং ডিভাইসে সংরক্ষণ করতে একটি বিবৃতিতে প্রবেশ করুন:-
getDataSize()
দিয়ে সত্তা ডেটার আকার পান এবং সেই আকারের একটি বাইট অ্যারে তৈরি করুন। -
readEntityData()
কল করুন এবং এটিকে বাইট অ্যারে পাস করুন, যেখানে ডেটা যাবে এবং স্টার্ট অফসেট এবং পড়ার আকার নির্দিষ্ট করুন। - আপনার বাইট অ্যারে এখন পূর্ণ। ডেটা পড়ুন এবং আপনার পছন্দ মতো ডিভাইসে লিখুন।
-
আপনি ডিভাইসে আপনার ডেটা পড়ার এবং লেখার পরে,
newState
প্যারামিটারে আপনার ডেটার অবস্থা লিখুন যেমন আপনিonBackup()
সময় করেন।
উদাহরণস্বরূপ, পূর্ববর্তী বিভাগে উদাহরণ দ্বারা ব্যাক আপ করা ডেটা কীভাবে আপনি পুনরুদ্ধার করতে পারেন তা এখানে:
কোটলিন
@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) } } }
জাভা
@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
বৈশিষ্ট্য দ্বারা সংজ্ঞায়িত করা হয়েছে। ব্যাকআপ ম্যানেজার আপনার ডেটা পুনরুদ্ধার করতে আপনার ব্যাকআপ এজেন্টকে কল করার আগে, এটি ইনস্টল করা অ্যাপের android:versionCode
দেখে এবং পুনরুদ্ধার ডেটা সেটে রেকর্ড করা মানের সাথে তুলনা করে। যদি পুনরুদ্ধার ডেটা সেটে রেকর্ড করা সংস্করণটি ডিভাইসের অ্যাপ সংস্করণের চেয়ে নতুন হয়, তাহলে ব্যবহারকারী তাদের অ্যাপটি ডাউনগ্রেড করেছেন। এই ক্ষেত্রে, ব্যাকআপ ম্যানেজার আপনার অ্যাপের জন্য পুনরুদ্ধার অপারেশন বাতিল করবে এবং আপনার onRestore()
পদ্ধতিতে কল করবে না, কারণ পুনরুদ্ধার সেটটি পুরানো সংস্করণের জন্য অর্থহীন বলে মনে করা হয়।
আপনি android:restoreAnyVersion
অ্যাট্রিবিউট দিয়ে এই আচরণটিকে ওভাররাইড করতে পারেন। পুনরুদ্ধার সেট সংস্করণ নির্বিশেষে আপনি অ্যাপটি পুনরুদ্ধার করতে চান তা নির্দেশ করতে এই বৈশিষ্ট্যটিকে true
সেট করুন৷ ডিফল্ট মান false
। আপনি যদি এটি true
সেট করেন তবে ব্যাকআপ ম্যানেজার android:versionCode
উপেক্ষা করবে এবং সমস্ত ক্ষেত্রে আপনার onRestore()
পদ্ধতিতে কল করবে। এটি করার মাধ্যমে, আপনি আপনার onRestore()
পদ্ধতিতে সংস্করণের পার্থক্যটি ম্যানুয়ালি পরীক্ষা করতে পারেন এবং সংস্করণগুলি না মিললে ডেটা সামঞ্জস্যপূর্ণ করার জন্য প্রয়োজনীয় যেকোনো পদক্ষেপ নিতে পারেন।
একটি পুনরুদ্ধার ক্রিয়াকলাপের সময় আপনাকে বিভিন্ন সংস্করণ পরিচালনা করতে সহায়তা করার জন্য, onRestore()
পদ্ধতিটি আপনাকে appVersionCode
প্যারামিটার হিসাবে পুনরুদ্ধার ডেটা সেটের সাথে অন্তর্ভুক্ত সংস্করণ কোড পাস করে। তারপর আপনি PackageInfo.versionCode
ফিল্ডের সাথে বর্তমান অ্যাপের সংস্করণ কোড জিজ্ঞাসা করতে পারেন। যেমন:
কোটলিন
val info: PackageInfo? = try { packageManager.getPackageInfo(packageName, 0) } catch (e: PackageManager.NameNotFoundException) { null } val version: Int = info?.versionCode ?: 0
জাভা
PackageInfo info; try { String name = getPackageName(); info = getPackageManager().getPackageInfo(name, 0); } catch (NameNotFoundException nnfe) { info = null; } int version; if (info != null) { version = info.versionCode; }
তারপরে PackageInfo
থেকে অর্জিত version
onRestore()
এ পাস করা appVersionCode
এর সাথে তুলনা করুন।
একটি ব্যাকআপ অনুরোধ
আপনি যে কোনো সময় dataChanged()
কল করে একটি ব্যাকআপ অপারেশনের অনুরোধ করতে পারেন। এই পদ্ধতিটি ব্যাকআপ ম্যানেজারকে অবহিত করে যে আপনি আপনার ব্যাকআপ এজেন্ট ব্যবহার করে আপনার ডেটা ব্যাক আপ করতে চান৷ ব্যাকআপ ম্যানেজার তখন ভবিষ্যতে আপনার ব্যাকআপ এজেন্টের onBackup()
পদ্ধতিতে কল করবে। সাধারণত, প্রতিবার আপনার ডেটা পরিবর্তন করার সময় আপনার একটি ব্যাকআপের অনুরোধ করা উচিত (যেমন যখন ব্যবহারকারী একটি অ্যাপ পছন্দ পরিবর্তন করে যা আপনি ব্যাক আপ করতে চান)। ব্যাকআপ ম্যানেজার আপনার এজেন্টের কাছ থেকে একটি ব্যাকআপের অনুরোধ করার আগে আপনি যদি dataChanged()
বেশ কয়েকবার কল করেন, তবে আপনার এজেন্ট এখনও onBackup()
এ মাত্র একটি কল পাবেন।
একটি পুনরুদ্ধার অনুরোধ
আপনার অ্যাপের স্বাভাবিক জীবন চলাকালীন, আপনাকে পুনরুদ্ধার অপারেশনের অনুরোধ করার দরকার নেই। সিস্টেম স্বয়ংক্রিয়ভাবে ব্যাকআপ ডেটা পরীক্ষা করে এবং যখন আপনার অ্যাপ ইনস্টল করা হয় তখন পুনরুদ্ধার করে।
স্বতঃ ব্যাকআপে স্থানান্তর করুন৷
আপনি ম্যানিফেস্ট ফাইলের <application>
উপাদানে android:fullBackupOnly
true
সেট করে আপনার অ্যাপটিকে সম্পূর্ণ-ডেটা ব্যাকআপে রূপান্তর করতে পারেন। Android 5.1 (API লেভেল 22) বা তার নিচের একটি ডিভাইসে চলার সময়, আপনার অ্যাপ ম্যানিফেস্টে এই মানটিকে উপেক্ষা করে এবং কী-মান ব্যাকআপ করা চালিয়ে যায়। Android 6.0 (API লেভেল 23) বা উচ্চতর ডিভাইসে চললে, আপনার অ্যাপ কী-মান ব্যাকআপের পরিবর্তে অটো ব্যাকআপ করে।
ব্যবহারকারীর গোপনীয়তা
Google-এ, ব্যবহারকারীরা আমাদের উপর যে আস্থা রাখে এবং ব্যবহারকারীদের গোপনীয়তা রক্ষা করার জন্য আমাদের দায়িত্ব সম্পর্কে আমরা গভীরভাবে সচেতন। ব্যাকআপ প্রদান এবং বৈশিষ্ট্য পুনরুদ্ধার করার জন্য Google নিরাপদে Google সার্ভারে এবং থেকে ব্যাকআপ ডেটা প্রেরণ করে। Google এই ডেটাকে Google-এর গোপনীয়তা নীতি অনুসারে ব্যক্তিগত তথ্য হিসাবে বিবেচনা করে৷
এছাড়াও, ব্যবহারকারীরা অ্যান্ড্রয়েড সিস্টেমের ব্যাকআপ সেটিংসের মাধ্যমে ডেটা ব্যাকআপ কার্যকারিতা অক্ষম করতে পারেন। যখন একজন ব্যবহারকারী ব্যাকআপ অক্ষম করে, তখন Android ব্যাকআপ পরিষেবা সমস্ত সংরক্ষিত ব্যাকআপ ডেটা মুছে ফেলে৷ একজন ব্যবহারকারী ডিভাইসে ব্যাকআপ পুনরায় সক্ষম করতে পারেন, তবে Android ব্যাকআপ পরিষেবা পূর্বে মুছে ফেলা ডেটা পুনরুদ্ধার করবে না।