[アンドロイド] データベースtrongのアンドロイド – P5のバックアップとインポート
Androidのデータベースに書き込まれたシリーズのように、新しいでたらめに対する今日忙しい数日. ある程度 5, また、最後の部分は私がどのようにアンドロイドでのバックアップおよびインポートデータベースにご案内します.
コンテンツ
ステップ 1: AndroidManifest.xmlに、メモリカードにデータを読み書きできるよう
<?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="cachhoc.net.tut.demodatabase" > <!-- set can read and write on sd card--> <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /> <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" /> <application android:allowBackup="true" android:icon="@mipmap/ic_launcher" android:label="@string/app_name" android:theme="@style/AppTheme" > <activity android:name=".MainActivity" android:label="@string/app_name" > <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> <activity android:name=".NoteActivity" android:label="@string/title_activity_note" > </activity> </application> </manifest>
キャップニャットファイルmenu_main.xml – ファイルメニューのCUA MainActivity
<menu xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools" tools:context=".MainActivity"> <item android:id="@+id/menu_more" android:icon="@drawable/ic_more" android:title="Menu" app:showAsAction="always"> <menu> <item android:id="@+id/menu_backup" android:orderInCategory="100" android:title="@string/backup_data" app:showAsAction="never" /> <item android:id="@+id/menu_import" android:orderInCategory="100" android:title="@string/import_data" app:showAsAction="never" /> </menu> </item> </menu>
あなた自身は、上記しています 1 アイテム – こちらの商品は、ボタンです 3 ドット (オーバーフロー). あなたは、ボタンをクリックします 3 ドットが表示されます 2 メニューバックアップVAインポート (ビデオを見ます) あります 2 その中のアイテム.
イベントメニューをキャッチするMainActivity.javaファイルのアップデート:
package cachhoc.net.tut.demodatabase; import android.content.Context; import android.content.Intent; import android.os.Bundle; import android.support.v7.app.AppCompatActivity; import android.support.v7.widget.LinearLayoutManager; import android.support.v7.widget.RecyclerView; import android.view.Menu; import android.view.MenuItem; import android.view.View; import android.widget.Toast; import java.util.ArrayList; import java.util.List; public class MainActivity extends AppCompatActivity implements View.OnClickListener, BackupData.OnBackupListener { private ItemNoteAdapter adapter; private List<Note> listNote = new ArrayList<>(); private Context context; private DatabaseHelper db; private BackupData backupData; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); context = this; db = new DatabaseHelper(context); backupData = new BackupData(context); backupData.setOnBackupListener(this); connectView(); } /** * connect java with xml view */ private void connectView() { // find Float Action Button findViewById(R.id.fab).setOnClickListener(this); RecyclerView recyclerView = (RecyclerView) findViewById(R.id.rv_note); // If the size of views will not change as the data changes. recyclerView.setHasFixedSize(true); // Setting the LayoutManager. RecyclerView.LayoutManager layoutManager = new LinearLayoutManager(this); recyclerView.setLayoutManager(layoutManager); // Setting the adapter. adapter = new ItemNoteAdapter(context, listNote); recyclerView.setAdapter(adapter); } /** * update list note when resume (open app or finish NoteActivity) */ public void onResume() { super.onResume(); updateListNote(); } /** * select all note from database and set to ls * use for loop to add into listNote. * We must add all item in ls into listNote then adapter can update * we add reverse ls to show new note at top of list */ private void updateListNote() { // clear old list listNote.clear(); // add all notes from database, reverse list ArrayList<Note> ls = db.getListNote("SELECT * FROM " + DatabaseHelper.TABLE_NOTE); // reverse list for (int i = ls.size() - 1; i >= 0; i--) { listNote.add(ls.get(i)); } adapter.notifyDataSetChanged(); } /** * display note have id */ public static void showNote(Context context, long id) { Intent intent = new Intent(context, NoteActivity.class); // send id to NoteActivity intent.putExtra(NoteActivity.ID, id); context.startActivity(intent); } @Override public void onClick(View v) { switch (v.getId()) { case R.id.fab: showNote(context, NoteActivity.NEW_NOTE); break; default: break; } } @Override public boolean onCreateOptionsMenu(Menu menu) { getMenuInflater().inflate(R.menu.menu_main, menu); return true; } @Override public boolean onOptionsItemSelected(MenuItem item) { switch (item.getItemId()) { case R.id.menu_backup: backupData.exportToSD(); break; case R.id.menu_import: backupData.importFromSD(); break; default: break; } return super.onOptionsItemSelected(item); } @Override public void onFinishExport(String error) { String notify = error; if (error == null) { notify = "Export success"; } Toast.makeText(context, notify, Toast.LENGTH_SHORT).show(); } @Override public void onFinishImport(String error) { String notify = error; if (error == null) { notify = "Import success"; updateListNote(); } Toast.makeText(context, notify, Toast.LENGTH_SHORT).show(); } }
あなたは、私が持っている注意してください インタフェースBackupData.OnBackupListenerを実装 クラスBACKUPDATAで (それ以降に記述します) とオーバーライド 2 メソッド onFinishExport と onFinishImport その, 2 この方法は、私たちは、通知を処理することを可能にするか、バックアップとインポートが完成行った後、.
イベントコールメニューを開始すると 2 メソッド backupData.exportToSD と backupData.importFromSD 実行する.
ステップ 3: ライト級BACKUPDATAを行います
先に説明した彼女のステップで. ユーザーがBACKUPDATAを選択すると、我々は、特定のフォルダに配置されたメモリカードにデータをバックアップします, これだけでは、フォルダに保存されました MyNote. それが存在しない場合、プログラムは自動的にこのフォルダを作成します. バックアップファイルの名前は、日付、時間とともに、データベースの名前になります, 最初のビデオのポストとして時間分秒.
ユーザーは、インポートデータを選択すると、, インポートする前に既存のデータをバックアップする場合、私たちは要求されます. もしそうであれば、バックアップしてからインポートする以前のバックアップファイルを一覧表示. それ以外の場合は、ファイルのみをリストのみをインポートします.
データの損失を回避し、新しい構造やや古いデータと既存のデータの場合にエラーを回避するには, 我々は、既存のデータのすべてのレコードを削除した後、一時的なデータベースにバックアップファイルをコピーします (一時データベース) し、現在のデータにテーブルと一時databseでレコード全体をコピーします. たとえば、現在のデータ·テーブル·ノート, このテーブルの列は、LAST_MODIFIEDその古いdatabseでありません, 一方場合は、直接コピーしたデータベースにつながるとのlast_modifiedカラム不良のアプリケーションを持っていません.
ここでは、コードが比較的明確に説明されました. あなたが読むことができます.
package cachhoc.net.tut.demodatabase; import android.app.ProgressDialog; import android.content.Context; import android.content.DialogInterface; import android.database.Cursor; import android.database.sqlite.SQLiteDatabase; import android.os.AsyncTask; import android.os.Environment; import android.support.v4.app.FragmentActivity; import android.support.v7.app.AlertDialog; import android.view.LayoutInflater; import android.view.View; import android.widget.AdapterView; import android.widget.AdapterView.OnItemClickListener; import android.widget.ArrayAdapter; import android.widget.ListView; import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; import java.nio.channels.FileChannel; import java.text.SimpleDateFormat; import java.util.Date; public class BackupData { // url for database private final String dataPath = "//data//cachhoc.net.tut.demodatabase//databases//"; // name of main data private final String dataName = DatabaseHelper.DATABASE_NAME; // data main private final String data = dataPath + dataName; // name of temp data private final String dataTempName = DatabaseHelper.DATABASE_NAME + "_temp"; // temp data for copy data from sd then copy data temp into main data private final String dataTemp = dataPath + dataTempName; // folder on sd to backup data private final String folderSD = Environment.getExternalStorageDirectory() + "/MyNote"; private Context context; public BackupData(Context context) { this.context = context; } // create folder if it not exist private void createFolder() { File sd = new File(folderSD); if (!sd.exists()) { sd.mkdir(); System.out.println("create folder"); } else { System.out.println("exits"); } } /** * Copy database to sd card * name of file = database name + time when copy * When finish, we call onFinishExport method to send notify for activity */ public void exportToSD() { String error = null; try { createFolder(); File sd = new File(folderSD); if (sd.canWrite()) { SimpleDateFormat formatTime = new SimpleDateFormat("yyyy_MM_dd__HH_mm_ss"); String backupDBPath = dataName + "_" + formatTime.format(new Date()); File currentDB = new File(Environment.getDataDirectory(), data); File backupDB = new File(sd, backupDBPath); if (currentDB.exists()) { FileChannel src = new FileInputStream(currentDB).getChannel(); FileChannel dst = new FileOutputStream(backupDB).getChannel(); dst.transferFrom(src, 0, src.size()); src.close(); dst.close(); } else { System.out.println("db not exist"); } } } catch (Exception e) { e.printStackTrace(); error = "Error backup"; } onBackupListener.onFinishExport(error); } /** * import data from file backup on sd card * we must create a temp database for copy file on sd card to it. * Then we copy all row of temp database into main database. * It will keep struct of curren database not change when struct backup database is old * * @param fileNameOnSD name of file database backup on sd card */ public void importData(String fileNameOnSD) { File sd = new File(folderSD); // create temp database SQLiteDatabase dbBackup = context.openOrCreateDatabase(dataTempName, SQLiteDatabase.CREATE_IF_NECESSARY, null); String error = null; if (sd.canWrite()) { File currentDB = new File(Environment.getDataDirectory(), dataTemp); File backupDB = new File(sd, fileNameOnSD); if (currentDB.exists()) { FileChannel src; try { src = new FileInputStream(backupDB).getChannel(); FileChannel dst = new FileOutputStream(currentDB) .getChannel(); dst.transferFrom(src, 0, src.size()); src.close(); dst.close(); } catch (FileNotFoundException e) { e.printStackTrace(); error = "Error load file"; } catch (IOException e) { error = "Error import"; } } } /** *when copy old database into temp database success * we copy all row of table into main database */ if (error == null) { new CopyDataAsyncTask(dbBackup).execute(); } else { onBackupListener.onFinishImport(error); } } /** * show dialog for select backup database before import database * if user select yes, we will export curren database * then show dialog to select old database to import * else we onoly show dialog to select old database to import */ public void importFromSD() { final AlertDialog.Builder builder = new AlertDialog.Builder(context, R.style.AppCompatAlertDialogStyle); builder.setTitle(R.string.backup_data).setIcon(R.mipmap.ic_launcher) .setMessage(R.string.backup_before_import); builder.setPositiveButton(R.string.no, new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { showDialogListFile(folderSD); } }); builder.setNegativeButton(R.string.yes, new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { showDialogListFile(folderSD); exportToSD(); } }); builder.show(); } /** * show dialog list all backup file on sd card * @param forderPath folder conatain backup file */ private void showDialogListFile(String forderPath) { createFolder(); File forder = new File(forderPath); File[] listFile = forder.listFiles(); final String[] listFileName = new String[listFile.length]; for (int i = 0, j = listFile.length - 1; i < listFile.length; i++, j--) { listFileName[j] = listFile[i].getName(); } if (listFileName.length > 0) { // get layout for list LayoutInflater inflater = ((FragmentActivity) context).getLayoutInflater(); View convertView = (View) inflater.inflate(R.layout.list_backup_file, null); final AlertDialog.Builder builder = new AlertDialog.Builder(context, R.style.AppCompatAlertDialogStyle); // set view for dialog builder.setView(convertView); builder.setTitle(R.string.select_file).setIcon(R.mipmap.ic_launcher); final AlertDialog alert = builder.create(); ListView lv = (ListView) convertView.findViewById(R.id.lv_backup); ArrayAdapter<String> adapter = new ArrayAdapter<String>(context, android.R.layout.simple_list_item_1, listFileName); lv.setAdapter(adapter); lv.setOnItemClickListener(new OnItemClickListener() { @Override public void onItemClick(AdapterView<?> parent, View view, int position, long id) { alert.dismiss(); importData(listFileName[position]); } }); alert.show(); } else { final AlertDialog.Builder builder = new AlertDialog.Builder(context, R.style.AppCompatAlertDialogStyle); builder.setTitle(R.string.delete).setIcon(R.mipmap.ic_launcher) .setMessage(R.string.backup_empty); builder.show(); } } /** * AsyncTask for copy data */ class CopyDataAsyncTask extends AsyncTask<Void, Void, Void> { ProgressDialog progress = new ProgressDialog(context); SQLiteDatabase db; public CopyDataAsyncTask(SQLiteDatabase dbBackup) { this.db = dbBackup; } /** * will call first */ @Override protected void onPreExecute() { // TODO Auto-generated method stub super.onPreExecute(); progress.setMessage("Importing..."); progress.show(); } @Override protected Void doInBackground(Void... params) { copyData(db); return null; } /** * end process */ @Override protected void onPostExecute(Void error) { // TODO Auto-generated method stub super.onPostExecute(error); if (progress.isShowing()) { progress.dismiss(); } onBackupListener.onFinishImport(null); } } /** * copy all row of temp database into main database * @param dbBackup */ private void copyData(SQLiteDatabase dbBackup) { DatabaseHelper db = new DatabaseHelper(context); db.deleteNote(null); /** copy all row of subject table */ Cursor cursor = dbBackup.query(true, DatabaseHelper.TABLE_NOTE, null, null, null, null, null, null, null); cursor.moveToFirst(); while (!cursor.isAfterLast()) { Note note = db.cursorToNote(cursor); db.insertNote(note); cursor.moveToNext(); } cursor.close(); context.deleteDatabase(dataTempName); } private OnBackupListener onBackupListener; public void setOnBackupListener(OnBackupListener onBackupListener) { this.onBackupListener = onBackupListener; } public interface OnBackupListener { public void onFinishExport(String error); public void onFinishImport(String error); } }
あなたは注意が必要になります 2 次の:
- データベースAsyncTaskをインポートするためのその使用このプロセスは、長い時間がかかる場合がありますので、. これは、ショーを助けます 1 ユーザを示すダイアログがどのユーザーがアプリケーションを凍結していると考えられていない心強いかのように処理され、.
-
コピー中, 私はコマンドを求めています 注注= db.cursorToNote(カーソル); クラスのcursorToNote前回の注文や民間DatabaseHelper, あなたは今すぐしたいです 公共の修理 NHE.
ファイルのリストをインポートするためのインタフェース
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical"> <ListView android:id="@+id/lv_backup" android:layout_width="match_parent" android:layout_height="match_parent"> </ListView> </LinearLayout>
ファイルstring.xmlを指定でいくつかの変更
<resources> <string name="app_name">My Note</string> <string name="hello_world">Hello world!</string> <string name="action_settings">Settings</string> <string name="add">Add</string> <string name="delete">Delete</string> <string name="save">Save</string> <string name="yes">Yes</string> <string name="no">No</string> <string name="backup_data">Backup data</string> <string name="import_data">Import data</string> <string name="backup_before_import">Do you want backup curren database before import an old databas?</string> <string name="select_file">Select file</string> <string name="backup_empty">Backup file is empty</string> <!-- --> <string name="title_note">Title note</string> <string name="content">Content</string> <string name="title_activity_note">Create Note</string> </resources>
あなたはできます ここではソースコードをダウンロード.
それはそれだ. 私はあなたに良い学習を希望します.
チュートリアルで行われた投稿 データベースtrongのアンドロイド によって nguyenvanquan7826
こんにちは陸軍,
まず、データベースが非常に便利なAndroidの一連のを見つけました.
私は、最初の部分にあなたの指導の下、再びコードを試してみました 5 バックアップとインポート. しかし、私は、バックアップおよびインポートではありません失敗しません, 私は、コードを数回チェックしましたが、どこにエラーを見つけることができませんでした.
日食で自分のコード, ここにあなたのソースコードです. 私はあなたが私がバグを修正するのに役立つ願っています. あなたは、ライブラリプロジェクトをインポートして、エラーメッセージがビルドさになるまで、プロジェクトが再び失敗し再起動した場合.
http://www.mediafire.com/download/jq14bp7dw4poe0a/SQLite_Demo.rar
おかげで軍事!
あなたが得るのを助けるために、この新しいテストの数日申し訳ありませんが、あまりにも忙しいです.
あなたが会います 2 エラー:
– 書き込み文字列テーブル作成エラー:
あなたはKEY_LAST_MODIFIED_NOTEを追加すると、レコードが追加されることはありませんので、あなたは、新しいインストールのTEXT DEFAULTにスペースがありません.
– 間違ったラインによって、バックアップのエラー:
あなたは、データベースからコピーされていないテーブルTABLE_NOTEからコピーする必要があります.
修理:
私のためにエラーがbackupdata.javaであります
この行で
SQLiteDatabase DBBACKUP = context.openOrCreateDatabase(dataTempName,
SQLiteDatabase.CREATE_IF_NECESSARY, ヌル);
エラーとは何ですか? あなたはここでエラーを投稿したり、写真を撮ることができます?
こんにちは,
あなたは、AndroidのバージョンへのGradleを更新することができますしてください 3. 私は、新しいバージョンで古いプログラムを実行すると、あまりにも多くの問題を抱えています. 私は、変更を行う方法を理解していないので、初心者です. 私はオンラインのすべてを試み, 助けは何もありません.
レポートのためにありがとうございました. 私のチュートリアルのこのプロジェクトは、あなたと古いバージョンを使用します. あなたは私にあなたの問題を伝えることができます?
あなたは例のバックアップを行うとルーム永続化ライブラリを使用して復元することができ? 私はルーム永続ライブラリを使用するには、この機能を適応困難を抱えています
プライベートボイドのCopyData(SQLiteDatabase DBBACKUP) {
DatabaseHelperデシベル=新しいDatabaseHelper(コンテキスト);
db.deleteNote(ヌル);
/** 対象テーブルのすべての行をコピーします */
カーソルcursor = dbBackup.query(真, DatabaseHelper.TABLE_NOTE, ヌル, ヌル, ヌル, ヌル, ヌル, ヌル, ヌル);
cursor.moveToFirst();
同時に (!cursor.isAfterLast()) {
注注= db.cursorToNote(カーソル);
db.insertNote(注意);
cursor.moveToNext();
}
cursor.close();
context.deleteDatabase(dataTempName);
}
こんにちは, それについては申し訳ありません, 私は、このライブラリを使用していません, 私はそれを作るために知りません.
こんにちは,
私はあなたのコードを使用してバックアップを作成しています. getExternalStorageDirectory以降() 廃止されました. 以下の書き方 .
private final String folderSD = Environment.getExternalStorageDirectory() + “/MyNote”;
おかげで,
こんにちは, あなたはここで見ることができます: https://stackoverflow.com/questions/57116335/environment-getexternalstoragedirectory-deprecated-in-api-level-29-java