Saya telah menerapkan BackupAgentHelper
menggunakan yang disediakan FileBackupHelper
untuk membuat cadangan dan memulihkan database asli yang saya miliki. Ini adalah database yang biasanya Anda gunakan bersama ContentProviders
dan yang berada di dalamnya /data/data/yourpackage/databases/
.
Orang akan mengira ini adalah kasus yang umum. Namun dokumen tersebut tidak menjelaskan apa yang harus dilakukan: http://developer.android.com/guide/topics/data/backup.html . Tidak ada BackupHelper
database khusus untuk tipikal ini. Oleh karena itu saya menggunakanFileBackupHelper
, mengarahkannya ke file .db saya di " /databases/
", memperkenalkan kunci di sekitar operasi db (seperti db.insert
) di my ContentProviders
, dan bahkan mencoba membuat /databases/
direktori " " sebelumnya onRestore()
karena tidak ada setelah instalasi.
Saya telah menerapkan solusi serupa untuk SharedPreferences
berhasil di aplikasi yang berbeda di masa lalu. Namun ketika saya menguji implementasi baru saya di emulator-2.2, saya melihat backup sedang dilakukan ke LocalTransport
dari log, serta pemulihan sedang dilakukan (dan onRestore()
dipanggil). Namun, file db itu sendiri tidak pernah dibuat.
Perhatikan bahwa ini semua setelah penginstalan, dan sebelum peluncuran pertama aplikasi, setelah pemulihan dilakukan. Selain itu, strategi pengujian saya didasarkan pada http://developer.android.com/guide/topics/data/backup.html#Testing .
Harap perhatikan juga bahwa saya tidak berbicara tentang beberapa database sqlite yang saya kelola sendiri, atau tentang mencadangkan ke SDcard, server sendiri, atau di tempat lain.
Saya memang melihat penyebutan di dokumen tentang database yang menyarankan untuk menggunakan kustom BackupAgent
tetapi tampaknya tidak terkait:
Namun, Anda mungkin ingin memperluas BackupAgent secara langsung jika Anda perlu: * Mencadangkan data dalam database. Jika Anda memiliki database SQLite yang ingin Anda pulihkan saat pengguna menginstal ulang aplikasi Anda, Anda perlu membuat BackupAgent kustom yang membaca data yang sesuai selama operasi pencadangan, kemudian membuat tabel dan memasukkan data tersebut selama operasi pemulihan.
Mohon kejelasannya.
Jika saya benar-benar perlu melakukannya sendiri hingga level SQL, maka saya khawatir tentang topik berikut:
Buka database dan transaksi. Saya tidak tahu cara menutupnya dari kelas tunggal di luar alur kerja aplikasi saya.
Cara memberi tahu pengguna bahwa cadangan sedang berlangsung dan database terkunci. Mungkin butuh waktu lama, jadi saya mungkin perlu menampilkan bilah kemajuan.
Cara melakukan hal yang sama pada pemulihan. Seperti yang saya pahami, pemulihan mungkin terjadi tepat ketika pengguna sudah mulai menggunakan aplikasi (dan memasukkan data ke dalam database). Jadi Anda tidak bisa berasumsi untuk hanya mengembalikan data yang dicadangkan di tempatnya (menghapus data kosong atau lama). Anda harus entah bagaimana bergabung dengannya, yang tidak mungkin untuk database non-sepele karena id.
Cara menyegarkan aplikasi setelah pemulihan selesai tanpa membuat pengguna terjebak di beberapa titik - yang sekarang - tidak dapat dijangkau.
Dapatkah saya memastikan bahwa database telah diupgrade saat melakukan backup atau restore? Jika tidak, skema yang diharapkan mungkin tidak cocok.
Jawaban:
Pendekatan yang lebih bersih adalah membuat kustom
BackupHelper
:public class DbBackupHelper extends FileBackupHelper { public DbBackupHelper(Context ctx, String dbName) { super(ctx, ctx.getDatabasePath(dbName).getAbsolutePath()); } }
lalu tambahkan ke
BackupAgentHelper
:public void onCreate() { addHelper(DATABASE, new DbBackupHelper(this, DB.FILE)); }
sumber
Setelah meninjau kembali pertanyaan saya, saya bisa membuatnya berfungsi setelah melihat bagaimana ConnectBot melakukannya . Terima kasih Kenny dan Jeffrey!
Ini sebenarnya semudah menambahkan:
FileBackupHelper hosts = new FileBackupHelper(this, "../databases/" + HostDatabase.DB_NAME); addHelper(HostDatabase.DB_NAME, hosts);
untuk Anda
BackupAgentHelper
.Hal yang saya lewatkan adalah kenyataan bahwa Anda harus menggunakan jalur relatif dengan "
../databases/
".Namun, ini bukanlah solusi yang sempurna. Dokumen tersebut
FileBackupHelper
misalnya: "FileBackupHelper
harus digunakan hanya dengan file konfigurasi kecil, bukan file biner besar. ", Yang terakhir adalah kasus dengan database SQLite.Saya ingin mendapatkan lebih banyak saran, wawasan tentang apa yang diharapkan dari kita (apa solusi yang tepat), dan saran tentang bagaimana ini bisa rusak.
sumber
db.open()
melaluidb.close()
atau hanyainsert
pernyataan atau apa.Berikut cara yang lebih bersih untuk mem-backup database sebagai file. Tidak ada jalur hardcode.
class MyBackupAgent extends BackupAgentHelper{ private static final String DB_NAME = "my_db"; @Override public void onCreate(){ FileBackupHelper dbs = new FileBackupHelper(this, DB_NAME); addHelper("dbs", dbs); } @Override public File getFilesDir(){ File path = getDatabasePath(DB_NAME); return path.getParentFile(); } }
Catatan: ini menggantikan getFilesDir sehingga FileBackupHelper bekerja di database dir, bukan file dir.
Petunjuk lain: Anda juga dapat menggunakan databaseList untuk mendapatkan semua nama DB dan feed Anda dari daftar ini (tanpa jalur induk) ke FileBackupHelper. Kemudian semua DB aplikasi akan disimpan dalam cadangan.
sumber
Menggunakan
FileBackupHelper
untuk mencadangkan / memulihkan db sqlite menimbulkan beberapa pertanyaan serius:1. Apa yang terjadi jika aplikasi menggunakan kursor yang diambil dari
ContentProvider.query()
dan agen pencadangan mencoba menimpa seluruh file?2. Tautan adalah contoh bagus dari pengujian sempurna (entropi rendah;). Anda menghapus aplikasi, menginstalnya lagi dan cadangan dipulihkan. Bagaimanapun hidup bisa menjadi brutal. Lihat tautannya . Bayangkan skenario ketika pengguna membeli perangkat baru. Karena tidak memiliki set sendiri, agen backup menggunakan set perangkat lain. Aplikasi diinstal dan backupHelper Anda mengambil file lama dengan skema versi db yang lebih rendah dari yang sekarang.
SQLiteOpenHelper
panggilanonDowngrade
dengan implementasi default:public void onDowngrade(SQLiteDatabase db, int oldVersion, int newVersion) { throw new SQLiteException("Can't downgrade database from version " + oldVersion + " to " + newVersion); }
Apa pun yang dilakukan pengguna, dia tidak dapat menggunakan aplikasi Anda di perangkat baru.
Saya sarankan menggunakan
ContentResolver
untuk mendapatkan data -> serialize (tanpa_id
s) untuk backup dan deserialize -> masukkan data untuk restore.Catatan: mendapatkan / memasukkan data dilakukan melalui ContentResolver sehingga menghindari masalah cuncurrency. Serialisasi dilakukan di backupAgent Anda. Jika Anda membuat kursor <-> pemetaan objek Anda sendiri, membuat serial item bisa semudah mengimplementasikan
Serializable
dengantransient
field _id pada kelas yang mewakili entitas Anda.Saya juga akan menggunakan
ContentProviderOperation
contoh insert massal danCursorLoader.setUpdateThrottle
agar aplikasi tidak terjebak dengan restart loader pada perubahan data selama proses pemulihan cadangan.Jika Anda kebetulan berada dalam situasi penurunan, Anda dapat memilih untuk membatalkan pemulihan data atau memulihkan dan memperbarui ContentResolver dengan bidang yang relevan dengan versi yang diturunkan.
Saya setuju bahwa subjeknya tidak mudah, tidak dijelaskan dengan baik di dokumen dan beberapa pertanyaan masih tetap seperti ukuran data massal dll.
Semoga ini membantu.
sumber
Mulai Android M, sekarang ada API pencadangan / pemulihan data lengkap yang tersedia untuk aplikasi. API baru ini menyertakan spesifikasi berbasis XML dalam manifes aplikasi yang memungkinkan pengembang menjelaskan file mana yang akan dicadangkan dengan cara semantik langsung: 'cadangkan database yang disebut "mydata.db"'. API baru ini jauh lebih mudah digunakan oleh pengembang - Anda tidak perlu melacak diff atau meminta izin cadangan secara eksplisit, dan deskripsi XML tentang file mana yang akan dicadangkan berarti Anda sering tidak perlu menulis kode apa pun sama sekali.
(Anda dapat terlibat bahkan dalam operasi pencadangan / pemulihan data lengkap untuk mendapatkan panggilan balik saat pemulihan terjadi, misalnya. Dengan cara itu fleksibel.)
Lihat Mengonfigurasi Auto Backup untuk Aplikasi di developer.android.com untuk mengetahui deskripsi tentang cara menggunakan API baru.
sumber
Salah satu opsinya adalah membangunnya dalam logika aplikasi di atas database. Saya pikir itu benar-benar berteriak untuk levell seperti itu. Tidak yakin apakah Anda sudah melakukannya, tetapi kebanyakan orang (meskipun ada pendekatan kursor pengelola konten android) akan memperkenalkan beberapa pemetaan ORM - baik pendekatan kustom atau pendekatan orm-lite. Dan apa yang saya lebih suka lakukan dalam kasus ini adalah:
Jadi dalam hal ini daripada melakukannya pada level db, lakukanlah pada level aplikasi.
sumber