My solution neither uses any third-party library nor forces you to call custom methods on SQLiteOpenHelper
subclass to initialize the database on creation. It also takes care of database upgrades as well. All that needs to be done is to subclass SQLiteOpenHelper
.
android_metadata
with an attribute locale
having the value en_US
in addition to the tables unique to your app.SQLiteOpenHelper
:SQLiteOpenHelper
.private
method within the SQLiteOpenHelper
subclass. This method contains the logic to copy database contents from the database file in the 'assets' folder to the database created in the application package context.onCreate
, onUpgrade
and onOpen
methods of SQLiteOpenHelper
.Enough said. Here goes the SQLiteOpenHelper
subclass:
public class PlanDetailsSQLiteOpenHelper extends SQLiteOpenHelper {
private static final String TAG = "SQLiteOpenHelper";
private final Context context;
private static final int DATABASE_VERSION = 1;
private static final String DATABASE_NAME = "my_custom_db";
private boolean createDb = false, upgradeDb = false;
public PlanDetailsSQLiteOpenHelper(Context context) {
super(context, DATABASE_NAME, null, DATABASE_VERSION);
this.context = context;
}
/**
* Copy packaged database from assets folder to the database created in the
* application package context.
*
* @param db
* The target database in the application package context.
*/
private void copyDatabaseFromAssets(SQLiteDatabase db) {
Log.i(TAG, "copyDatabase");
InputStream myInput = null;
OutputStream myOutput = null;
try {
// Open db packaged as asset as the input stream
myInput = context.getAssets().open("path/to/shipped/db/file");
// Open the db in the application package context:
myOutput = new FileOutputStream(db.getPath());
// Transfer db file contents:
byte[] buffer = new byte[1024];
int length;
while ((length = myInput.read(buffer)) > 0) {
myOutput.write(buffer, 0, length);
}
myOutput.flush();
// Set the version of the copied database to the current
// version:
SQLiteDatabase copiedDb = context.openOrCreateDatabase(
DATABASE_NAME, 0, null);
copiedDb.execSQL("PRAGMA user_version = " + DATABASE_VERSION);
copiedDb.close();
} catch (IOException e) {
e.printStackTrace();
throw new Error(TAG + " Error copying database");
} finally {
// Close the streams
try {
if (myOutput != null) {
myOutput.close();
}
if (myInput != null) {
myInput.close();
}
} catch (IOException e) {
e.printStackTrace();
throw new Error(TAG + " Error closing streams");
}
}
}
@Override
public void onCreate(SQLiteDatabase db) {
Log.i(TAG, "onCreate db");
createDb = true;
}
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
Log.i(TAG, "onUpgrade db");
upgradeDb = true;
}
@Override
public void onOpen(SQLiteDatabase db) {
Log.i(TAG, "onOpen db");
if (createDb) {// The db in the application package
// context is being created.
// So copy the contents from the db
// file packaged in the assets
// folder:
createDb = false;
copyDatabaseFromAssets(db);
}
if (upgradeDb) {// The db in the application package
// context is being upgraded from a lower to a higher version.
upgradeDb = false;
// Your db upgrade logic here:
}
}
}
Finally, to get a database connection, just call getReadableDatabase()
or getWritableDatabase()
on the SQLiteOpenHelper
subclass and it will take care of creating a db, copying db contents from the specified file in the 'assets' folder, if the database does not exist.
In short, you can use the SQLiteOpenHelper
subclass to access the db shipped in the assets folder just as you would use for a database that is initialized using SQL queries in the onCreate()
method.