If your Android application has a database and you want your users to be able to backup the database and restore it as they see fit, you’ll need to mess about with database files.
Below is a class called DbExportImport. Once you’ve set it up with the correct values, all you need to do is call exportDb(), importDb() or restoreDb() from your application to perform the necessary operations.
This is also useful as a temporary measure when changing your package name or key for application signing, as your application will be newly installed and you will lose your database.
I have only left in a few comments, so for any clarification, leave a comment and I’ll make it a little clearer.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 |
package testCode; import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; import java.nio.channels.FileChannel; import android.content.Context; import android.database.Cursor; import android.database.sqlite.SQLiteDatabase; import android.database.sqlite.SQLiteException; import android.os.Environment; import android.text.format.DateFormat; import android.util.Log; public class DbExportImport { public static final String TAG = DbExportImport.class.getName(); /** Directory that files are to be read from and written to **/ protected static final File DATABASE_DIRECTORY = new File(Environment.getExternalStorageDirectory(),"MyDirectory"); /** File path of Db to be imported **/ protected static final File IMPORT_FILE = new File(DATABASE_DIRECTORY,"MyDb.db"); public static final String PACKAGE_NAME = "com.example.app"; public static final String DATABASE_NAME = "example.db"; public static final String DATABASE_TABLE = "entryTable"; /** Contains: /data/data/com.example.app/databases/example.db **/ private static final File DATA_DIRECTORY_DATABASE = new File(Environment.getDataDirectory() + "/data/" + PACKAGE_NAME + "/databases/" + DATABASE_NAME ); /** Saves the application database to the * export directory under MyDb.db **/ protected static boolean exportDb(){ if( ! SdIsPresent() ) return false; File dbFile = DATA_DIRECTORY_DATABASE; String filename = "MyDb.db"; File exportDir = DATABASE_DIRECTORY; File file = new File(exportDir, filename); if (!exportDir.exists()) { exportDir.mkdirs(); } try { file.createNewFile(); copyFile(dbFile, file); return true; } catch (IOException e) { e.printStackTrace(); return false; } } /** Replaces current database with the IMPORT_FILE if * import database is valid and of the correct type **/ protected static boolean restoreDb(){ if( ! SdIsPresent() ) return false; File exportFile = DATA_DIRECTORY_DATABASE; File importFile = IMPORT_FILE; if( ! checkDbIsValid(importFile) ) return false; if (!importFile.exists()) { Log.d(TAG, "File does not exist"); return false; } try { exportFile.createNewFile(); copyFile(importFile, exportFile); return true; } catch (IOException e) { e.printStackTrace(); return false; } } /** Imports the file at IMPORT_FILE **/ protected static boolean importIntoDb(Context ctx){ if( ! SdIsPresent() ) return false; File importFile = IMPORT_FILE; if( ! checkDbIsValid(importFile) ) return false; try{ SQLiteDatabase sqlDb = SQLiteDatabase.openDatabase (importFile.getPath(), null, SQLiteDatabase.OPEN_READONLY); Cursor cursor = sqlDb.query(true, DATABASE_TABLE, null, null, null, null, null, null, null ); DbAdapter dbAdapter = new DbAdapter(ctx); dbAdapter.open(); final int titleColumn = cursor.getColumnIndexOrThrow("title"); final int timestampColumn = cursor.getColumnIndexOrThrow("timestamp"); // Adds all items in cursor to current database cursor.moveToPosition(-1); while(cursor.moveToNext()){ dbAdapter.createQuote( cursor.getString(titleColumn), cursor.getString(timestampColumn) ); } sqlDb.close(); cursor.close(); dbAdapter.close(); } catch( Exception e ){ e.printStackTrace(); return false; } return true; } /** Given an SQLite database file, this checks if the file * is a valid SQLite database and that it contains all the * columns represented by DbAdapter.ALL_COLUMN_KEYS **/ protected static boolean checkDbIsValid( File db ){ try{ SQLiteDatabase sqlDb = SQLiteDatabase.openDatabase (db.getPath(), null, SQLiteDatabase.OPEN_READONLY); Cursor cursor = sqlDb.query(true, DATABASE_TABLE, null, null, null, null, null, null, null ); // ALL_COLUMN_KEYS should be an array of keys of essential columns. // Throws exception if any column is missing for( String s : DbAdapter.ALL_COLUMN_KEYS ){ cursor.getColumnIndexOrThrow(s); } sqlDb.close(); cursor.close(); } catch( IllegalArgumentException e ) { Log.d(TAG, "Database valid but not the right type"); e.printStackTrace(); return false; } catch( SQLiteException e ) { Log.d(TAG, "Database file is invalid."); e.printStackTrace(); return false; } catch( Exception e){ Log.d(TAG, "checkDbIsValid encountered an exception"); e.printStackTrace(); return false; } return true; } private static void copyFile(File src, File dst) throws IOException { FileChannel inChannel = new FileInputStream(src).getChannel(); FileChannel outChannel = new FileOutputStream(dst).getChannel(); try { inChannel.transferTo(0, inChannel.size(), outChannel); } finally { if (inChannel != null) inChannel.close(); if (outChannel != null) outChannel.close(); } } /** Returns whether an SD card is present and writable **/ public static boolean SdIsPresent() { return Environment.getExternalStorageState().equals( Environment.MEDIA_MOUNTED); } } |