Android SQLite ErrorCopyingDataBase Error
I'm need help. I have an existing database and I want to copy that from assets to my device, but I only end up getting this error:
java.lang.Error: ErrorCopyingDataBase
at com.example.maas.databaseapplication.DatabaseHelper.createDataBase(DatabaseHelper.java:66)
Where line 66 is the throw clause in code below which is linked with copyDataBase().
public class DatabaseHelper extends SQLiteAssetHelper {
private static String TAG = "DataBaseHelper"; // Tag just for the LogCat window
//destination path (location) of our database on device
private static String DB_PATH = "";
private static String DB_NAME ="NewDatabase1.db";// Database name
private SQLiteDatabase mDataBase;
private final Context mContext;
public Cursor data1;
public DatabaseHelper(Context context) {
super(context, DB_NAME, null, 1);// 1? Its database Version
this.mContext = context;
if(android.os.Build.VERSION.SDK_INT >= 17){
DB_PATH = Environment.getDataDirectory() + "/data/" + mContext.getPackageName() + "/databases/";
}
else
{
DB_PATH = "/data/data/" + context.getPackageName() + "/databases/";
}
}
public void createDataBase() throws IOException
{
//If the database does not exist, copy it from the assets.
boolean mDataBaseExist = checkDataBase();
if(!mDataBaseExist)
{
this.getReadableDatabase();
this.close();
try
{
//Copy the database from assests
copyDataBase();
Log.e(TAG, "createDatabase database created");
}
catch (IOException mIOException)
{
throw new Error("ErrorCopyingDataBase");
}
}
}
//Check that the database exists here: /data/data/your package/databases/Da Name
private boolean checkDataBase()
{
File dbFile = new File(DB_PATH + DB_NAME);
return dbFile.exists();
}
//Copy the database from assets
private void copyDataBase() throws IOException
{
InputStream mInput = mContext.getAssets().open(DB_NAME);
String outFileName = DB_PATH + DB_NAME;
OutputStream mOutput = new FileOutputStream(outFileName);
byte mBuffer = new byte[1024];
int mLength;
while ((mLength = mInput.read(mBuffer))>0)
{
mOutput.write(mBuffer, 0, mLength);
}
mOutput.flush();
mOutput.close();
mInput.close();
}
//Open the database, so we can query it
public boolean openDataBase() throws SQLException
{
String mPath = DB_PATH + DB_NAME;
//Log.v("mPath", mPath);
mDataBase = SQLiteDatabase.openDatabase(mPath, null, SQLiteDatabase.CREATE_IF_NECESSARY);
//mDataBase = SQLiteDatabase.openDatabase(mPath, null, SQLiteDatabase.NO_LOCALIZED_COLLATORS);
return mDataBase != null;
}
@Override
public synchronized void close()
{
if(mDataBase != null)
mDataBase.close();
super.close();
}
I have the
<uses-permission android:name="androidx.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="androidx.permission.READ_EXTERNAL_STORAGE" />
permissions in my manifest. Can someone please help me? I have tried different database-adapters, but none seem to be working.
I have applied the methods presented in Android : Error Copying database (Sqliite) From Asset Folder . It did NOT solve my problem, if it solved my problem I would not have made a new thread.
java android database sqlite
add a comment |
I'm need help. I have an existing database and I want to copy that from assets to my device, but I only end up getting this error:
java.lang.Error: ErrorCopyingDataBase
at com.example.maas.databaseapplication.DatabaseHelper.createDataBase(DatabaseHelper.java:66)
Where line 66 is the throw clause in code below which is linked with copyDataBase().
public class DatabaseHelper extends SQLiteAssetHelper {
private static String TAG = "DataBaseHelper"; // Tag just for the LogCat window
//destination path (location) of our database on device
private static String DB_PATH = "";
private static String DB_NAME ="NewDatabase1.db";// Database name
private SQLiteDatabase mDataBase;
private final Context mContext;
public Cursor data1;
public DatabaseHelper(Context context) {
super(context, DB_NAME, null, 1);// 1? Its database Version
this.mContext = context;
if(android.os.Build.VERSION.SDK_INT >= 17){
DB_PATH = Environment.getDataDirectory() + "/data/" + mContext.getPackageName() + "/databases/";
}
else
{
DB_PATH = "/data/data/" + context.getPackageName() + "/databases/";
}
}
public void createDataBase() throws IOException
{
//If the database does not exist, copy it from the assets.
boolean mDataBaseExist = checkDataBase();
if(!mDataBaseExist)
{
this.getReadableDatabase();
this.close();
try
{
//Copy the database from assests
copyDataBase();
Log.e(TAG, "createDatabase database created");
}
catch (IOException mIOException)
{
throw new Error("ErrorCopyingDataBase");
}
}
}
//Check that the database exists here: /data/data/your package/databases/Da Name
private boolean checkDataBase()
{
File dbFile = new File(DB_PATH + DB_NAME);
return dbFile.exists();
}
//Copy the database from assets
private void copyDataBase() throws IOException
{
InputStream mInput = mContext.getAssets().open(DB_NAME);
String outFileName = DB_PATH + DB_NAME;
OutputStream mOutput = new FileOutputStream(outFileName);
byte mBuffer = new byte[1024];
int mLength;
while ((mLength = mInput.read(mBuffer))>0)
{
mOutput.write(mBuffer, 0, mLength);
}
mOutput.flush();
mOutput.close();
mInput.close();
}
//Open the database, so we can query it
public boolean openDataBase() throws SQLException
{
String mPath = DB_PATH + DB_NAME;
//Log.v("mPath", mPath);
mDataBase = SQLiteDatabase.openDatabase(mPath, null, SQLiteDatabase.CREATE_IF_NECESSARY);
//mDataBase = SQLiteDatabase.openDatabase(mPath, null, SQLiteDatabase.NO_LOCALIZED_COLLATORS);
return mDataBase != null;
}
@Override
public synchronized void close()
{
if(mDataBase != null)
mDataBase.close();
super.close();
}
I have the
<uses-permission android:name="androidx.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="androidx.permission.READ_EXTERNAL_STORAGE" />
permissions in my manifest. Can someone please help me? I have tried different database-adapters, but none seem to be working.
I have applied the methods presented in Android : Error Copying database (Sqliite) From Asset Folder . It did NOT solve my problem, if it solved my problem I would not have made a new thread.
java android database sqlite
Possible duplicate of Android : Error Copying database (Sqliite) From Asset Folder
– Lekr0
Nov 21 '18 at 15:11
It is not a duplicate since the presented soulutions in that topic already is in my code. Please see my first post.
– Ulrich_Peters
Nov 21 '18 at 15:20
add a comment |
I'm need help. I have an existing database and I want to copy that from assets to my device, but I only end up getting this error:
java.lang.Error: ErrorCopyingDataBase
at com.example.maas.databaseapplication.DatabaseHelper.createDataBase(DatabaseHelper.java:66)
Where line 66 is the throw clause in code below which is linked with copyDataBase().
public class DatabaseHelper extends SQLiteAssetHelper {
private static String TAG = "DataBaseHelper"; // Tag just for the LogCat window
//destination path (location) of our database on device
private static String DB_PATH = "";
private static String DB_NAME ="NewDatabase1.db";// Database name
private SQLiteDatabase mDataBase;
private final Context mContext;
public Cursor data1;
public DatabaseHelper(Context context) {
super(context, DB_NAME, null, 1);// 1? Its database Version
this.mContext = context;
if(android.os.Build.VERSION.SDK_INT >= 17){
DB_PATH = Environment.getDataDirectory() + "/data/" + mContext.getPackageName() + "/databases/";
}
else
{
DB_PATH = "/data/data/" + context.getPackageName() + "/databases/";
}
}
public void createDataBase() throws IOException
{
//If the database does not exist, copy it from the assets.
boolean mDataBaseExist = checkDataBase();
if(!mDataBaseExist)
{
this.getReadableDatabase();
this.close();
try
{
//Copy the database from assests
copyDataBase();
Log.e(TAG, "createDatabase database created");
}
catch (IOException mIOException)
{
throw new Error("ErrorCopyingDataBase");
}
}
}
//Check that the database exists here: /data/data/your package/databases/Da Name
private boolean checkDataBase()
{
File dbFile = new File(DB_PATH + DB_NAME);
return dbFile.exists();
}
//Copy the database from assets
private void copyDataBase() throws IOException
{
InputStream mInput = mContext.getAssets().open(DB_NAME);
String outFileName = DB_PATH + DB_NAME;
OutputStream mOutput = new FileOutputStream(outFileName);
byte mBuffer = new byte[1024];
int mLength;
while ((mLength = mInput.read(mBuffer))>0)
{
mOutput.write(mBuffer, 0, mLength);
}
mOutput.flush();
mOutput.close();
mInput.close();
}
//Open the database, so we can query it
public boolean openDataBase() throws SQLException
{
String mPath = DB_PATH + DB_NAME;
//Log.v("mPath", mPath);
mDataBase = SQLiteDatabase.openDatabase(mPath, null, SQLiteDatabase.CREATE_IF_NECESSARY);
//mDataBase = SQLiteDatabase.openDatabase(mPath, null, SQLiteDatabase.NO_LOCALIZED_COLLATORS);
return mDataBase != null;
}
@Override
public synchronized void close()
{
if(mDataBase != null)
mDataBase.close();
super.close();
}
I have the
<uses-permission android:name="androidx.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="androidx.permission.READ_EXTERNAL_STORAGE" />
permissions in my manifest. Can someone please help me? I have tried different database-adapters, but none seem to be working.
I have applied the methods presented in Android : Error Copying database (Sqliite) From Asset Folder . It did NOT solve my problem, if it solved my problem I would not have made a new thread.
java android database sqlite
I'm need help. I have an existing database and I want to copy that from assets to my device, but I only end up getting this error:
java.lang.Error: ErrorCopyingDataBase
at com.example.maas.databaseapplication.DatabaseHelper.createDataBase(DatabaseHelper.java:66)
Where line 66 is the throw clause in code below which is linked with copyDataBase().
public class DatabaseHelper extends SQLiteAssetHelper {
private static String TAG = "DataBaseHelper"; // Tag just for the LogCat window
//destination path (location) of our database on device
private static String DB_PATH = "";
private static String DB_NAME ="NewDatabase1.db";// Database name
private SQLiteDatabase mDataBase;
private final Context mContext;
public Cursor data1;
public DatabaseHelper(Context context) {
super(context, DB_NAME, null, 1);// 1? Its database Version
this.mContext = context;
if(android.os.Build.VERSION.SDK_INT >= 17){
DB_PATH = Environment.getDataDirectory() + "/data/" + mContext.getPackageName() + "/databases/";
}
else
{
DB_PATH = "/data/data/" + context.getPackageName() + "/databases/";
}
}
public void createDataBase() throws IOException
{
//If the database does not exist, copy it from the assets.
boolean mDataBaseExist = checkDataBase();
if(!mDataBaseExist)
{
this.getReadableDatabase();
this.close();
try
{
//Copy the database from assests
copyDataBase();
Log.e(TAG, "createDatabase database created");
}
catch (IOException mIOException)
{
throw new Error("ErrorCopyingDataBase");
}
}
}
//Check that the database exists here: /data/data/your package/databases/Da Name
private boolean checkDataBase()
{
File dbFile = new File(DB_PATH + DB_NAME);
return dbFile.exists();
}
//Copy the database from assets
private void copyDataBase() throws IOException
{
InputStream mInput = mContext.getAssets().open(DB_NAME);
String outFileName = DB_PATH + DB_NAME;
OutputStream mOutput = new FileOutputStream(outFileName);
byte mBuffer = new byte[1024];
int mLength;
while ((mLength = mInput.read(mBuffer))>0)
{
mOutput.write(mBuffer, 0, mLength);
}
mOutput.flush();
mOutput.close();
mInput.close();
}
//Open the database, so we can query it
public boolean openDataBase() throws SQLException
{
String mPath = DB_PATH + DB_NAME;
//Log.v("mPath", mPath);
mDataBase = SQLiteDatabase.openDatabase(mPath, null, SQLiteDatabase.CREATE_IF_NECESSARY);
//mDataBase = SQLiteDatabase.openDatabase(mPath, null, SQLiteDatabase.NO_LOCALIZED_COLLATORS);
return mDataBase != null;
}
@Override
public synchronized void close()
{
if(mDataBase != null)
mDataBase.close();
super.close();
}
I have the
<uses-permission android:name="androidx.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="androidx.permission.READ_EXTERNAL_STORAGE" />
permissions in my manifest. Can someone please help me? I have tried different database-adapters, but none seem to be working.
I have applied the methods presented in Android : Error Copying database (Sqliite) From Asset Folder . It did NOT solve my problem, if it solved my problem I would not have made a new thread.
java android database sqlite
java android database sqlite
edited Nov 21 '18 at 15:25
Ulrich_Peters
asked Nov 21 '18 at 14:57
Ulrich_PetersUlrich_Peters
52
52
Possible duplicate of Android : Error Copying database (Sqliite) From Asset Folder
– Lekr0
Nov 21 '18 at 15:11
It is not a duplicate since the presented soulutions in that topic already is in my code. Please see my first post.
– Ulrich_Peters
Nov 21 '18 at 15:20
add a comment |
Possible duplicate of Android : Error Copying database (Sqliite) From Asset Folder
– Lekr0
Nov 21 '18 at 15:11
It is not a duplicate since the presented soulutions in that topic already is in my code. Please see my first post.
– Ulrich_Peters
Nov 21 '18 at 15:20
Possible duplicate of Android : Error Copying database (Sqliite) From Asset Folder
– Lekr0
Nov 21 '18 at 15:11
Possible duplicate of Android : Error Copying database (Sqliite) From Asset Folder
– Lekr0
Nov 21 '18 at 15:11
It is not a duplicate since the presented soulutions in that topic already is in my code. Please see my first post.
– Ulrich_Peters
Nov 21 '18 at 15:20
It is not a duplicate since the presented soulutions in that topic already is in my code. Please see my first post.
– Ulrich_Peters
Nov 21 '18 at 15:20
add a comment |
2 Answers
2
active
oldest
votes
The problem with the code you have is that numerous exceptions are caught by using throws IOException
and then you just issue a generic exception.
Whilst there could be a number of underlying causes.
It could be that asset itself doesn't exist where it's expected (in the assets folder (e.g. not in the databases directory (SQLiteAssetHelper uses this directory))).
It could be that the databases folder, within the package doesn't exist (use mkdirs on the DB_PATH). e.g. have something like :-
private boolean checkDatabase {
File db = new File(mContext.getDatabasePath(DB_NAME).getPath());
if(db.exists()) return true;
File dir = new File(db.getParent());
if (!dir.exists()) {
dir.mkdirs();
}
return false;
}
- Note the use of the Context's getDatabasePath
The following is code that is very long but provides very comprehensive logging (it also caters for multiple databases (up to 10 by default) and is also caters for directories in the assets folder).
/**
* Database Helper that includes ability to open database from assets
* if the database doesn't exist.
* (i.e. a pre-defined database)
*
*/
public class OpenAssetDBHelper extends SQLiteOpenHelper {
private static final String LOGTAG = "OADB-HLPR";
public static final int MAXIMUM_HELPERS = 10;
private String mDBPath, mAssetPath;
private static OpenAssetDBHelper mInstance = new OpenAssetDBHelper[MAXIMUM_HELPERS];
private SQLiteDatabase mDB;
/**
* OpenAssetDBHelper Class that will copy a predefined database
* from the assets folder and then open it is the database;
*
* The copy will only be done if the database does not exist.
*
* Note this code is intended to be used for development and/or
* experimentation, hence the extensive logging.
*/
/**
* get an OpenAssetDBHelper instance as a singleton;
* Note! caters for up to 10 OpenAssetDBHelpers for up to 10 databases
* as specified by the helper_index
*
* @param helper_index Index to this instance/database
* (0-MAXIMUM_HELPERS less 1)
* @param context Context for the database
* @param database Database name (i.e. file name)
* @param dbversion Database version (user_version)
* @param assetfile Name of the asset file to be copied to the database
* @param asset_sub_directories String Array of the sub-directories where
* the asset file is located;
* MUST be in order
* @return The resultant OpenAssetDBHelper
*/
public static synchronized OpenAssetDBHelper getInstance(
int helper_index,
Context context,
String database,
int dbversion,
String assetfile,
String asset_sub_directories) {
// Checck that helper_index is within bounds
if (helper_index > (MAXIMUM_HELPERS -1)) {
throw new RuntimeException(
"Helper Index greater than " +
MAXIMUM_HELPERS
);
}
if (helper_index < 0) {
throw new RuntimeException(
"Helper Index cannot be negative, must be 0-" +
MAXIMUM_HELPERS
);
}
// Create the respective OpenAssetDBHelper instance
if(mInstance[helper_index] == null) {
mInstance[helper_index] = new OpenAssetDBHelper(context,
database,
dbversion,
assetfile,
asset_sub_directories);
}
return mInstance[helper_index];
}
/**
* Construct an OpenAssetDBHelper instance;
* Note! can only be called within class
*
* @param context the context to be used
* @param database the database name (equates to filename)
* @param dbversion the databaae version (user_version)
* @param assetfile The name of the asset file i.e. the pre-defined db
* @param directories The hierarchy of directories within the assets folder
* where the asset file is located
* (null or zero elements = in the assets folder)
*/
private OpenAssetDBHelper(Context context,
String database,
int dbversion,
String assetfile,
String directories) {
super(context, database, null, dbversion);
Log.d(LOGTAG,"OpenAssetDBHelper being constructed.");
mDBPath = context.getDatabasePath(database).getPath();
if (assetfile == null || assetfile.length() < 1) {
assetfile = database;
}
mAssetPath = buildAssetPath(directories,assetfile);
if (!ifDatabaseExists(mDBPath)) {
Log.d(LOGTAG,"Database " + database + " not found at " + mDBPath + " so attempting to copy from assets.");
if (copyDatabaseFromAssets(context,mDBPath, database, mAssetPath)) {
Log.d(LOGTAG, "Successfully Copied Database from Assets.");
} else {
throw new RuntimeException("No Database Available.");
}
}
// Force Database open and store it
this.mDB = this.getWritableDatabase();
logDatabaseTableInformation(mDB);
Log.d(LOGTAG,"OpenAssetDBHelper constructed.");
}
/**
* onCreate - This is where you would create tables;
* Typically this is where you would alter the structure of the database;
* Note that this is called once for the lifetime of the database.
* @param db The SQLitedatabase
*/
@Override
public void onCreate(SQLiteDatabase db) {
Log.d(LOGTAG,new Object(){}.getClass().getEnclosingMethod().getName() + " initiated.");
// As Database is copied from assets nothing to do in onCreate!
Log.d(LOGTAG,new Object(){}.getClass().getEnclosingMethod().getName() + " completed.");
}
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
Log.d(LOGTAG,new Object(){}.getClass().getEnclosingMethod().getName() + " initiated.");
// Nothing to do as it's early days in the Database's lifetime.
Log.d(LOGTAG,new Object(){}.getClass().getEnclosingMethod().getName() + " completed.");
}
/**
* Check to see if the Database exists,
* if it doesn't exists then check to see if
* the database directory exists,
* if the directory(ies) does(do) not exist then make the directory(ies);
*
*
* @param dbpath The path to the database
* @return true if the database exists, else false
*/
private boolean ifDatabaseExists(String dbpath) {
Log.d(LOGTAG,new Object(){}.getClass().getEnclosingMethod().getName() + " initiated.");
File db = new File(dbpath);
if(db.exists()) return true;
File dir = new File(db.getParent());
if (!dir.exists()) {
dir.mkdirs();
}
return false;
}
/**
* Copy the Database from the assets folder
* @param context
* @param dbpath
* @return
*/
private boolean copyDatabaseFromAssets(Context context,String dbpath, String dbname, String asset) {
String thisclass = new Object(){}.getClass().getEnclosingMethod().getName();
Log.d(LOGTAG,thisclass + " initiated");
InputStream assetsdb;
OutputStream database;
File db = new File(dbpath);
int filesize;
// Get the asset file
try {
Log.d(LOGTAG,thisclass + " attempting to find asset " + asset);
assetsdb = context.getAssets().open(asset);
filesize = assetsdb.available();
Log.d(LOGTAG,thisclass + " asset " + asset +
" located successfully with a size of " +
Integer.toString(filesize)
);
} catch (IOException e) {
Log.d(LOGTAG,thisclass + " Did not locate asset " + asset);
e.printStackTrace();
return false;
}
// Read the first 16 bytes from the asset file
byte dbcheck = new byte[16];
try {
assetsdb.read(dbcheck,0,16);
} catch (IOException e) {
Log.d(LOGTAG, thisclass + " failed trying to read 16 bytes to check for a valid database. ");
e.printStackTrace();
return false;
}
// Check that the asset file is an SQLite database
String chkdb = new String(dbcheck);
if(!chkdb.equals("SQLite format 3u0000")) {
Log.d(LOGTAG,thisclass + " asset " +
asset +
" is not a valid SQLite Database File (found " +
chkdb +
" at bytes 1-16 instead of SQLite format 3)");
try {
assetsdb.close();
} catch (IOException e) {
// Not worth doing anything
}
return false;
}
// Close the asset file
try {
assetsdb.close();
} catch (IOException e) {
Log.d(LOGTAG,thisclass +
" failed to close assets file after checking for a valid database."
);
return false;
}
// Re-open the asset file
try {
assetsdb = context.getAssets().open(asset);
filesize = assetsdb.available();
} catch (IOException e) {
Log.d(LOGTAG, thisclass +
" failed trying to re-open asset " +
asset +
" after checking for a valid database."
);
e.printStackTrace();
return false;
}
// Read the entire asset file into a buffer
Log.d(LOGTAG, thisclass +
" copying asset database " +
dbname +
" into buffer of size " +
filesize
);
byte buffer = new byte[filesize];
// Close the asset file
try {
assetsdb.read(buffer);
Log.d(LOGTAG,thisclass +
" closing asset database " + dbname
);
assetsdb.close();
} catch (IOException e) {
Log.d(LOGTAG, thisclass +
" failed while copying asset database " +
dbname +
" (or closing asset database)."
);
e.printStackTrace();
return false;
}
// Open the new database file
try {
Log.d(LOGTAG,thisclass + " attempting to open new database file " + dbpath);
database = new FileOutputStream(dbpath);
} catch (IOException e) {
Log.d(LOGTAG, thisclass + " failed to open new database file.");
e.printStackTrace();
return false;
}
// Write the new database file
try {
Log.d(LOGTAG, thisclass + " writing new database file " + dbpath);
database.write(buffer);
} catch (IOException e) {
Log.d(LOGTAG, thisclass + " failed while writing new database file " + dbpath);
e.printStackTrace();
return false;
}
// Flush the new database file
try {
Log.d(LOGTAG, thisclass + " flushing new database file " + dbpath);
database.flush();
} catch (IOException e) {
Log.d(LOGTAG, thisclass + " failed while flushing new database file " + dbpath);
e.printStackTrace();
return false;
}
// Close the new database file
try {
Log.d(LOGTAG, thisclass + " closing new database file " + dbpath);
database.close();
} catch (IOException e) {
Log.d(LOGTAG, thisclass + " failed while closing new database file " + dbpath);
e.printStackTrace();
return false;
}
Log.d(LOGTAG,new Object(){}.getClass().getEnclosingMethod().getName() + " completed.");
return true;
}
/**
* Log Database table Information
*/
private void logDatabaseTableInformation(SQLiteDatabase db) {
Log.d(LOGTAG,new Object(){}.getClass().getEnclosingMethod().getName() + " initiated.");
String mastertable = "sqlite_master";
String typecolumn = "type";
String namecolumn = "name";
String sqlcolumn = "sql";
String args = new String{"table","android_metadata"};
Cursor csr = db.query(mastertable,
null,
typecolumn + "=? AND " + namecolumn + "!=?",
args,
null,null,null
);
while (csr.moveToNext()) {
Log.d(LOGTAG,"Database contains Table " +
csr.getString(csr.getColumnIndex(namecolumn)) +
" created by SQL " +
csr.getString(csr.getColumnIndex(sqlcolumn))
);
logTableInformation(db, csr.getString(csr.getColumnIndex(namecolumn)));
}
csr.close();
Log.d(LOGTAG,new Object(){}.getClass().getEnclosingMethod().getName() + " completed.");
}
/**
* Write Table information, Table name, Column Count,
* Row Count and Column Names to the Log
* @param table Name of the table to be reported on
*/
private void logTableInformation(SQLiteDatabase db, String table) {
Cursor csr = db.query(table,
null,
null,
null,
null,
null,
null
);
Log.d(LOGTAG,"Table is " +
table +
" Column Count = " +
Integer.toString(csr.getColumnCount()) +
" Row Count = " +
Long.toString(DatabaseUtils.queryNumEntries(mDB,table))
);
StringBuilder columns_as_string = new StringBuilder();
for (String s: csr.getColumnNames()) {
columns_as_string.append(s).append(" ");
}
Log.d(LOGTAG, "tColumns are :- " + columns_as_string);
csr.close();
}
/**
* Build the sub-path to the asset, according to the directories specified
*
* @param directories directories underneath the assets folder where
* the asset files is located, null or empty
* array if file is located directly in the
* assets folder;
* directories must be specified in the order
* in which they appear in the path.
* @param filename The filename of the asset
* @return The fill sub-path to the asset
*/
private String buildAssetPath(String directories, String filename) {
StringBuilder sb = new StringBuilder();
final String SEPERATOR = "/";
if (directories != null && directories.length > 0) {
for (String s: directories) {
sb.append(s);
if (!s.substring(s.length()-1,s.length()).equals(SEPERATOR)) {
sb.append(SEPERATOR);
}
}
sb.append(filename);
return sb.toString();
} else {
return filename;
}
}
}
Example Usage
public class MainActivity extends AppCompatActivity {
public static final int DBVERSION = 1;
public static final String DBNAME1 = "openassetdb.db";
public static final int DB1_INDEX = 0;
public static final String DBNAME2 = "myshopping";
public static final int DB2_INDEX = 1;
OpenAssetDBHelper mOADBHlpr;
OpenAssetDBHelper mShoppingHelper;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// Example 1 - Database file located in the assets folder and
// database name same as file name
mOADBHlpr = OpenAssetDBHelper.getInstance(DB1_INDEX,
this,
DBNAME1,
DBVERSION,
DBNAME1,
null
);
// Example 2 - Database file in databases directory of the assets folder
// database name different to the asset filename
mShoppingHelper = OpenAssetDBHelper.getInstance(DB2_INDEX,
this,
DBNAME2,
DBVERSION,
"shopper",
new String{"databases"}
);
}
}
Result (when no databases exist) :-
2018-11-22 07:06:01.408 1993-1993/? D/OADB-HLPR: OpenAssetDBHelper being constructed.
2018-11-22 07:06:01.408 1993-1993/? D/OADB-HLPR: ifDatabaseExists initiated.
2018-11-22 07:06:01.408 1993-1993/? D/OADB-HLPR: Database openassetdb.db not found at /data/user/0/mjt.openassetdb/databases/openassetdb.db so attempting to copy from assets.
2018-11-22 07:06:01.409 1993-1993/? D/OADB-HLPR: copyDatabaseFromAssets initiated
2018-11-22 07:06:01.409 1993-1993/? D/OADB-HLPR: copyDatabaseFromAssets attempting to find asset openassetdb.db
2018-11-22 07:06:01.409 1993-1993/? D/OADB-HLPR: copyDatabaseFromAssets asset openassetdb.db located successfully with a size of 12288
2018-11-22 07:06:01.409 1993-1993/? D/OADB-HLPR: copyDatabaseFromAssets copying asset database openassetdb.db into buffer of size 12288
2018-11-22 07:06:01.409 1993-1993/? D/OADB-HLPR: copyDatabaseFromAssets closing asset database openassetdb.db
2018-11-22 07:06:01.409 1993-1993/? D/OADB-HLPR: copyDatabaseFromAssets attempting to open new database file /data/user/0/mjt.openassetdb/databases/openassetdb.db
2018-11-22 07:06:01.410 1993-1993/? D/OADB-HLPR: copyDatabaseFromAssets writing new database file /data/user/0/mjt.openassetdb/databases/openassetdb.db
2018-11-22 07:06:01.410 1993-1993/? D/OADB-HLPR: copyDatabaseFromAssets flushing new database file /data/user/0/mjt.openassetdb/databases/openassetdb.db
2018-11-22 07:06:01.410 1993-1993/? D/OADB-HLPR: copyDatabaseFromAssets closing new database file /data/user/0/mjt.openassetdb/databases/openassetdb.db
2018-11-22 07:06:01.410 1993-1993/? D/OADB-HLPR: copyDatabaseFromAssets completed.
2018-11-22 07:06:01.410 1993-1993/? D/OADB-HLPR: Successfully Copied Database from Assets.
2018-11-22 07:06:01.421 1993-1993/? D/OADB-HLPR: onCreate initiated.
2018-11-22 07:06:01.421 1993-1993/? D/OADB-HLPR: onCreate completed.
2018-11-22 07:06:01.425 1993-1993/? D/OADB-HLPR: logDatabaseTableInformation initiated.
2018-11-22 07:06:01.426 1993-1993/? D/OADB-HLPR: Database contains Table testtable created by SQL CREATE TABLE `testtable` (
`_id` INTEGER PRIMARY KEY AUTOINCREMENT,
`name` TEXT,
`timestamp` INTEGER
)
2018-11-22 07:06:01.426 1993-1993/? D/OADB-HLPR: Table is testtable Column Count = 3 Row Count = 2
2018-11-22 07:06:01.426 1993-1993/? D/OADB-HLPR: Columns are :- _id name timestamp
2018-11-22 07:06:01.426 1993-1993/? D/OADB-HLPR: Database contains Table sqlite_sequence created by SQL CREATE TABLE sqlite_sequence(name,seq)
2018-11-22 07:06:01.427 1993-1993/? D/OADB-HLPR: Table is sqlite_sequence Column Count = 2 Row Count = 1
2018-11-22 07:06:01.427 1993-1993/? D/OADB-HLPR: Columns are :- name seq
2018-11-22 07:06:01.427 1993-1993/? D/OADB-HLPR: logDatabaseTableInformation completed.
(2nd)
2018-11-22 07:06:01.427 1993-1993/? D/OADB-HLPR: OpenAssetDBHelper constructed.
2018-11-22 07:06:01.427 1993-1993/? D/OADB-HLPR: OpenAssetDBHelper being constructed.
2018-11-22 07:06:01.427 1993-1993/? D/OADB-HLPR: ifDatabaseExists initiated.
2018-11-22 07:06:01.428 1993-1993/? D/OADB-HLPR: Database myshopping not found at /data/user/0/mjt.openassetdb/databases/myshopping so attempting to copy from assets.
2018-11-22 07:06:01.428 1993-1993/? D/OADB-HLPR: copyDatabaseFromAssets initiated
2018-11-22 07:06:01.428 1993-1993/? D/OADB-HLPR: copyDatabaseFromAssets attempting to find asset databases/shopper
2018-11-22 07:06:01.428 1993-1993/? D/OADB-HLPR: copyDatabaseFromAssets asset databases/shopper located successfully with a size of 262144
2018-11-22 07:06:01.428 1993-1993/? D/OADB-HLPR: copyDatabaseFromAssets copying asset database myshopping into buffer of size 262144
2018-11-22 07:06:01.429 1993-1993/? D/OADB-HLPR: copyDatabaseFromAssets closing asset database myshopping
2018-11-22 07:06:01.429 1993-1993/? D/OADB-HLPR: copyDatabaseFromAssets attempting to open new database file /data/user/0/mjt.openassetdb/databases/myshopping
2018-11-22 07:06:01.429 1993-1993/? D/OADB-HLPR: copyDatabaseFromAssets writing new database file /data/user/0/mjt.openassetdb/databases/myshopping
2018-11-22 07:06:01.429 1993-1993/? D/OADB-HLPR: copyDatabaseFromAssets flushing new database file /data/user/0/mjt.openassetdb/databases/myshopping
2018-11-22 07:06:01.429 1993-1993/? D/OADB-HLPR: copyDatabaseFromAssets closing new database file /data/user/0/mjt.openassetdb/databases/myshopping
2018-11-22 07:06:01.429 1993-1993/? D/OADB-HLPR: copyDatabaseFromAssets completed.
2018-11-22 07:06:01.429 1993-1993/? D/OADB-HLPR: Successfully Copied Database from Assets.
2018-11-22 07:06:01.440 1993-1993/? D/OADB-HLPR: onCreate initiated.
2018-11-22 07:06:01.440 1993-1993/? D/OADB-HLPR: onCreate completed.
2018-11-22 07:06:01.443 1993-1993/? D/OADB-HLPR: logDatabaseTableInformation initiated.
2018-11-22 07:06:01.444 1993-1993/? D/OADB-HLPR: Database contains Table shops created by SQL CREATE TABLE shops (_id INTEGER PRIMARY KEY , shopname TEXT , shoporder INTEGER DEFAULT 100 , shopstreet TEXT , shopcity TEXT , shopstate TEXT , shopphone TEXT , shopnotes TEXT )
2018-11-22 07:06:01.445 1993-1993/? D/OADB-HLPR: Table is shops Column Count = 8 Row Count = 4
2018-11-22 07:06:01.445 1993-1993/? D/OADB-HLPR: Columns are :- _id shopname shoporder shopstreet shopcity shopstate shopphone shopnotes
2018-11-22 07:06:01.446 1993-1993/? D/OADB-HLPR: Database contains Table aisles created by SQL CREATE TABLE aisles (_id INTEGER PRIMARY KEY , aislename TEXT , aisleorder INTEGER DEFAULT 100 , aisleshopref INTEGER )
2018-11-22 07:06:01.448 1993-1993/? D/OADB-HLPR: Table is aisles Column Count = 4 Row Count = 20
2018-11-22 07:06:01.448 1993-1993/? D/OADB-HLPR: Columns are :- _id aislename aisleorder aisleshopref
2018-11-22 07:06:01.448 1993-1993/? D/OADB-HLPR: Database contains Table products created by SQL CREATE TABLE products (_id INTEGER PRIMARY KEY , productname TEXT , productorder INTEGER DEFAULT 100 , productaisleref INTEGER , productuses INTEGER DEFAULT 0 , productnotes TEXT )
2018-11-22 07:06:01.449 1993-1993/? D/OADB-HLPR: Table is products Column Count = 6 Row Count = 10
2018-11-22 07:06:01.449 1993-1993/? D/OADB-HLPR: Columns are :- _id productname productorder productaisleref productuses productnotes
2018-11-22 07:06:01.449 1993-1993/? D/OADB-HLPR: Database contains Table productusage created by SQL CREATE TABLE productusage (productailseref INTEGER , productproductref INTEGER , productcost REAL DEFAULT 1.00 , productbuycount INTEGER DEFAULT 0 , productfirstbuydate INTEGER DEFAULT 0 , productlatestbuydate INTEGER DEFAULT 0 , mincost REAL , PRIMARY KEY (productailseref, productproductref))
2018-11-22 07:06:01.451 1993-1993/? D/OADB-HLPR: Table is productusage Column Count = 7 Row Count = 20
2018-11-22 07:06:01.451 1993-1993/? D/OADB-HLPR: Columns are :- productailseref productproductref productcost productbuycount productfirstbuydate productlatestbuydate mincost
2018-11-22 07:06:01.451 1993-1993/? D/OADB-HLPR: Database contains Table rules created by SQL CREATE TABLE rules (ruleid INTEGER PRIMARY KEY , rulename TEXT , ruletype INTEGER , rulepromptflag INTEGER , ruleperiod INTEGER , rulemultiplier INTEGER , ruleactiveon INTEGER , ruleproductref INTEGER , ruleaisleref INTEGER )
2018-11-22 07:06:01.452 1993-1993/? D/OADB-HLPR: Table is rules Column Count = 9 Row Count = 0
2018-11-22 07:06:01.452 1993-1993/? D/OADB-HLPR: Columns are :- ruleid rulename ruletype rulepromptflag ruleperiod rulemultiplier ruleactiveon ruleproductref ruleaisleref
2018-11-22 07:06:01.452 1993-1993/? D/OADB-HLPR: Database contains Table shoplist created by SQL CREATE TABLE "shoplist" ("_id" INTEGER PRIMARY KEY NOT NULL , "productref" INTEGER, "dateadded" INTEGER, "numbertoget" INTEGER, "done" BOOL, "dategot" INTEGER, "cost" REAL, "productusageref" INTEGER, "aisleref" INTEGER)
2018-11-22 07:06:01.453 1993-1993/? D/OADB-HLPR: Table is shoplist Column Count = 9 Row Count = 4
2018-11-22 07:06:01.454 1993-1993/? D/OADB-HLPR: Columns are :- _id productref dateadded numbertoget done dategot cost productusageref aisleref
2018-11-22 07:06:01.454 1993-1993/? D/OADB-HLPR: logDatabaseTableInformation completed.
2018-11-22 07:06:01.454 1993-1993/? D/OADB-HLPR: OpenAssetDBHelper constructed.
I tester your database adapter and it is working. I will investigate my own code later. Thank you very much for your reply!
– Ulrich_Peters
Nov 26 '18 at 15:54
Ok. Somehow it is not working anymore. I simply get an D/OADB-HLPR: copyDatabaseFromAssets Did not locate asset NewDATABASE.db even though i have NewDATABASE.db in my assets folder.
– Ulrich_Peters
Nov 29 '18 at 5:58
@Ulrich_Peters, I've added an explanatory answer (had to add another due to size restriction). I would initially suspect that you have specified a directory but not placed the asset in the directory or vice-versa. What you have/have not specified will be in the log before and after the line you have shown (there's no way that that is the only line in the log, unless you've made numerous changes)
– MikeT
Nov 29 '18 at 8:22
@Ulrich_Peters also note that file and directory names are case dependant.
– MikeT
Nov 29 '18 at 8:59
add a comment |
Additional - Asset not found example
using
mShopper = OpenAssetDBHelper.getInstance(DB3_INDEX,
this,
DBNAME3,
DBVERSION,
"Shopper.lite", // not the asset name
new String{"databases"}
);
Where
- DBNAME3 resolves to rumplestiltskin (the final database name)
- DBVERSION is 1
- and the asset filename is Shopper.lite which should be in the databases folder (doesn't exist though).
The resultant log is :-
11-29 07:46:22.603 4816-4816/? D/OADB-HLPR: OpenAssetDBHelper constructed.
11-29 07:46:22.603 4816-4816/? D/OADB-HLPR: OpenAssetDBHelper being constructed.
11-29 07:46:22.603 4816-4816/? D/OADB-HLPR: ifDatabaseExists initiated.
11-29 07:46:22.603 4816-4816/? D/OADB-HLPR: Database rumplestilskin not found at /data/data/mjt.openassetdb/databases/rumplestilskin so attempting to copy from assets.
11-29 07:46:22.603 4816-4816/? D/OADB-HLPR: copyDatabaseFromAssets initiated
11-29 07:46:22.603 4816-4816/? D/OADB-HLPR: copyDatabaseFromAssets attempting to find asset databases/Shopper.lite
11-29 07:46:22.603 4816-4816/? D/OADB-HLPR: copyDatabaseFromAssets Did not locate asset databases/Shopper.lite
11-29 07:46:22.603 4816-4816/? W/System.err: java.io.FileNotFoundException: databases/Shopper.lite
11-29 07:46:22.603 4816-4816/? W/System.err: at android.content.res.AssetManager.openAsset(Native Method)
11-29 07:46:22.603 4816-4816/? W/System.err: at android.content.res.AssetManager.open(AssetManager.java:315)
11-29 07:46:22.603 4816-4816/? W/System.err: at android.content.res.AssetManager.open(AssetManager.java:289)
11-29 07:46:22.603 4816-4816/? W/System.err: at mjt.openassetdb.OpenAssetDBHelper.copyDatabaseFromAssets(OpenAssetDBHelper.java:187)
11-29 07:46:22.603 4816-4816/? W/System.err: at mjt.openassetdb.OpenAssetDBHelper.<init>(OpenAssetDBHelper.java:117)
11-29 07:46:22.603 4816-4816/? W/System.err: at mjt.openassetdb.OpenAssetDBHelper.getInstance(OpenAssetDBHelper.java:80)
11-29 07:46:22.603 4816-4816/? W/System.err: at mjt.openassetdb.MainActivity.onCreate(MainActivity.java:87)
11-29 07:46:22.603 4816-4816/? W/System.err: at android.app.Activity.performCreate(Activity.java:5008)
11-29 07:46:22.603 4816-4816/? W/System.err: at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1079)
11-29 07:46:22.603 4816-4816/? W/System.err: at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2023)
11-29 07:46:22.603 4816-4816/? W/System.err: at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2084)
11-29 07:46:22.603 4816-4816/? W/System.err: at android.app.ActivityThread.access$600(ActivityThread.java:130)
11-29 07:46:22.603 4816-4816/? W/System.err: at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1195)
11-29 07:46:22.603 4816-4816/? W/System.err: at android.os.Handler.dispatchMessage(Handler.java:99)
11-29 07:46:22.603 4816-4816/? W/System.err: at android.os.Looper.loop(Looper.java:137)
11-29 07:46:22.603 4816-4816/? W/System.err: at android.app.ActivityThread.main(ActivityThread.java:4745)
11-29 07:46:22.603 4816-4816/? W/System.err: at java.lang.reflect.Method.invokeNative(Native Method)
11-29 07:46:22.603 4816-4816/? W/System.err: at java.lang.reflect.Method.invoke(Method.java:511)
11-29 07:46:22.603 4816-4816/? W/System.err: at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:786)
11-29 07:46:22.603 4816-4816/? W/System.err: at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:553)
11-29 07:46:22.603 4816-4816/? W/System.err: at dalvik.system.NativeStart.main(Native Method)
11-29 07:46:22.603 4816-4816/? D/AndroidRuntime: Shutting down VM
11-29 07:46:22.603 4816-4816/? W/dalvikvm: threadid=1: thread exiting with uncaught exception (group=0xa6265288)
11-29 07:46:22.603 4816-4816/? E/AndroidRuntime: FATAL EXCEPTION: main
java.lang.RuntimeException: Unable to start activity ComponentInfo{mjt.openassetdb/mjt.openassetdb.MainActivity}: java.lang.RuntimeException: No Database Available.
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2059)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2084)
at android.app.ActivityThread.access$600(ActivityThread.java:130)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1195)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loop(Looper.java:137)
at android.app.ActivityThread.main(ActivityThread.java:4745)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:511)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:786)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:553)
at dalvik.system.NativeStart.main(Native Method)
Caused by: java.lang.RuntimeException: No Database Available.
at mjt.openassetdb.OpenAssetDBHelper.<init>(OpenAssetDBHelper.java:120)
at mjt.openassetdb.OpenAssetDBHelper.getInstance(OpenAssetDBHelper.java:80)
at mjt.openassetdb.MainActivity.onCreate(MainActivity.java:87)
at android.app.Activity.performCreate(Activity.java:5008)
at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1079)
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2023)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2084)
at android.app.ActivityThread.access$600(ActivityThread.java:130)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1195)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loop(Looper.java:137)
at android.app.ActivityThread.main(ActivityThread.java:4745)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:511)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:786)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:553)
at dalvik.system.NativeStart.main(Native Method)
The first pertinent line is D/OADB-HLPR: copyDatabaseFromAssets attempting to find asset databases/Shopper.lite
This provides the path within the assets folder where the asset is expected to be found (in this example the filename is expected to be Shopper.lite in the databases subfolder/directory)
The line D/OADB-HLPR: copyDatabaseFromAssets Did not locate asset databases/Shopper.lite
reports that the asset file was not found.
This is followed by the trapped exception (not the actual crash)
Processing continues until the final crash as reported by :-
E/AndroidRuntime: FATAL EXCEPTION: main
java.lang.RuntimeException: Unable to start activity ComponentInfo{mjt.openassetdb/mjt.openassetdb.MainActivity}: java.lang.RuntimeException: No Database Available.
add a comment |
Your Answer
StackExchange.ifUsing("editor", function () {
StackExchange.using("externalEditor", function () {
StackExchange.using("snippets", function () {
StackExchange.snippets.init();
});
});
}, "code-snippets");
StackExchange.ready(function() {
var channelOptions = {
tags: "".split(" "),
id: "1"
};
initTagRenderer("".split(" "), "".split(" "), channelOptions);
StackExchange.using("externalEditor", function() {
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled) {
StackExchange.using("snippets", function() {
createEditor();
});
}
else {
createEditor();
}
});
function createEditor() {
StackExchange.prepareEditor({
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: true,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: 10,
bindNavPrevention: true,
postfix: "",
imageUploader: {
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
},
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
});
}
});
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53414789%2fandroid-sqlite-errorcopyingdatabase-error%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
2 Answers
2
active
oldest
votes
2 Answers
2
active
oldest
votes
active
oldest
votes
active
oldest
votes
The problem with the code you have is that numerous exceptions are caught by using throws IOException
and then you just issue a generic exception.
Whilst there could be a number of underlying causes.
It could be that asset itself doesn't exist where it's expected (in the assets folder (e.g. not in the databases directory (SQLiteAssetHelper uses this directory))).
It could be that the databases folder, within the package doesn't exist (use mkdirs on the DB_PATH). e.g. have something like :-
private boolean checkDatabase {
File db = new File(mContext.getDatabasePath(DB_NAME).getPath());
if(db.exists()) return true;
File dir = new File(db.getParent());
if (!dir.exists()) {
dir.mkdirs();
}
return false;
}
- Note the use of the Context's getDatabasePath
The following is code that is very long but provides very comprehensive logging (it also caters for multiple databases (up to 10 by default) and is also caters for directories in the assets folder).
/**
* Database Helper that includes ability to open database from assets
* if the database doesn't exist.
* (i.e. a pre-defined database)
*
*/
public class OpenAssetDBHelper extends SQLiteOpenHelper {
private static final String LOGTAG = "OADB-HLPR";
public static final int MAXIMUM_HELPERS = 10;
private String mDBPath, mAssetPath;
private static OpenAssetDBHelper mInstance = new OpenAssetDBHelper[MAXIMUM_HELPERS];
private SQLiteDatabase mDB;
/**
* OpenAssetDBHelper Class that will copy a predefined database
* from the assets folder and then open it is the database;
*
* The copy will only be done if the database does not exist.
*
* Note this code is intended to be used for development and/or
* experimentation, hence the extensive logging.
*/
/**
* get an OpenAssetDBHelper instance as a singleton;
* Note! caters for up to 10 OpenAssetDBHelpers for up to 10 databases
* as specified by the helper_index
*
* @param helper_index Index to this instance/database
* (0-MAXIMUM_HELPERS less 1)
* @param context Context for the database
* @param database Database name (i.e. file name)
* @param dbversion Database version (user_version)
* @param assetfile Name of the asset file to be copied to the database
* @param asset_sub_directories String Array of the sub-directories where
* the asset file is located;
* MUST be in order
* @return The resultant OpenAssetDBHelper
*/
public static synchronized OpenAssetDBHelper getInstance(
int helper_index,
Context context,
String database,
int dbversion,
String assetfile,
String asset_sub_directories) {
// Checck that helper_index is within bounds
if (helper_index > (MAXIMUM_HELPERS -1)) {
throw new RuntimeException(
"Helper Index greater than " +
MAXIMUM_HELPERS
);
}
if (helper_index < 0) {
throw new RuntimeException(
"Helper Index cannot be negative, must be 0-" +
MAXIMUM_HELPERS
);
}
// Create the respective OpenAssetDBHelper instance
if(mInstance[helper_index] == null) {
mInstance[helper_index] = new OpenAssetDBHelper(context,
database,
dbversion,
assetfile,
asset_sub_directories);
}
return mInstance[helper_index];
}
/**
* Construct an OpenAssetDBHelper instance;
* Note! can only be called within class
*
* @param context the context to be used
* @param database the database name (equates to filename)
* @param dbversion the databaae version (user_version)
* @param assetfile The name of the asset file i.e. the pre-defined db
* @param directories The hierarchy of directories within the assets folder
* where the asset file is located
* (null or zero elements = in the assets folder)
*/
private OpenAssetDBHelper(Context context,
String database,
int dbversion,
String assetfile,
String directories) {
super(context, database, null, dbversion);
Log.d(LOGTAG,"OpenAssetDBHelper being constructed.");
mDBPath = context.getDatabasePath(database).getPath();
if (assetfile == null || assetfile.length() < 1) {
assetfile = database;
}
mAssetPath = buildAssetPath(directories,assetfile);
if (!ifDatabaseExists(mDBPath)) {
Log.d(LOGTAG,"Database " + database + " not found at " + mDBPath + " so attempting to copy from assets.");
if (copyDatabaseFromAssets(context,mDBPath, database, mAssetPath)) {
Log.d(LOGTAG, "Successfully Copied Database from Assets.");
} else {
throw new RuntimeException("No Database Available.");
}
}
// Force Database open and store it
this.mDB = this.getWritableDatabase();
logDatabaseTableInformation(mDB);
Log.d(LOGTAG,"OpenAssetDBHelper constructed.");
}
/**
* onCreate - This is where you would create tables;
* Typically this is where you would alter the structure of the database;
* Note that this is called once for the lifetime of the database.
* @param db The SQLitedatabase
*/
@Override
public void onCreate(SQLiteDatabase db) {
Log.d(LOGTAG,new Object(){}.getClass().getEnclosingMethod().getName() + " initiated.");
// As Database is copied from assets nothing to do in onCreate!
Log.d(LOGTAG,new Object(){}.getClass().getEnclosingMethod().getName() + " completed.");
}
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
Log.d(LOGTAG,new Object(){}.getClass().getEnclosingMethod().getName() + " initiated.");
// Nothing to do as it's early days in the Database's lifetime.
Log.d(LOGTAG,new Object(){}.getClass().getEnclosingMethod().getName() + " completed.");
}
/**
* Check to see if the Database exists,
* if it doesn't exists then check to see if
* the database directory exists,
* if the directory(ies) does(do) not exist then make the directory(ies);
*
*
* @param dbpath The path to the database
* @return true if the database exists, else false
*/
private boolean ifDatabaseExists(String dbpath) {
Log.d(LOGTAG,new Object(){}.getClass().getEnclosingMethod().getName() + " initiated.");
File db = new File(dbpath);
if(db.exists()) return true;
File dir = new File(db.getParent());
if (!dir.exists()) {
dir.mkdirs();
}
return false;
}
/**
* Copy the Database from the assets folder
* @param context
* @param dbpath
* @return
*/
private boolean copyDatabaseFromAssets(Context context,String dbpath, String dbname, String asset) {
String thisclass = new Object(){}.getClass().getEnclosingMethod().getName();
Log.d(LOGTAG,thisclass + " initiated");
InputStream assetsdb;
OutputStream database;
File db = new File(dbpath);
int filesize;
// Get the asset file
try {
Log.d(LOGTAG,thisclass + " attempting to find asset " + asset);
assetsdb = context.getAssets().open(asset);
filesize = assetsdb.available();
Log.d(LOGTAG,thisclass + " asset " + asset +
" located successfully with a size of " +
Integer.toString(filesize)
);
} catch (IOException e) {
Log.d(LOGTAG,thisclass + " Did not locate asset " + asset);
e.printStackTrace();
return false;
}
// Read the first 16 bytes from the asset file
byte dbcheck = new byte[16];
try {
assetsdb.read(dbcheck,0,16);
} catch (IOException e) {
Log.d(LOGTAG, thisclass + " failed trying to read 16 bytes to check for a valid database. ");
e.printStackTrace();
return false;
}
// Check that the asset file is an SQLite database
String chkdb = new String(dbcheck);
if(!chkdb.equals("SQLite format 3u0000")) {
Log.d(LOGTAG,thisclass + " asset " +
asset +
" is not a valid SQLite Database File (found " +
chkdb +
" at bytes 1-16 instead of SQLite format 3)");
try {
assetsdb.close();
} catch (IOException e) {
// Not worth doing anything
}
return false;
}
// Close the asset file
try {
assetsdb.close();
} catch (IOException e) {
Log.d(LOGTAG,thisclass +
" failed to close assets file after checking for a valid database."
);
return false;
}
// Re-open the asset file
try {
assetsdb = context.getAssets().open(asset);
filesize = assetsdb.available();
} catch (IOException e) {
Log.d(LOGTAG, thisclass +
" failed trying to re-open asset " +
asset +
" after checking for a valid database."
);
e.printStackTrace();
return false;
}
// Read the entire asset file into a buffer
Log.d(LOGTAG, thisclass +
" copying asset database " +
dbname +
" into buffer of size " +
filesize
);
byte buffer = new byte[filesize];
// Close the asset file
try {
assetsdb.read(buffer);
Log.d(LOGTAG,thisclass +
" closing asset database " + dbname
);
assetsdb.close();
} catch (IOException e) {
Log.d(LOGTAG, thisclass +
" failed while copying asset database " +
dbname +
" (or closing asset database)."
);
e.printStackTrace();
return false;
}
// Open the new database file
try {
Log.d(LOGTAG,thisclass + " attempting to open new database file " + dbpath);
database = new FileOutputStream(dbpath);
} catch (IOException e) {
Log.d(LOGTAG, thisclass + " failed to open new database file.");
e.printStackTrace();
return false;
}
// Write the new database file
try {
Log.d(LOGTAG, thisclass + " writing new database file " + dbpath);
database.write(buffer);
} catch (IOException e) {
Log.d(LOGTAG, thisclass + " failed while writing new database file " + dbpath);
e.printStackTrace();
return false;
}
// Flush the new database file
try {
Log.d(LOGTAG, thisclass + " flushing new database file " + dbpath);
database.flush();
} catch (IOException e) {
Log.d(LOGTAG, thisclass + " failed while flushing new database file " + dbpath);
e.printStackTrace();
return false;
}
// Close the new database file
try {
Log.d(LOGTAG, thisclass + " closing new database file " + dbpath);
database.close();
} catch (IOException e) {
Log.d(LOGTAG, thisclass + " failed while closing new database file " + dbpath);
e.printStackTrace();
return false;
}
Log.d(LOGTAG,new Object(){}.getClass().getEnclosingMethod().getName() + " completed.");
return true;
}
/**
* Log Database table Information
*/
private void logDatabaseTableInformation(SQLiteDatabase db) {
Log.d(LOGTAG,new Object(){}.getClass().getEnclosingMethod().getName() + " initiated.");
String mastertable = "sqlite_master";
String typecolumn = "type";
String namecolumn = "name";
String sqlcolumn = "sql";
String args = new String{"table","android_metadata"};
Cursor csr = db.query(mastertable,
null,
typecolumn + "=? AND " + namecolumn + "!=?",
args,
null,null,null
);
while (csr.moveToNext()) {
Log.d(LOGTAG,"Database contains Table " +
csr.getString(csr.getColumnIndex(namecolumn)) +
" created by SQL " +
csr.getString(csr.getColumnIndex(sqlcolumn))
);
logTableInformation(db, csr.getString(csr.getColumnIndex(namecolumn)));
}
csr.close();
Log.d(LOGTAG,new Object(){}.getClass().getEnclosingMethod().getName() + " completed.");
}
/**
* Write Table information, Table name, Column Count,
* Row Count and Column Names to the Log
* @param table Name of the table to be reported on
*/
private void logTableInformation(SQLiteDatabase db, String table) {
Cursor csr = db.query(table,
null,
null,
null,
null,
null,
null
);
Log.d(LOGTAG,"Table is " +
table +
" Column Count = " +
Integer.toString(csr.getColumnCount()) +
" Row Count = " +
Long.toString(DatabaseUtils.queryNumEntries(mDB,table))
);
StringBuilder columns_as_string = new StringBuilder();
for (String s: csr.getColumnNames()) {
columns_as_string.append(s).append(" ");
}
Log.d(LOGTAG, "tColumns are :- " + columns_as_string);
csr.close();
}
/**
* Build the sub-path to the asset, according to the directories specified
*
* @param directories directories underneath the assets folder where
* the asset files is located, null or empty
* array if file is located directly in the
* assets folder;
* directories must be specified in the order
* in which they appear in the path.
* @param filename The filename of the asset
* @return The fill sub-path to the asset
*/
private String buildAssetPath(String directories, String filename) {
StringBuilder sb = new StringBuilder();
final String SEPERATOR = "/";
if (directories != null && directories.length > 0) {
for (String s: directories) {
sb.append(s);
if (!s.substring(s.length()-1,s.length()).equals(SEPERATOR)) {
sb.append(SEPERATOR);
}
}
sb.append(filename);
return sb.toString();
} else {
return filename;
}
}
}
Example Usage
public class MainActivity extends AppCompatActivity {
public static final int DBVERSION = 1;
public static final String DBNAME1 = "openassetdb.db";
public static final int DB1_INDEX = 0;
public static final String DBNAME2 = "myshopping";
public static final int DB2_INDEX = 1;
OpenAssetDBHelper mOADBHlpr;
OpenAssetDBHelper mShoppingHelper;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// Example 1 - Database file located in the assets folder and
// database name same as file name
mOADBHlpr = OpenAssetDBHelper.getInstance(DB1_INDEX,
this,
DBNAME1,
DBVERSION,
DBNAME1,
null
);
// Example 2 - Database file in databases directory of the assets folder
// database name different to the asset filename
mShoppingHelper = OpenAssetDBHelper.getInstance(DB2_INDEX,
this,
DBNAME2,
DBVERSION,
"shopper",
new String{"databases"}
);
}
}
Result (when no databases exist) :-
2018-11-22 07:06:01.408 1993-1993/? D/OADB-HLPR: OpenAssetDBHelper being constructed.
2018-11-22 07:06:01.408 1993-1993/? D/OADB-HLPR: ifDatabaseExists initiated.
2018-11-22 07:06:01.408 1993-1993/? D/OADB-HLPR: Database openassetdb.db not found at /data/user/0/mjt.openassetdb/databases/openassetdb.db so attempting to copy from assets.
2018-11-22 07:06:01.409 1993-1993/? D/OADB-HLPR: copyDatabaseFromAssets initiated
2018-11-22 07:06:01.409 1993-1993/? D/OADB-HLPR: copyDatabaseFromAssets attempting to find asset openassetdb.db
2018-11-22 07:06:01.409 1993-1993/? D/OADB-HLPR: copyDatabaseFromAssets asset openassetdb.db located successfully with a size of 12288
2018-11-22 07:06:01.409 1993-1993/? D/OADB-HLPR: copyDatabaseFromAssets copying asset database openassetdb.db into buffer of size 12288
2018-11-22 07:06:01.409 1993-1993/? D/OADB-HLPR: copyDatabaseFromAssets closing asset database openassetdb.db
2018-11-22 07:06:01.409 1993-1993/? D/OADB-HLPR: copyDatabaseFromAssets attempting to open new database file /data/user/0/mjt.openassetdb/databases/openassetdb.db
2018-11-22 07:06:01.410 1993-1993/? D/OADB-HLPR: copyDatabaseFromAssets writing new database file /data/user/0/mjt.openassetdb/databases/openassetdb.db
2018-11-22 07:06:01.410 1993-1993/? D/OADB-HLPR: copyDatabaseFromAssets flushing new database file /data/user/0/mjt.openassetdb/databases/openassetdb.db
2018-11-22 07:06:01.410 1993-1993/? D/OADB-HLPR: copyDatabaseFromAssets closing new database file /data/user/0/mjt.openassetdb/databases/openassetdb.db
2018-11-22 07:06:01.410 1993-1993/? D/OADB-HLPR: copyDatabaseFromAssets completed.
2018-11-22 07:06:01.410 1993-1993/? D/OADB-HLPR: Successfully Copied Database from Assets.
2018-11-22 07:06:01.421 1993-1993/? D/OADB-HLPR: onCreate initiated.
2018-11-22 07:06:01.421 1993-1993/? D/OADB-HLPR: onCreate completed.
2018-11-22 07:06:01.425 1993-1993/? D/OADB-HLPR: logDatabaseTableInformation initiated.
2018-11-22 07:06:01.426 1993-1993/? D/OADB-HLPR: Database contains Table testtable created by SQL CREATE TABLE `testtable` (
`_id` INTEGER PRIMARY KEY AUTOINCREMENT,
`name` TEXT,
`timestamp` INTEGER
)
2018-11-22 07:06:01.426 1993-1993/? D/OADB-HLPR: Table is testtable Column Count = 3 Row Count = 2
2018-11-22 07:06:01.426 1993-1993/? D/OADB-HLPR: Columns are :- _id name timestamp
2018-11-22 07:06:01.426 1993-1993/? D/OADB-HLPR: Database contains Table sqlite_sequence created by SQL CREATE TABLE sqlite_sequence(name,seq)
2018-11-22 07:06:01.427 1993-1993/? D/OADB-HLPR: Table is sqlite_sequence Column Count = 2 Row Count = 1
2018-11-22 07:06:01.427 1993-1993/? D/OADB-HLPR: Columns are :- name seq
2018-11-22 07:06:01.427 1993-1993/? D/OADB-HLPR: logDatabaseTableInformation completed.
(2nd)
2018-11-22 07:06:01.427 1993-1993/? D/OADB-HLPR: OpenAssetDBHelper constructed.
2018-11-22 07:06:01.427 1993-1993/? D/OADB-HLPR: OpenAssetDBHelper being constructed.
2018-11-22 07:06:01.427 1993-1993/? D/OADB-HLPR: ifDatabaseExists initiated.
2018-11-22 07:06:01.428 1993-1993/? D/OADB-HLPR: Database myshopping not found at /data/user/0/mjt.openassetdb/databases/myshopping so attempting to copy from assets.
2018-11-22 07:06:01.428 1993-1993/? D/OADB-HLPR: copyDatabaseFromAssets initiated
2018-11-22 07:06:01.428 1993-1993/? D/OADB-HLPR: copyDatabaseFromAssets attempting to find asset databases/shopper
2018-11-22 07:06:01.428 1993-1993/? D/OADB-HLPR: copyDatabaseFromAssets asset databases/shopper located successfully with a size of 262144
2018-11-22 07:06:01.428 1993-1993/? D/OADB-HLPR: copyDatabaseFromAssets copying asset database myshopping into buffer of size 262144
2018-11-22 07:06:01.429 1993-1993/? D/OADB-HLPR: copyDatabaseFromAssets closing asset database myshopping
2018-11-22 07:06:01.429 1993-1993/? D/OADB-HLPR: copyDatabaseFromAssets attempting to open new database file /data/user/0/mjt.openassetdb/databases/myshopping
2018-11-22 07:06:01.429 1993-1993/? D/OADB-HLPR: copyDatabaseFromAssets writing new database file /data/user/0/mjt.openassetdb/databases/myshopping
2018-11-22 07:06:01.429 1993-1993/? D/OADB-HLPR: copyDatabaseFromAssets flushing new database file /data/user/0/mjt.openassetdb/databases/myshopping
2018-11-22 07:06:01.429 1993-1993/? D/OADB-HLPR: copyDatabaseFromAssets closing new database file /data/user/0/mjt.openassetdb/databases/myshopping
2018-11-22 07:06:01.429 1993-1993/? D/OADB-HLPR: copyDatabaseFromAssets completed.
2018-11-22 07:06:01.429 1993-1993/? D/OADB-HLPR: Successfully Copied Database from Assets.
2018-11-22 07:06:01.440 1993-1993/? D/OADB-HLPR: onCreate initiated.
2018-11-22 07:06:01.440 1993-1993/? D/OADB-HLPR: onCreate completed.
2018-11-22 07:06:01.443 1993-1993/? D/OADB-HLPR: logDatabaseTableInformation initiated.
2018-11-22 07:06:01.444 1993-1993/? D/OADB-HLPR: Database contains Table shops created by SQL CREATE TABLE shops (_id INTEGER PRIMARY KEY , shopname TEXT , shoporder INTEGER DEFAULT 100 , shopstreet TEXT , shopcity TEXT , shopstate TEXT , shopphone TEXT , shopnotes TEXT )
2018-11-22 07:06:01.445 1993-1993/? D/OADB-HLPR: Table is shops Column Count = 8 Row Count = 4
2018-11-22 07:06:01.445 1993-1993/? D/OADB-HLPR: Columns are :- _id shopname shoporder shopstreet shopcity shopstate shopphone shopnotes
2018-11-22 07:06:01.446 1993-1993/? D/OADB-HLPR: Database contains Table aisles created by SQL CREATE TABLE aisles (_id INTEGER PRIMARY KEY , aislename TEXT , aisleorder INTEGER DEFAULT 100 , aisleshopref INTEGER )
2018-11-22 07:06:01.448 1993-1993/? D/OADB-HLPR: Table is aisles Column Count = 4 Row Count = 20
2018-11-22 07:06:01.448 1993-1993/? D/OADB-HLPR: Columns are :- _id aislename aisleorder aisleshopref
2018-11-22 07:06:01.448 1993-1993/? D/OADB-HLPR: Database contains Table products created by SQL CREATE TABLE products (_id INTEGER PRIMARY KEY , productname TEXT , productorder INTEGER DEFAULT 100 , productaisleref INTEGER , productuses INTEGER DEFAULT 0 , productnotes TEXT )
2018-11-22 07:06:01.449 1993-1993/? D/OADB-HLPR: Table is products Column Count = 6 Row Count = 10
2018-11-22 07:06:01.449 1993-1993/? D/OADB-HLPR: Columns are :- _id productname productorder productaisleref productuses productnotes
2018-11-22 07:06:01.449 1993-1993/? D/OADB-HLPR: Database contains Table productusage created by SQL CREATE TABLE productusage (productailseref INTEGER , productproductref INTEGER , productcost REAL DEFAULT 1.00 , productbuycount INTEGER DEFAULT 0 , productfirstbuydate INTEGER DEFAULT 0 , productlatestbuydate INTEGER DEFAULT 0 , mincost REAL , PRIMARY KEY (productailseref, productproductref))
2018-11-22 07:06:01.451 1993-1993/? D/OADB-HLPR: Table is productusage Column Count = 7 Row Count = 20
2018-11-22 07:06:01.451 1993-1993/? D/OADB-HLPR: Columns are :- productailseref productproductref productcost productbuycount productfirstbuydate productlatestbuydate mincost
2018-11-22 07:06:01.451 1993-1993/? D/OADB-HLPR: Database contains Table rules created by SQL CREATE TABLE rules (ruleid INTEGER PRIMARY KEY , rulename TEXT , ruletype INTEGER , rulepromptflag INTEGER , ruleperiod INTEGER , rulemultiplier INTEGER , ruleactiveon INTEGER , ruleproductref INTEGER , ruleaisleref INTEGER )
2018-11-22 07:06:01.452 1993-1993/? D/OADB-HLPR: Table is rules Column Count = 9 Row Count = 0
2018-11-22 07:06:01.452 1993-1993/? D/OADB-HLPR: Columns are :- ruleid rulename ruletype rulepromptflag ruleperiod rulemultiplier ruleactiveon ruleproductref ruleaisleref
2018-11-22 07:06:01.452 1993-1993/? D/OADB-HLPR: Database contains Table shoplist created by SQL CREATE TABLE "shoplist" ("_id" INTEGER PRIMARY KEY NOT NULL , "productref" INTEGER, "dateadded" INTEGER, "numbertoget" INTEGER, "done" BOOL, "dategot" INTEGER, "cost" REAL, "productusageref" INTEGER, "aisleref" INTEGER)
2018-11-22 07:06:01.453 1993-1993/? D/OADB-HLPR: Table is shoplist Column Count = 9 Row Count = 4
2018-11-22 07:06:01.454 1993-1993/? D/OADB-HLPR: Columns are :- _id productref dateadded numbertoget done dategot cost productusageref aisleref
2018-11-22 07:06:01.454 1993-1993/? D/OADB-HLPR: logDatabaseTableInformation completed.
2018-11-22 07:06:01.454 1993-1993/? D/OADB-HLPR: OpenAssetDBHelper constructed.
I tester your database adapter and it is working. I will investigate my own code later. Thank you very much for your reply!
– Ulrich_Peters
Nov 26 '18 at 15:54
Ok. Somehow it is not working anymore. I simply get an D/OADB-HLPR: copyDatabaseFromAssets Did not locate asset NewDATABASE.db even though i have NewDATABASE.db in my assets folder.
– Ulrich_Peters
Nov 29 '18 at 5:58
@Ulrich_Peters, I've added an explanatory answer (had to add another due to size restriction). I would initially suspect that you have specified a directory but not placed the asset in the directory or vice-versa. What you have/have not specified will be in the log before and after the line you have shown (there's no way that that is the only line in the log, unless you've made numerous changes)
– MikeT
Nov 29 '18 at 8:22
@Ulrich_Peters also note that file and directory names are case dependant.
– MikeT
Nov 29 '18 at 8:59
add a comment |
The problem with the code you have is that numerous exceptions are caught by using throws IOException
and then you just issue a generic exception.
Whilst there could be a number of underlying causes.
It could be that asset itself doesn't exist where it's expected (in the assets folder (e.g. not in the databases directory (SQLiteAssetHelper uses this directory))).
It could be that the databases folder, within the package doesn't exist (use mkdirs on the DB_PATH). e.g. have something like :-
private boolean checkDatabase {
File db = new File(mContext.getDatabasePath(DB_NAME).getPath());
if(db.exists()) return true;
File dir = new File(db.getParent());
if (!dir.exists()) {
dir.mkdirs();
}
return false;
}
- Note the use of the Context's getDatabasePath
The following is code that is very long but provides very comprehensive logging (it also caters for multiple databases (up to 10 by default) and is also caters for directories in the assets folder).
/**
* Database Helper that includes ability to open database from assets
* if the database doesn't exist.
* (i.e. a pre-defined database)
*
*/
public class OpenAssetDBHelper extends SQLiteOpenHelper {
private static final String LOGTAG = "OADB-HLPR";
public static final int MAXIMUM_HELPERS = 10;
private String mDBPath, mAssetPath;
private static OpenAssetDBHelper mInstance = new OpenAssetDBHelper[MAXIMUM_HELPERS];
private SQLiteDatabase mDB;
/**
* OpenAssetDBHelper Class that will copy a predefined database
* from the assets folder and then open it is the database;
*
* The copy will only be done if the database does not exist.
*
* Note this code is intended to be used for development and/or
* experimentation, hence the extensive logging.
*/
/**
* get an OpenAssetDBHelper instance as a singleton;
* Note! caters for up to 10 OpenAssetDBHelpers for up to 10 databases
* as specified by the helper_index
*
* @param helper_index Index to this instance/database
* (0-MAXIMUM_HELPERS less 1)
* @param context Context for the database
* @param database Database name (i.e. file name)
* @param dbversion Database version (user_version)
* @param assetfile Name of the asset file to be copied to the database
* @param asset_sub_directories String Array of the sub-directories where
* the asset file is located;
* MUST be in order
* @return The resultant OpenAssetDBHelper
*/
public static synchronized OpenAssetDBHelper getInstance(
int helper_index,
Context context,
String database,
int dbversion,
String assetfile,
String asset_sub_directories) {
// Checck that helper_index is within bounds
if (helper_index > (MAXIMUM_HELPERS -1)) {
throw new RuntimeException(
"Helper Index greater than " +
MAXIMUM_HELPERS
);
}
if (helper_index < 0) {
throw new RuntimeException(
"Helper Index cannot be negative, must be 0-" +
MAXIMUM_HELPERS
);
}
// Create the respective OpenAssetDBHelper instance
if(mInstance[helper_index] == null) {
mInstance[helper_index] = new OpenAssetDBHelper(context,
database,
dbversion,
assetfile,
asset_sub_directories);
}
return mInstance[helper_index];
}
/**
* Construct an OpenAssetDBHelper instance;
* Note! can only be called within class
*
* @param context the context to be used
* @param database the database name (equates to filename)
* @param dbversion the databaae version (user_version)
* @param assetfile The name of the asset file i.e. the pre-defined db
* @param directories The hierarchy of directories within the assets folder
* where the asset file is located
* (null or zero elements = in the assets folder)
*/
private OpenAssetDBHelper(Context context,
String database,
int dbversion,
String assetfile,
String directories) {
super(context, database, null, dbversion);
Log.d(LOGTAG,"OpenAssetDBHelper being constructed.");
mDBPath = context.getDatabasePath(database).getPath();
if (assetfile == null || assetfile.length() < 1) {
assetfile = database;
}
mAssetPath = buildAssetPath(directories,assetfile);
if (!ifDatabaseExists(mDBPath)) {
Log.d(LOGTAG,"Database " + database + " not found at " + mDBPath + " so attempting to copy from assets.");
if (copyDatabaseFromAssets(context,mDBPath, database, mAssetPath)) {
Log.d(LOGTAG, "Successfully Copied Database from Assets.");
} else {
throw new RuntimeException("No Database Available.");
}
}
// Force Database open and store it
this.mDB = this.getWritableDatabase();
logDatabaseTableInformation(mDB);
Log.d(LOGTAG,"OpenAssetDBHelper constructed.");
}
/**
* onCreate - This is where you would create tables;
* Typically this is where you would alter the structure of the database;
* Note that this is called once for the lifetime of the database.
* @param db The SQLitedatabase
*/
@Override
public void onCreate(SQLiteDatabase db) {
Log.d(LOGTAG,new Object(){}.getClass().getEnclosingMethod().getName() + " initiated.");
// As Database is copied from assets nothing to do in onCreate!
Log.d(LOGTAG,new Object(){}.getClass().getEnclosingMethod().getName() + " completed.");
}
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
Log.d(LOGTAG,new Object(){}.getClass().getEnclosingMethod().getName() + " initiated.");
// Nothing to do as it's early days in the Database's lifetime.
Log.d(LOGTAG,new Object(){}.getClass().getEnclosingMethod().getName() + " completed.");
}
/**
* Check to see if the Database exists,
* if it doesn't exists then check to see if
* the database directory exists,
* if the directory(ies) does(do) not exist then make the directory(ies);
*
*
* @param dbpath The path to the database
* @return true if the database exists, else false
*/
private boolean ifDatabaseExists(String dbpath) {
Log.d(LOGTAG,new Object(){}.getClass().getEnclosingMethod().getName() + " initiated.");
File db = new File(dbpath);
if(db.exists()) return true;
File dir = new File(db.getParent());
if (!dir.exists()) {
dir.mkdirs();
}
return false;
}
/**
* Copy the Database from the assets folder
* @param context
* @param dbpath
* @return
*/
private boolean copyDatabaseFromAssets(Context context,String dbpath, String dbname, String asset) {
String thisclass = new Object(){}.getClass().getEnclosingMethod().getName();
Log.d(LOGTAG,thisclass + " initiated");
InputStream assetsdb;
OutputStream database;
File db = new File(dbpath);
int filesize;
// Get the asset file
try {
Log.d(LOGTAG,thisclass + " attempting to find asset " + asset);
assetsdb = context.getAssets().open(asset);
filesize = assetsdb.available();
Log.d(LOGTAG,thisclass + " asset " + asset +
" located successfully with a size of " +
Integer.toString(filesize)
);
} catch (IOException e) {
Log.d(LOGTAG,thisclass + " Did not locate asset " + asset);
e.printStackTrace();
return false;
}
// Read the first 16 bytes from the asset file
byte dbcheck = new byte[16];
try {
assetsdb.read(dbcheck,0,16);
} catch (IOException e) {
Log.d(LOGTAG, thisclass + " failed trying to read 16 bytes to check for a valid database. ");
e.printStackTrace();
return false;
}
// Check that the asset file is an SQLite database
String chkdb = new String(dbcheck);
if(!chkdb.equals("SQLite format 3u0000")) {
Log.d(LOGTAG,thisclass + " asset " +
asset +
" is not a valid SQLite Database File (found " +
chkdb +
" at bytes 1-16 instead of SQLite format 3)");
try {
assetsdb.close();
} catch (IOException e) {
// Not worth doing anything
}
return false;
}
// Close the asset file
try {
assetsdb.close();
} catch (IOException e) {
Log.d(LOGTAG,thisclass +
" failed to close assets file after checking for a valid database."
);
return false;
}
// Re-open the asset file
try {
assetsdb = context.getAssets().open(asset);
filesize = assetsdb.available();
} catch (IOException e) {
Log.d(LOGTAG, thisclass +
" failed trying to re-open asset " +
asset +
" after checking for a valid database."
);
e.printStackTrace();
return false;
}
// Read the entire asset file into a buffer
Log.d(LOGTAG, thisclass +
" copying asset database " +
dbname +
" into buffer of size " +
filesize
);
byte buffer = new byte[filesize];
// Close the asset file
try {
assetsdb.read(buffer);
Log.d(LOGTAG,thisclass +
" closing asset database " + dbname
);
assetsdb.close();
} catch (IOException e) {
Log.d(LOGTAG, thisclass +
" failed while copying asset database " +
dbname +
" (or closing asset database)."
);
e.printStackTrace();
return false;
}
// Open the new database file
try {
Log.d(LOGTAG,thisclass + " attempting to open new database file " + dbpath);
database = new FileOutputStream(dbpath);
} catch (IOException e) {
Log.d(LOGTAG, thisclass + " failed to open new database file.");
e.printStackTrace();
return false;
}
// Write the new database file
try {
Log.d(LOGTAG, thisclass + " writing new database file " + dbpath);
database.write(buffer);
} catch (IOException e) {
Log.d(LOGTAG, thisclass + " failed while writing new database file " + dbpath);
e.printStackTrace();
return false;
}
// Flush the new database file
try {
Log.d(LOGTAG, thisclass + " flushing new database file " + dbpath);
database.flush();
} catch (IOException e) {
Log.d(LOGTAG, thisclass + " failed while flushing new database file " + dbpath);
e.printStackTrace();
return false;
}
// Close the new database file
try {
Log.d(LOGTAG, thisclass + " closing new database file " + dbpath);
database.close();
} catch (IOException e) {
Log.d(LOGTAG, thisclass + " failed while closing new database file " + dbpath);
e.printStackTrace();
return false;
}
Log.d(LOGTAG,new Object(){}.getClass().getEnclosingMethod().getName() + " completed.");
return true;
}
/**
* Log Database table Information
*/
private void logDatabaseTableInformation(SQLiteDatabase db) {
Log.d(LOGTAG,new Object(){}.getClass().getEnclosingMethod().getName() + " initiated.");
String mastertable = "sqlite_master";
String typecolumn = "type";
String namecolumn = "name";
String sqlcolumn = "sql";
String args = new String{"table","android_metadata"};
Cursor csr = db.query(mastertable,
null,
typecolumn + "=? AND " + namecolumn + "!=?",
args,
null,null,null
);
while (csr.moveToNext()) {
Log.d(LOGTAG,"Database contains Table " +
csr.getString(csr.getColumnIndex(namecolumn)) +
" created by SQL " +
csr.getString(csr.getColumnIndex(sqlcolumn))
);
logTableInformation(db, csr.getString(csr.getColumnIndex(namecolumn)));
}
csr.close();
Log.d(LOGTAG,new Object(){}.getClass().getEnclosingMethod().getName() + " completed.");
}
/**
* Write Table information, Table name, Column Count,
* Row Count and Column Names to the Log
* @param table Name of the table to be reported on
*/
private void logTableInformation(SQLiteDatabase db, String table) {
Cursor csr = db.query(table,
null,
null,
null,
null,
null,
null
);
Log.d(LOGTAG,"Table is " +
table +
" Column Count = " +
Integer.toString(csr.getColumnCount()) +
" Row Count = " +
Long.toString(DatabaseUtils.queryNumEntries(mDB,table))
);
StringBuilder columns_as_string = new StringBuilder();
for (String s: csr.getColumnNames()) {
columns_as_string.append(s).append(" ");
}
Log.d(LOGTAG, "tColumns are :- " + columns_as_string);
csr.close();
}
/**
* Build the sub-path to the asset, according to the directories specified
*
* @param directories directories underneath the assets folder where
* the asset files is located, null or empty
* array if file is located directly in the
* assets folder;
* directories must be specified in the order
* in which they appear in the path.
* @param filename The filename of the asset
* @return The fill sub-path to the asset
*/
private String buildAssetPath(String directories, String filename) {
StringBuilder sb = new StringBuilder();
final String SEPERATOR = "/";
if (directories != null && directories.length > 0) {
for (String s: directories) {
sb.append(s);
if (!s.substring(s.length()-1,s.length()).equals(SEPERATOR)) {
sb.append(SEPERATOR);
}
}
sb.append(filename);
return sb.toString();
} else {
return filename;
}
}
}
Example Usage
public class MainActivity extends AppCompatActivity {
public static final int DBVERSION = 1;
public static final String DBNAME1 = "openassetdb.db";
public static final int DB1_INDEX = 0;
public static final String DBNAME2 = "myshopping";
public static final int DB2_INDEX = 1;
OpenAssetDBHelper mOADBHlpr;
OpenAssetDBHelper mShoppingHelper;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// Example 1 - Database file located in the assets folder and
// database name same as file name
mOADBHlpr = OpenAssetDBHelper.getInstance(DB1_INDEX,
this,
DBNAME1,
DBVERSION,
DBNAME1,
null
);
// Example 2 - Database file in databases directory of the assets folder
// database name different to the asset filename
mShoppingHelper = OpenAssetDBHelper.getInstance(DB2_INDEX,
this,
DBNAME2,
DBVERSION,
"shopper",
new String{"databases"}
);
}
}
Result (when no databases exist) :-
2018-11-22 07:06:01.408 1993-1993/? D/OADB-HLPR: OpenAssetDBHelper being constructed.
2018-11-22 07:06:01.408 1993-1993/? D/OADB-HLPR: ifDatabaseExists initiated.
2018-11-22 07:06:01.408 1993-1993/? D/OADB-HLPR: Database openassetdb.db not found at /data/user/0/mjt.openassetdb/databases/openassetdb.db so attempting to copy from assets.
2018-11-22 07:06:01.409 1993-1993/? D/OADB-HLPR: copyDatabaseFromAssets initiated
2018-11-22 07:06:01.409 1993-1993/? D/OADB-HLPR: copyDatabaseFromAssets attempting to find asset openassetdb.db
2018-11-22 07:06:01.409 1993-1993/? D/OADB-HLPR: copyDatabaseFromAssets asset openassetdb.db located successfully with a size of 12288
2018-11-22 07:06:01.409 1993-1993/? D/OADB-HLPR: copyDatabaseFromAssets copying asset database openassetdb.db into buffer of size 12288
2018-11-22 07:06:01.409 1993-1993/? D/OADB-HLPR: copyDatabaseFromAssets closing asset database openassetdb.db
2018-11-22 07:06:01.409 1993-1993/? D/OADB-HLPR: copyDatabaseFromAssets attempting to open new database file /data/user/0/mjt.openassetdb/databases/openassetdb.db
2018-11-22 07:06:01.410 1993-1993/? D/OADB-HLPR: copyDatabaseFromAssets writing new database file /data/user/0/mjt.openassetdb/databases/openassetdb.db
2018-11-22 07:06:01.410 1993-1993/? D/OADB-HLPR: copyDatabaseFromAssets flushing new database file /data/user/0/mjt.openassetdb/databases/openassetdb.db
2018-11-22 07:06:01.410 1993-1993/? D/OADB-HLPR: copyDatabaseFromAssets closing new database file /data/user/0/mjt.openassetdb/databases/openassetdb.db
2018-11-22 07:06:01.410 1993-1993/? D/OADB-HLPR: copyDatabaseFromAssets completed.
2018-11-22 07:06:01.410 1993-1993/? D/OADB-HLPR: Successfully Copied Database from Assets.
2018-11-22 07:06:01.421 1993-1993/? D/OADB-HLPR: onCreate initiated.
2018-11-22 07:06:01.421 1993-1993/? D/OADB-HLPR: onCreate completed.
2018-11-22 07:06:01.425 1993-1993/? D/OADB-HLPR: logDatabaseTableInformation initiated.
2018-11-22 07:06:01.426 1993-1993/? D/OADB-HLPR: Database contains Table testtable created by SQL CREATE TABLE `testtable` (
`_id` INTEGER PRIMARY KEY AUTOINCREMENT,
`name` TEXT,
`timestamp` INTEGER
)
2018-11-22 07:06:01.426 1993-1993/? D/OADB-HLPR: Table is testtable Column Count = 3 Row Count = 2
2018-11-22 07:06:01.426 1993-1993/? D/OADB-HLPR: Columns are :- _id name timestamp
2018-11-22 07:06:01.426 1993-1993/? D/OADB-HLPR: Database contains Table sqlite_sequence created by SQL CREATE TABLE sqlite_sequence(name,seq)
2018-11-22 07:06:01.427 1993-1993/? D/OADB-HLPR: Table is sqlite_sequence Column Count = 2 Row Count = 1
2018-11-22 07:06:01.427 1993-1993/? D/OADB-HLPR: Columns are :- name seq
2018-11-22 07:06:01.427 1993-1993/? D/OADB-HLPR: logDatabaseTableInformation completed.
(2nd)
2018-11-22 07:06:01.427 1993-1993/? D/OADB-HLPR: OpenAssetDBHelper constructed.
2018-11-22 07:06:01.427 1993-1993/? D/OADB-HLPR: OpenAssetDBHelper being constructed.
2018-11-22 07:06:01.427 1993-1993/? D/OADB-HLPR: ifDatabaseExists initiated.
2018-11-22 07:06:01.428 1993-1993/? D/OADB-HLPR: Database myshopping not found at /data/user/0/mjt.openassetdb/databases/myshopping so attempting to copy from assets.
2018-11-22 07:06:01.428 1993-1993/? D/OADB-HLPR: copyDatabaseFromAssets initiated
2018-11-22 07:06:01.428 1993-1993/? D/OADB-HLPR: copyDatabaseFromAssets attempting to find asset databases/shopper
2018-11-22 07:06:01.428 1993-1993/? D/OADB-HLPR: copyDatabaseFromAssets asset databases/shopper located successfully with a size of 262144
2018-11-22 07:06:01.428 1993-1993/? D/OADB-HLPR: copyDatabaseFromAssets copying asset database myshopping into buffer of size 262144
2018-11-22 07:06:01.429 1993-1993/? D/OADB-HLPR: copyDatabaseFromAssets closing asset database myshopping
2018-11-22 07:06:01.429 1993-1993/? D/OADB-HLPR: copyDatabaseFromAssets attempting to open new database file /data/user/0/mjt.openassetdb/databases/myshopping
2018-11-22 07:06:01.429 1993-1993/? D/OADB-HLPR: copyDatabaseFromAssets writing new database file /data/user/0/mjt.openassetdb/databases/myshopping
2018-11-22 07:06:01.429 1993-1993/? D/OADB-HLPR: copyDatabaseFromAssets flushing new database file /data/user/0/mjt.openassetdb/databases/myshopping
2018-11-22 07:06:01.429 1993-1993/? D/OADB-HLPR: copyDatabaseFromAssets closing new database file /data/user/0/mjt.openassetdb/databases/myshopping
2018-11-22 07:06:01.429 1993-1993/? D/OADB-HLPR: copyDatabaseFromAssets completed.
2018-11-22 07:06:01.429 1993-1993/? D/OADB-HLPR: Successfully Copied Database from Assets.
2018-11-22 07:06:01.440 1993-1993/? D/OADB-HLPR: onCreate initiated.
2018-11-22 07:06:01.440 1993-1993/? D/OADB-HLPR: onCreate completed.
2018-11-22 07:06:01.443 1993-1993/? D/OADB-HLPR: logDatabaseTableInformation initiated.
2018-11-22 07:06:01.444 1993-1993/? D/OADB-HLPR: Database contains Table shops created by SQL CREATE TABLE shops (_id INTEGER PRIMARY KEY , shopname TEXT , shoporder INTEGER DEFAULT 100 , shopstreet TEXT , shopcity TEXT , shopstate TEXT , shopphone TEXT , shopnotes TEXT )
2018-11-22 07:06:01.445 1993-1993/? D/OADB-HLPR: Table is shops Column Count = 8 Row Count = 4
2018-11-22 07:06:01.445 1993-1993/? D/OADB-HLPR: Columns are :- _id shopname shoporder shopstreet shopcity shopstate shopphone shopnotes
2018-11-22 07:06:01.446 1993-1993/? D/OADB-HLPR: Database contains Table aisles created by SQL CREATE TABLE aisles (_id INTEGER PRIMARY KEY , aislename TEXT , aisleorder INTEGER DEFAULT 100 , aisleshopref INTEGER )
2018-11-22 07:06:01.448 1993-1993/? D/OADB-HLPR: Table is aisles Column Count = 4 Row Count = 20
2018-11-22 07:06:01.448 1993-1993/? D/OADB-HLPR: Columns are :- _id aislename aisleorder aisleshopref
2018-11-22 07:06:01.448 1993-1993/? D/OADB-HLPR: Database contains Table products created by SQL CREATE TABLE products (_id INTEGER PRIMARY KEY , productname TEXT , productorder INTEGER DEFAULT 100 , productaisleref INTEGER , productuses INTEGER DEFAULT 0 , productnotes TEXT )
2018-11-22 07:06:01.449 1993-1993/? D/OADB-HLPR: Table is products Column Count = 6 Row Count = 10
2018-11-22 07:06:01.449 1993-1993/? D/OADB-HLPR: Columns are :- _id productname productorder productaisleref productuses productnotes
2018-11-22 07:06:01.449 1993-1993/? D/OADB-HLPR: Database contains Table productusage created by SQL CREATE TABLE productusage (productailseref INTEGER , productproductref INTEGER , productcost REAL DEFAULT 1.00 , productbuycount INTEGER DEFAULT 0 , productfirstbuydate INTEGER DEFAULT 0 , productlatestbuydate INTEGER DEFAULT 0 , mincost REAL , PRIMARY KEY (productailseref, productproductref))
2018-11-22 07:06:01.451 1993-1993/? D/OADB-HLPR: Table is productusage Column Count = 7 Row Count = 20
2018-11-22 07:06:01.451 1993-1993/? D/OADB-HLPR: Columns are :- productailseref productproductref productcost productbuycount productfirstbuydate productlatestbuydate mincost
2018-11-22 07:06:01.451 1993-1993/? D/OADB-HLPR: Database contains Table rules created by SQL CREATE TABLE rules (ruleid INTEGER PRIMARY KEY , rulename TEXT , ruletype INTEGER , rulepromptflag INTEGER , ruleperiod INTEGER , rulemultiplier INTEGER , ruleactiveon INTEGER , ruleproductref INTEGER , ruleaisleref INTEGER )
2018-11-22 07:06:01.452 1993-1993/? D/OADB-HLPR: Table is rules Column Count = 9 Row Count = 0
2018-11-22 07:06:01.452 1993-1993/? D/OADB-HLPR: Columns are :- ruleid rulename ruletype rulepromptflag ruleperiod rulemultiplier ruleactiveon ruleproductref ruleaisleref
2018-11-22 07:06:01.452 1993-1993/? D/OADB-HLPR: Database contains Table shoplist created by SQL CREATE TABLE "shoplist" ("_id" INTEGER PRIMARY KEY NOT NULL , "productref" INTEGER, "dateadded" INTEGER, "numbertoget" INTEGER, "done" BOOL, "dategot" INTEGER, "cost" REAL, "productusageref" INTEGER, "aisleref" INTEGER)
2018-11-22 07:06:01.453 1993-1993/? D/OADB-HLPR: Table is shoplist Column Count = 9 Row Count = 4
2018-11-22 07:06:01.454 1993-1993/? D/OADB-HLPR: Columns are :- _id productref dateadded numbertoget done dategot cost productusageref aisleref
2018-11-22 07:06:01.454 1993-1993/? D/OADB-HLPR: logDatabaseTableInformation completed.
2018-11-22 07:06:01.454 1993-1993/? D/OADB-HLPR: OpenAssetDBHelper constructed.
I tester your database adapter and it is working. I will investigate my own code later. Thank you very much for your reply!
– Ulrich_Peters
Nov 26 '18 at 15:54
Ok. Somehow it is not working anymore. I simply get an D/OADB-HLPR: copyDatabaseFromAssets Did not locate asset NewDATABASE.db even though i have NewDATABASE.db in my assets folder.
– Ulrich_Peters
Nov 29 '18 at 5:58
@Ulrich_Peters, I've added an explanatory answer (had to add another due to size restriction). I would initially suspect that you have specified a directory but not placed the asset in the directory or vice-versa. What you have/have not specified will be in the log before and after the line you have shown (there's no way that that is the only line in the log, unless you've made numerous changes)
– MikeT
Nov 29 '18 at 8:22
@Ulrich_Peters also note that file and directory names are case dependant.
– MikeT
Nov 29 '18 at 8:59
add a comment |
The problem with the code you have is that numerous exceptions are caught by using throws IOException
and then you just issue a generic exception.
Whilst there could be a number of underlying causes.
It could be that asset itself doesn't exist where it's expected (in the assets folder (e.g. not in the databases directory (SQLiteAssetHelper uses this directory))).
It could be that the databases folder, within the package doesn't exist (use mkdirs on the DB_PATH). e.g. have something like :-
private boolean checkDatabase {
File db = new File(mContext.getDatabasePath(DB_NAME).getPath());
if(db.exists()) return true;
File dir = new File(db.getParent());
if (!dir.exists()) {
dir.mkdirs();
}
return false;
}
- Note the use of the Context's getDatabasePath
The following is code that is very long but provides very comprehensive logging (it also caters for multiple databases (up to 10 by default) and is also caters for directories in the assets folder).
/**
* Database Helper that includes ability to open database from assets
* if the database doesn't exist.
* (i.e. a pre-defined database)
*
*/
public class OpenAssetDBHelper extends SQLiteOpenHelper {
private static final String LOGTAG = "OADB-HLPR";
public static final int MAXIMUM_HELPERS = 10;
private String mDBPath, mAssetPath;
private static OpenAssetDBHelper mInstance = new OpenAssetDBHelper[MAXIMUM_HELPERS];
private SQLiteDatabase mDB;
/**
* OpenAssetDBHelper Class that will copy a predefined database
* from the assets folder and then open it is the database;
*
* The copy will only be done if the database does not exist.
*
* Note this code is intended to be used for development and/or
* experimentation, hence the extensive logging.
*/
/**
* get an OpenAssetDBHelper instance as a singleton;
* Note! caters for up to 10 OpenAssetDBHelpers for up to 10 databases
* as specified by the helper_index
*
* @param helper_index Index to this instance/database
* (0-MAXIMUM_HELPERS less 1)
* @param context Context for the database
* @param database Database name (i.e. file name)
* @param dbversion Database version (user_version)
* @param assetfile Name of the asset file to be copied to the database
* @param asset_sub_directories String Array of the sub-directories where
* the asset file is located;
* MUST be in order
* @return The resultant OpenAssetDBHelper
*/
public static synchronized OpenAssetDBHelper getInstance(
int helper_index,
Context context,
String database,
int dbversion,
String assetfile,
String asset_sub_directories) {
// Checck that helper_index is within bounds
if (helper_index > (MAXIMUM_HELPERS -1)) {
throw new RuntimeException(
"Helper Index greater than " +
MAXIMUM_HELPERS
);
}
if (helper_index < 0) {
throw new RuntimeException(
"Helper Index cannot be negative, must be 0-" +
MAXIMUM_HELPERS
);
}
// Create the respective OpenAssetDBHelper instance
if(mInstance[helper_index] == null) {
mInstance[helper_index] = new OpenAssetDBHelper(context,
database,
dbversion,
assetfile,
asset_sub_directories);
}
return mInstance[helper_index];
}
/**
* Construct an OpenAssetDBHelper instance;
* Note! can only be called within class
*
* @param context the context to be used
* @param database the database name (equates to filename)
* @param dbversion the databaae version (user_version)
* @param assetfile The name of the asset file i.e. the pre-defined db
* @param directories The hierarchy of directories within the assets folder
* where the asset file is located
* (null or zero elements = in the assets folder)
*/
private OpenAssetDBHelper(Context context,
String database,
int dbversion,
String assetfile,
String directories) {
super(context, database, null, dbversion);
Log.d(LOGTAG,"OpenAssetDBHelper being constructed.");
mDBPath = context.getDatabasePath(database).getPath();
if (assetfile == null || assetfile.length() < 1) {
assetfile = database;
}
mAssetPath = buildAssetPath(directories,assetfile);
if (!ifDatabaseExists(mDBPath)) {
Log.d(LOGTAG,"Database " + database + " not found at " + mDBPath + " so attempting to copy from assets.");
if (copyDatabaseFromAssets(context,mDBPath, database, mAssetPath)) {
Log.d(LOGTAG, "Successfully Copied Database from Assets.");
} else {
throw new RuntimeException("No Database Available.");
}
}
// Force Database open and store it
this.mDB = this.getWritableDatabase();
logDatabaseTableInformation(mDB);
Log.d(LOGTAG,"OpenAssetDBHelper constructed.");
}
/**
* onCreate - This is where you would create tables;
* Typically this is where you would alter the structure of the database;
* Note that this is called once for the lifetime of the database.
* @param db The SQLitedatabase
*/
@Override
public void onCreate(SQLiteDatabase db) {
Log.d(LOGTAG,new Object(){}.getClass().getEnclosingMethod().getName() + " initiated.");
// As Database is copied from assets nothing to do in onCreate!
Log.d(LOGTAG,new Object(){}.getClass().getEnclosingMethod().getName() + " completed.");
}
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
Log.d(LOGTAG,new Object(){}.getClass().getEnclosingMethod().getName() + " initiated.");
// Nothing to do as it's early days in the Database's lifetime.
Log.d(LOGTAG,new Object(){}.getClass().getEnclosingMethod().getName() + " completed.");
}
/**
* Check to see if the Database exists,
* if it doesn't exists then check to see if
* the database directory exists,
* if the directory(ies) does(do) not exist then make the directory(ies);
*
*
* @param dbpath The path to the database
* @return true if the database exists, else false
*/
private boolean ifDatabaseExists(String dbpath) {
Log.d(LOGTAG,new Object(){}.getClass().getEnclosingMethod().getName() + " initiated.");
File db = new File(dbpath);
if(db.exists()) return true;
File dir = new File(db.getParent());
if (!dir.exists()) {
dir.mkdirs();
}
return false;
}
/**
* Copy the Database from the assets folder
* @param context
* @param dbpath
* @return
*/
private boolean copyDatabaseFromAssets(Context context,String dbpath, String dbname, String asset) {
String thisclass = new Object(){}.getClass().getEnclosingMethod().getName();
Log.d(LOGTAG,thisclass + " initiated");
InputStream assetsdb;
OutputStream database;
File db = new File(dbpath);
int filesize;
// Get the asset file
try {
Log.d(LOGTAG,thisclass + " attempting to find asset " + asset);
assetsdb = context.getAssets().open(asset);
filesize = assetsdb.available();
Log.d(LOGTAG,thisclass + " asset " + asset +
" located successfully with a size of " +
Integer.toString(filesize)
);
} catch (IOException e) {
Log.d(LOGTAG,thisclass + " Did not locate asset " + asset);
e.printStackTrace();
return false;
}
// Read the first 16 bytes from the asset file
byte dbcheck = new byte[16];
try {
assetsdb.read(dbcheck,0,16);
} catch (IOException e) {
Log.d(LOGTAG, thisclass + " failed trying to read 16 bytes to check for a valid database. ");
e.printStackTrace();
return false;
}
// Check that the asset file is an SQLite database
String chkdb = new String(dbcheck);
if(!chkdb.equals("SQLite format 3u0000")) {
Log.d(LOGTAG,thisclass + " asset " +
asset +
" is not a valid SQLite Database File (found " +
chkdb +
" at bytes 1-16 instead of SQLite format 3)");
try {
assetsdb.close();
} catch (IOException e) {
// Not worth doing anything
}
return false;
}
// Close the asset file
try {
assetsdb.close();
} catch (IOException e) {
Log.d(LOGTAG,thisclass +
" failed to close assets file after checking for a valid database."
);
return false;
}
// Re-open the asset file
try {
assetsdb = context.getAssets().open(asset);
filesize = assetsdb.available();
} catch (IOException e) {
Log.d(LOGTAG, thisclass +
" failed trying to re-open asset " +
asset +
" after checking for a valid database."
);
e.printStackTrace();
return false;
}
// Read the entire asset file into a buffer
Log.d(LOGTAG, thisclass +
" copying asset database " +
dbname +
" into buffer of size " +
filesize
);
byte buffer = new byte[filesize];
// Close the asset file
try {
assetsdb.read(buffer);
Log.d(LOGTAG,thisclass +
" closing asset database " + dbname
);
assetsdb.close();
} catch (IOException e) {
Log.d(LOGTAG, thisclass +
" failed while copying asset database " +
dbname +
" (or closing asset database)."
);
e.printStackTrace();
return false;
}
// Open the new database file
try {
Log.d(LOGTAG,thisclass + " attempting to open new database file " + dbpath);
database = new FileOutputStream(dbpath);
} catch (IOException e) {
Log.d(LOGTAG, thisclass + " failed to open new database file.");
e.printStackTrace();
return false;
}
// Write the new database file
try {
Log.d(LOGTAG, thisclass + " writing new database file " + dbpath);
database.write(buffer);
} catch (IOException e) {
Log.d(LOGTAG, thisclass + " failed while writing new database file " + dbpath);
e.printStackTrace();
return false;
}
// Flush the new database file
try {
Log.d(LOGTAG, thisclass + " flushing new database file " + dbpath);
database.flush();
} catch (IOException e) {
Log.d(LOGTAG, thisclass + " failed while flushing new database file " + dbpath);
e.printStackTrace();
return false;
}
// Close the new database file
try {
Log.d(LOGTAG, thisclass + " closing new database file " + dbpath);
database.close();
} catch (IOException e) {
Log.d(LOGTAG, thisclass + " failed while closing new database file " + dbpath);
e.printStackTrace();
return false;
}
Log.d(LOGTAG,new Object(){}.getClass().getEnclosingMethod().getName() + " completed.");
return true;
}
/**
* Log Database table Information
*/
private void logDatabaseTableInformation(SQLiteDatabase db) {
Log.d(LOGTAG,new Object(){}.getClass().getEnclosingMethod().getName() + " initiated.");
String mastertable = "sqlite_master";
String typecolumn = "type";
String namecolumn = "name";
String sqlcolumn = "sql";
String args = new String{"table","android_metadata"};
Cursor csr = db.query(mastertable,
null,
typecolumn + "=? AND " + namecolumn + "!=?",
args,
null,null,null
);
while (csr.moveToNext()) {
Log.d(LOGTAG,"Database contains Table " +
csr.getString(csr.getColumnIndex(namecolumn)) +
" created by SQL " +
csr.getString(csr.getColumnIndex(sqlcolumn))
);
logTableInformation(db, csr.getString(csr.getColumnIndex(namecolumn)));
}
csr.close();
Log.d(LOGTAG,new Object(){}.getClass().getEnclosingMethod().getName() + " completed.");
}
/**
* Write Table information, Table name, Column Count,
* Row Count and Column Names to the Log
* @param table Name of the table to be reported on
*/
private void logTableInformation(SQLiteDatabase db, String table) {
Cursor csr = db.query(table,
null,
null,
null,
null,
null,
null
);
Log.d(LOGTAG,"Table is " +
table +
" Column Count = " +
Integer.toString(csr.getColumnCount()) +
" Row Count = " +
Long.toString(DatabaseUtils.queryNumEntries(mDB,table))
);
StringBuilder columns_as_string = new StringBuilder();
for (String s: csr.getColumnNames()) {
columns_as_string.append(s).append(" ");
}
Log.d(LOGTAG, "tColumns are :- " + columns_as_string);
csr.close();
}
/**
* Build the sub-path to the asset, according to the directories specified
*
* @param directories directories underneath the assets folder where
* the asset files is located, null or empty
* array if file is located directly in the
* assets folder;
* directories must be specified in the order
* in which they appear in the path.
* @param filename The filename of the asset
* @return The fill sub-path to the asset
*/
private String buildAssetPath(String directories, String filename) {
StringBuilder sb = new StringBuilder();
final String SEPERATOR = "/";
if (directories != null && directories.length > 0) {
for (String s: directories) {
sb.append(s);
if (!s.substring(s.length()-1,s.length()).equals(SEPERATOR)) {
sb.append(SEPERATOR);
}
}
sb.append(filename);
return sb.toString();
} else {
return filename;
}
}
}
Example Usage
public class MainActivity extends AppCompatActivity {
public static final int DBVERSION = 1;
public static final String DBNAME1 = "openassetdb.db";
public static final int DB1_INDEX = 0;
public static final String DBNAME2 = "myshopping";
public static final int DB2_INDEX = 1;
OpenAssetDBHelper mOADBHlpr;
OpenAssetDBHelper mShoppingHelper;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// Example 1 - Database file located in the assets folder and
// database name same as file name
mOADBHlpr = OpenAssetDBHelper.getInstance(DB1_INDEX,
this,
DBNAME1,
DBVERSION,
DBNAME1,
null
);
// Example 2 - Database file in databases directory of the assets folder
// database name different to the asset filename
mShoppingHelper = OpenAssetDBHelper.getInstance(DB2_INDEX,
this,
DBNAME2,
DBVERSION,
"shopper",
new String{"databases"}
);
}
}
Result (when no databases exist) :-
2018-11-22 07:06:01.408 1993-1993/? D/OADB-HLPR: OpenAssetDBHelper being constructed.
2018-11-22 07:06:01.408 1993-1993/? D/OADB-HLPR: ifDatabaseExists initiated.
2018-11-22 07:06:01.408 1993-1993/? D/OADB-HLPR: Database openassetdb.db not found at /data/user/0/mjt.openassetdb/databases/openassetdb.db so attempting to copy from assets.
2018-11-22 07:06:01.409 1993-1993/? D/OADB-HLPR: copyDatabaseFromAssets initiated
2018-11-22 07:06:01.409 1993-1993/? D/OADB-HLPR: copyDatabaseFromAssets attempting to find asset openassetdb.db
2018-11-22 07:06:01.409 1993-1993/? D/OADB-HLPR: copyDatabaseFromAssets asset openassetdb.db located successfully with a size of 12288
2018-11-22 07:06:01.409 1993-1993/? D/OADB-HLPR: copyDatabaseFromAssets copying asset database openassetdb.db into buffer of size 12288
2018-11-22 07:06:01.409 1993-1993/? D/OADB-HLPR: copyDatabaseFromAssets closing asset database openassetdb.db
2018-11-22 07:06:01.409 1993-1993/? D/OADB-HLPR: copyDatabaseFromAssets attempting to open new database file /data/user/0/mjt.openassetdb/databases/openassetdb.db
2018-11-22 07:06:01.410 1993-1993/? D/OADB-HLPR: copyDatabaseFromAssets writing new database file /data/user/0/mjt.openassetdb/databases/openassetdb.db
2018-11-22 07:06:01.410 1993-1993/? D/OADB-HLPR: copyDatabaseFromAssets flushing new database file /data/user/0/mjt.openassetdb/databases/openassetdb.db
2018-11-22 07:06:01.410 1993-1993/? D/OADB-HLPR: copyDatabaseFromAssets closing new database file /data/user/0/mjt.openassetdb/databases/openassetdb.db
2018-11-22 07:06:01.410 1993-1993/? D/OADB-HLPR: copyDatabaseFromAssets completed.
2018-11-22 07:06:01.410 1993-1993/? D/OADB-HLPR: Successfully Copied Database from Assets.
2018-11-22 07:06:01.421 1993-1993/? D/OADB-HLPR: onCreate initiated.
2018-11-22 07:06:01.421 1993-1993/? D/OADB-HLPR: onCreate completed.
2018-11-22 07:06:01.425 1993-1993/? D/OADB-HLPR: logDatabaseTableInformation initiated.
2018-11-22 07:06:01.426 1993-1993/? D/OADB-HLPR: Database contains Table testtable created by SQL CREATE TABLE `testtable` (
`_id` INTEGER PRIMARY KEY AUTOINCREMENT,
`name` TEXT,
`timestamp` INTEGER
)
2018-11-22 07:06:01.426 1993-1993/? D/OADB-HLPR: Table is testtable Column Count = 3 Row Count = 2
2018-11-22 07:06:01.426 1993-1993/? D/OADB-HLPR: Columns are :- _id name timestamp
2018-11-22 07:06:01.426 1993-1993/? D/OADB-HLPR: Database contains Table sqlite_sequence created by SQL CREATE TABLE sqlite_sequence(name,seq)
2018-11-22 07:06:01.427 1993-1993/? D/OADB-HLPR: Table is sqlite_sequence Column Count = 2 Row Count = 1
2018-11-22 07:06:01.427 1993-1993/? D/OADB-HLPR: Columns are :- name seq
2018-11-22 07:06:01.427 1993-1993/? D/OADB-HLPR: logDatabaseTableInformation completed.
(2nd)
2018-11-22 07:06:01.427 1993-1993/? D/OADB-HLPR: OpenAssetDBHelper constructed.
2018-11-22 07:06:01.427 1993-1993/? D/OADB-HLPR: OpenAssetDBHelper being constructed.
2018-11-22 07:06:01.427 1993-1993/? D/OADB-HLPR: ifDatabaseExists initiated.
2018-11-22 07:06:01.428 1993-1993/? D/OADB-HLPR: Database myshopping not found at /data/user/0/mjt.openassetdb/databases/myshopping so attempting to copy from assets.
2018-11-22 07:06:01.428 1993-1993/? D/OADB-HLPR: copyDatabaseFromAssets initiated
2018-11-22 07:06:01.428 1993-1993/? D/OADB-HLPR: copyDatabaseFromAssets attempting to find asset databases/shopper
2018-11-22 07:06:01.428 1993-1993/? D/OADB-HLPR: copyDatabaseFromAssets asset databases/shopper located successfully with a size of 262144
2018-11-22 07:06:01.428 1993-1993/? D/OADB-HLPR: copyDatabaseFromAssets copying asset database myshopping into buffer of size 262144
2018-11-22 07:06:01.429 1993-1993/? D/OADB-HLPR: copyDatabaseFromAssets closing asset database myshopping
2018-11-22 07:06:01.429 1993-1993/? D/OADB-HLPR: copyDatabaseFromAssets attempting to open new database file /data/user/0/mjt.openassetdb/databases/myshopping
2018-11-22 07:06:01.429 1993-1993/? D/OADB-HLPR: copyDatabaseFromAssets writing new database file /data/user/0/mjt.openassetdb/databases/myshopping
2018-11-22 07:06:01.429 1993-1993/? D/OADB-HLPR: copyDatabaseFromAssets flushing new database file /data/user/0/mjt.openassetdb/databases/myshopping
2018-11-22 07:06:01.429 1993-1993/? D/OADB-HLPR: copyDatabaseFromAssets closing new database file /data/user/0/mjt.openassetdb/databases/myshopping
2018-11-22 07:06:01.429 1993-1993/? D/OADB-HLPR: copyDatabaseFromAssets completed.
2018-11-22 07:06:01.429 1993-1993/? D/OADB-HLPR: Successfully Copied Database from Assets.
2018-11-22 07:06:01.440 1993-1993/? D/OADB-HLPR: onCreate initiated.
2018-11-22 07:06:01.440 1993-1993/? D/OADB-HLPR: onCreate completed.
2018-11-22 07:06:01.443 1993-1993/? D/OADB-HLPR: logDatabaseTableInformation initiated.
2018-11-22 07:06:01.444 1993-1993/? D/OADB-HLPR: Database contains Table shops created by SQL CREATE TABLE shops (_id INTEGER PRIMARY KEY , shopname TEXT , shoporder INTEGER DEFAULT 100 , shopstreet TEXT , shopcity TEXT , shopstate TEXT , shopphone TEXT , shopnotes TEXT )
2018-11-22 07:06:01.445 1993-1993/? D/OADB-HLPR: Table is shops Column Count = 8 Row Count = 4
2018-11-22 07:06:01.445 1993-1993/? D/OADB-HLPR: Columns are :- _id shopname shoporder shopstreet shopcity shopstate shopphone shopnotes
2018-11-22 07:06:01.446 1993-1993/? D/OADB-HLPR: Database contains Table aisles created by SQL CREATE TABLE aisles (_id INTEGER PRIMARY KEY , aislename TEXT , aisleorder INTEGER DEFAULT 100 , aisleshopref INTEGER )
2018-11-22 07:06:01.448 1993-1993/? D/OADB-HLPR: Table is aisles Column Count = 4 Row Count = 20
2018-11-22 07:06:01.448 1993-1993/? D/OADB-HLPR: Columns are :- _id aislename aisleorder aisleshopref
2018-11-22 07:06:01.448 1993-1993/? D/OADB-HLPR: Database contains Table products created by SQL CREATE TABLE products (_id INTEGER PRIMARY KEY , productname TEXT , productorder INTEGER DEFAULT 100 , productaisleref INTEGER , productuses INTEGER DEFAULT 0 , productnotes TEXT )
2018-11-22 07:06:01.449 1993-1993/? D/OADB-HLPR: Table is products Column Count = 6 Row Count = 10
2018-11-22 07:06:01.449 1993-1993/? D/OADB-HLPR: Columns are :- _id productname productorder productaisleref productuses productnotes
2018-11-22 07:06:01.449 1993-1993/? D/OADB-HLPR: Database contains Table productusage created by SQL CREATE TABLE productusage (productailseref INTEGER , productproductref INTEGER , productcost REAL DEFAULT 1.00 , productbuycount INTEGER DEFAULT 0 , productfirstbuydate INTEGER DEFAULT 0 , productlatestbuydate INTEGER DEFAULT 0 , mincost REAL , PRIMARY KEY (productailseref, productproductref))
2018-11-22 07:06:01.451 1993-1993/? D/OADB-HLPR: Table is productusage Column Count = 7 Row Count = 20
2018-11-22 07:06:01.451 1993-1993/? D/OADB-HLPR: Columns are :- productailseref productproductref productcost productbuycount productfirstbuydate productlatestbuydate mincost
2018-11-22 07:06:01.451 1993-1993/? D/OADB-HLPR: Database contains Table rules created by SQL CREATE TABLE rules (ruleid INTEGER PRIMARY KEY , rulename TEXT , ruletype INTEGER , rulepromptflag INTEGER , ruleperiod INTEGER , rulemultiplier INTEGER , ruleactiveon INTEGER , ruleproductref INTEGER , ruleaisleref INTEGER )
2018-11-22 07:06:01.452 1993-1993/? D/OADB-HLPR: Table is rules Column Count = 9 Row Count = 0
2018-11-22 07:06:01.452 1993-1993/? D/OADB-HLPR: Columns are :- ruleid rulename ruletype rulepromptflag ruleperiod rulemultiplier ruleactiveon ruleproductref ruleaisleref
2018-11-22 07:06:01.452 1993-1993/? D/OADB-HLPR: Database contains Table shoplist created by SQL CREATE TABLE "shoplist" ("_id" INTEGER PRIMARY KEY NOT NULL , "productref" INTEGER, "dateadded" INTEGER, "numbertoget" INTEGER, "done" BOOL, "dategot" INTEGER, "cost" REAL, "productusageref" INTEGER, "aisleref" INTEGER)
2018-11-22 07:06:01.453 1993-1993/? D/OADB-HLPR: Table is shoplist Column Count = 9 Row Count = 4
2018-11-22 07:06:01.454 1993-1993/? D/OADB-HLPR: Columns are :- _id productref dateadded numbertoget done dategot cost productusageref aisleref
2018-11-22 07:06:01.454 1993-1993/? D/OADB-HLPR: logDatabaseTableInformation completed.
2018-11-22 07:06:01.454 1993-1993/? D/OADB-HLPR: OpenAssetDBHelper constructed.
The problem with the code you have is that numerous exceptions are caught by using throws IOException
and then you just issue a generic exception.
Whilst there could be a number of underlying causes.
It could be that asset itself doesn't exist where it's expected (in the assets folder (e.g. not in the databases directory (SQLiteAssetHelper uses this directory))).
It could be that the databases folder, within the package doesn't exist (use mkdirs on the DB_PATH). e.g. have something like :-
private boolean checkDatabase {
File db = new File(mContext.getDatabasePath(DB_NAME).getPath());
if(db.exists()) return true;
File dir = new File(db.getParent());
if (!dir.exists()) {
dir.mkdirs();
}
return false;
}
- Note the use of the Context's getDatabasePath
The following is code that is very long but provides very comprehensive logging (it also caters for multiple databases (up to 10 by default) and is also caters for directories in the assets folder).
/**
* Database Helper that includes ability to open database from assets
* if the database doesn't exist.
* (i.e. a pre-defined database)
*
*/
public class OpenAssetDBHelper extends SQLiteOpenHelper {
private static final String LOGTAG = "OADB-HLPR";
public static final int MAXIMUM_HELPERS = 10;
private String mDBPath, mAssetPath;
private static OpenAssetDBHelper mInstance = new OpenAssetDBHelper[MAXIMUM_HELPERS];
private SQLiteDatabase mDB;
/**
* OpenAssetDBHelper Class that will copy a predefined database
* from the assets folder and then open it is the database;
*
* The copy will only be done if the database does not exist.
*
* Note this code is intended to be used for development and/or
* experimentation, hence the extensive logging.
*/
/**
* get an OpenAssetDBHelper instance as a singleton;
* Note! caters for up to 10 OpenAssetDBHelpers for up to 10 databases
* as specified by the helper_index
*
* @param helper_index Index to this instance/database
* (0-MAXIMUM_HELPERS less 1)
* @param context Context for the database
* @param database Database name (i.e. file name)
* @param dbversion Database version (user_version)
* @param assetfile Name of the asset file to be copied to the database
* @param asset_sub_directories String Array of the sub-directories where
* the asset file is located;
* MUST be in order
* @return The resultant OpenAssetDBHelper
*/
public static synchronized OpenAssetDBHelper getInstance(
int helper_index,
Context context,
String database,
int dbversion,
String assetfile,
String asset_sub_directories) {
// Checck that helper_index is within bounds
if (helper_index > (MAXIMUM_HELPERS -1)) {
throw new RuntimeException(
"Helper Index greater than " +
MAXIMUM_HELPERS
);
}
if (helper_index < 0) {
throw new RuntimeException(
"Helper Index cannot be negative, must be 0-" +
MAXIMUM_HELPERS
);
}
// Create the respective OpenAssetDBHelper instance
if(mInstance[helper_index] == null) {
mInstance[helper_index] = new OpenAssetDBHelper(context,
database,
dbversion,
assetfile,
asset_sub_directories);
}
return mInstance[helper_index];
}
/**
* Construct an OpenAssetDBHelper instance;
* Note! can only be called within class
*
* @param context the context to be used
* @param database the database name (equates to filename)
* @param dbversion the databaae version (user_version)
* @param assetfile The name of the asset file i.e. the pre-defined db
* @param directories The hierarchy of directories within the assets folder
* where the asset file is located
* (null or zero elements = in the assets folder)
*/
private OpenAssetDBHelper(Context context,
String database,
int dbversion,
String assetfile,
String directories) {
super(context, database, null, dbversion);
Log.d(LOGTAG,"OpenAssetDBHelper being constructed.");
mDBPath = context.getDatabasePath(database).getPath();
if (assetfile == null || assetfile.length() < 1) {
assetfile = database;
}
mAssetPath = buildAssetPath(directories,assetfile);
if (!ifDatabaseExists(mDBPath)) {
Log.d(LOGTAG,"Database " + database + " not found at " + mDBPath + " so attempting to copy from assets.");
if (copyDatabaseFromAssets(context,mDBPath, database, mAssetPath)) {
Log.d(LOGTAG, "Successfully Copied Database from Assets.");
} else {
throw new RuntimeException("No Database Available.");
}
}
// Force Database open and store it
this.mDB = this.getWritableDatabase();
logDatabaseTableInformation(mDB);
Log.d(LOGTAG,"OpenAssetDBHelper constructed.");
}
/**
* onCreate - This is where you would create tables;
* Typically this is where you would alter the structure of the database;
* Note that this is called once for the lifetime of the database.
* @param db The SQLitedatabase
*/
@Override
public void onCreate(SQLiteDatabase db) {
Log.d(LOGTAG,new Object(){}.getClass().getEnclosingMethod().getName() + " initiated.");
// As Database is copied from assets nothing to do in onCreate!
Log.d(LOGTAG,new Object(){}.getClass().getEnclosingMethod().getName() + " completed.");
}
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
Log.d(LOGTAG,new Object(){}.getClass().getEnclosingMethod().getName() + " initiated.");
// Nothing to do as it's early days in the Database's lifetime.
Log.d(LOGTAG,new Object(){}.getClass().getEnclosingMethod().getName() + " completed.");
}
/**
* Check to see if the Database exists,
* if it doesn't exists then check to see if
* the database directory exists,
* if the directory(ies) does(do) not exist then make the directory(ies);
*
*
* @param dbpath The path to the database
* @return true if the database exists, else false
*/
private boolean ifDatabaseExists(String dbpath) {
Log.d(LOGTAG,new Object(){}.getClass().getEnclosingMethod().getName() + " initiated.");
File db = new File(dbpath);
if(db.exists()) return true;
File dir = new File(db.getParent());
if (!dir.exists()) {
dir.mkdirs();
}
return false;
}
/**
* Copy the Database from the assets folder
* @param context
* @param dbpath
* @return
*/
private boolean copyDatabaseFromAssets(Context context,String dbpath, String dbname, String asset) {
String thisclass = new Object(){}.getClass().getEnclosingMethod().getName();
Log.d(LOGTAG,thisclass + " initiated");
InputStream assetsdb;
OutputStream database;
File db = new File(dbpath);
int filesize;
// Get the asset file
try {
Log.d(LOGTAG,thisclass + " attempting to find asset " + asset);
assetsdb = context.getAssets().open(asset);
filesize = assetsdb.available();
Log.d(LOGTAG,thisclass + " asset " + asset +
" located successfully with a size of " +
Integer.toString(filesize)
);
} catch (IOException e) {
Log.d(LOGTAG,thisclass + " Did not locate asset " + asset);
e.printStackTrace();
return false;
}
// Read the first 16 bytes from the asset file
byte dbcheck = new byte[16];
try {
assetsdb.read(dbcheck,0,16);
} catch (IOException e) {
Log.d(LOGTAG, thisclass + " failed trying to read 16 bytes to check for a valid database. ");
e.printStackTrace();
return false;
}
// Check that the asset file is an SQLite database
String chkdb = new String(dbcheck);
if(!chkdb.equals("SQLite format 3u0000")) {
Log.d(LOGTAG,thisclass + " asset " +
asset +
" is not a valid SQLite Database File (found " +
chkdb +
" at bytes 1-16 instead of SQLite format 3)");
try {
assetsdb.close();
} catch (IOException e) {
// Not worth doing anything
}
return false;
}
// Close the asset file
try {
assetsdb.close();
} catch (IOException e) {
Log.d(LOGTAG,thisclass +
" failed to close assets file after checking for a valid database."
);
return false;
}
// Re-open the asset file
try {
assetsdb = context.getAssets().open(asset);
filesize = assetsdb.available();
} catch (IOException e) {
Log.d(LOGTAG, thisclass +
" failed trying to re-open asset " +
asset +
" after checking for a valid database."
);
e.printStackTrace();
return false;
}
// Read the entire asset file into a buffer
Log.d(LOGTAG, thisclass +
" copying asset database " +
dbname +
" into buffer of size " +
filesize
);
byte buffer = new byte[filesize];
// Close the asset file
try {
assetsdb.read(buffer);
Log.d(LOGTAG,thisclass +
" closing asset database " + dbname
);
assetsdb.close();
} catch (IOException e) {
Log.d(LOGTAG, thisclass +
" failed while copying asset database " +
dbname +
" (or closing asset database)."
);
e.printStackTrace();
return false;
}
// Open the new database file
try {
Log.d(LOGTAG,thisclass + " attempting to open new database file " + dbpath);
database = new FileOutputStream(dbpath);
} catch (IOException e) {
Log.d(LOGTAG, thisclass + " failed to open new database file.");
e.printStackTrace();
return false;
}
// Write the new database file
try {
Log.d(LOGTAG, thisclass + " writing new database file " + dbpath);
database.write(buffer);
} catch (IOException e) {
Log.d(LOGTAG, thisclass + " failed while writing new database file " + dbpath);
e.printStackTrace();
return false;
}
// Flush the new database file
try {
Log.d(LOGTAG, thisclass + " flushing new database file " + dbpath);
database.flush();
} catch (IOException e) {
Log.d(LOGTAG, thisclass + " failed while flushing new database file " + dbpath);
e.printStackTrace();
return false;
}
// Close the new database file
try {
Log.d(LOGTAG, thisclass + " closing new database file " + dbpath);
database.close();
} catch (IOException e) {
Log.d(LOGTAG, thisclass + " failed while closing new database file " + dbpath);
e.printStackTrace();
return false;
}
Log.d(LOGTAG,new Object(){}.getClass().getEnclosingMethod().getName() + " completed.");
return true;
}
/**
* Log Database table Information
*/
private void logDatabaseTableInformation(SQLiteDatabase db) {
Log.d(LOGTAG,new Object(){}.getClass().getEnclosingMethod().getName() + " initiated.");
String mastertable = "sqlite_master";
String typecolumn = "type";
String namecolumn = "name";
String sqlcolumn = "sql";
String args = new String{"table","android_metadata"};
Cursor csr = db.query(mastertable,
null,
typecolumn + "=? AND " + namecolumn + "!=?",
args,
null,null,null
);
while (csr.moveToNext()) {
Log.d(LOGTAG,"Database contains Table " +
csr.getString(csr.getColumnIndex(namecolumn)) +
" created by SQL " +
csr.getString(csr.getColumnIndex(sqlcolumn))
);
logTableInformation(db, csr.getString(csr.getColumnIndex(namecolumn)));
}
csr.close();
Log.d(LOGTAG,new Object(){}.getClass().getEnclosingMethod().getName() + " completed.");
}
/**
* Write Table information, Table name, Column Count,
* Row Count and Column Names to the Log
* @param table Name of the table to be reported on
*/
private void logTableInformation(SQLiteDatabase db, String table) {
Cursor csr = db.query(table,
null,
null,
null,
null,
null,
null
);
Log.d(LOGTAG,"Table is " +
table +
" Column Count = " +
Integer.toString(csr.getColumnCount()) +
" Row Count = " +
Long.toString(DatabaseUtils.queryNumEntries(mDB,table))
);
StringBuilder columns_as_string = new StringBuilder();
for (String s: csr.getColumnNames()) {
columns_as_string.append(s).append(" ");
}
Log.d(LOGTAG, "tColumns are :- " + columns_as_string);
csr.close();
}
/**
* Build the sub-path to the asset, according to the directories specified
*
* @param directories directories underneath the assets folder where
* the asset files is located, null or empty
* array if file is located directly in the
* assets folder;
* directories must be specified in the order
* in which they appear in the path.
* @param filename The filename of the asset
* @return The fill sub-path to the asset
*/
private String buildAssetPath(String directories, String filename) {
StringBuilder sb = new StringBuilder();
final String SEPERATOR = "/";
if (directories != null && directories.length > 0) {
for (String s: directories) {
sb.append(s);
if (!s.substring(s.length()-1,s.length()).equals(SEPERATOR)) {
sb.append(SEPERATOR);
}
}
sb.append(filename);
return sb.toString();
} else {
return filename;
}
}
}
Example Usage
public class MainActivity extends AppCompatActivity {
public static final int DBVERSION = 1;
public static final String DBNAME1 = "openassetdb.db";
public static final int DB1_INDEX = 0;
public static final String DBNAME2 = "myshopping";
public static final int DB2_INDEX = 1;
OpenAssetDBHelper mOADBHlpr;
OpenAssetDBHelper mShoppingHelper;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// Example 1 - Database file located in the assets folder and
// database name same as file name
mOADBHlpr = OpenAssetDBHelper.getInstance(DB1_INDEX,
this,
DBNAME1,
DBVERSION,
DBNAME1,
null
);
// Example 2 - Database file in databases directory of the assets folder
// database name different to the asset filename
mShoppingHelper = OpenAssetDBHelper.getInstance(DB2_INDEX,
this,
DBNAME2,
DBVERSION,
"shopper",
new String{"databases"}
);
}
}
Result (when no databases exist) :-
2018-11-22 07:06:01.408 1993-1993/? D/OADB-HLPR: OpenAssetDBHelper being constructed.
2018-11-22 07:06:01.408 1993-1993/? D/OADB-HLPR: ifDatabaseExists initiated.
2018-11-22 07:06:01.408 1993-1993/? D/OADB-HLPR: Database openassetdb.db not found at /data/user/0/mjt.openassetdb/databases/openassetdb.db so attempting to copy from assets.
2018-11-22 07:06:01.409 1993-1993/? D/OADB-HLPR: copyDatabaseFromAssets initiated
2018-11-22 07:06:01.409 1993-1993/? D/OADB-HLPR: copyDatabaseFromAssets attempting to find asset openassetdb.db
2018-11-22 07:06:01.409 1993-1993/? D/OADB-HLPR: copyDatabaseFromAssets asset openassetdb.db located successfully with a size of 12288
2018-11-22 07:06:01.409 1993-1993/? D/OADB-HLPR: copyDatabaseFromAssets copying asset database openassetdb.db into buffer of size 12288
2018-11-22 07:06:01.409 1993-1993/? D/OADB-HLPR: copyDatabaseFromAssets closing asset database openassetdb.db
2018-11-22 07:06:01.409 1993-1993/? D/OADB-HLPR: copyDatabaseFromAssets attempting to open new database file /data/user/0/mjt.openassetdb/databases/openassetdb.db
2018-11-22 07:06:01.410 1993-1993/? D/OADB-HLPR: copyDatabaseFromAssets writing new database file /data/user/0/mjt.openassetdb/databases/openassetdb.db
2018-11-22 07:06:01.410 1993-1993/? D/OADB-HLPR: copyDatabaseFromAssets flushing new database file /data/user/0/mjt.openassetdb/databases/openassetdb.db
2018-11-22 07:06:01.410 1993-1993/? D/OADB-HLPR: copyDatabaseFromAssets closing new database file /data/user/0/mjt.openassetdb/databases/openassetdb.db
2018-11-22 07:06:01.410 1993-1993/? D/OADB-HLPR: copyDatabaseFromAssets completed.
2018-11-22 07:06:01.410 1993-1993/? D/OADB-HLPR: Successfully Copied Database from Assets.
2018-11-22 07:06:01.421 1993-1993/? D/OADB-HLPR: onCreate initiated.
2018-11-22 07:06:01.421 1993-1993/? D/OADB-HLPR: onCreate completed.
2018-11-22 07:06:01.425 1993-1993/? D/OADB-HLPR: logDatabaseTableInformation initiated.
2018-11-22 07:06:01.426 1993-1993/? D/OADB-HLPR: Database contains Table testtable created by SQL CREATE TABLE `testtable` (
`_id` INTEGER PRIMARY KEY AUTOINCREMENT,
`name` TEXT,
`timestamp` INTEGER
)
2018-11-22 07:06:01.426 1993-1993/? D/OADB-HLPR: Table is testtable Column Count = 3 Row Count = 2
2018-11-22 07:06:01.426 1993-1993/? D/OADB-HLPR: Columns are :- _id name timestamp
2018-11-22 07:06:01.426 1993-1993/? D/OADB-HLPR: Database contains Table sqlite_sequence created by SQL CREATE TABLE sqlite_sequence(name,seq)
2018-11-22 07:06:01.427 1993-1993/? D/OADB-HLPR: Table is sqlite_sequence Column Count = 2 Row Count = 1
2018-11-22 07:06:01.427 1993-1993/? D/OADB-HLPR: Columns are :- name seq
2018-11-22 07:06:01.427 1993-1993/? D/OADB-HLPR: logDatabaseTableInformation completed.
(2nd)
2018-11-22 07:06:01.427 1993-1993/? D/OADB-HLPR: OpenAssetDBHelper constructed.
2018-11-22 07:06:01.427 1993-1993/? D/OADB-HLPR: OpenAssetDBHelper being constructed.
2018-11-22 07:06:01.427 1993-1993/? D/OADB-HLPR: ifDatabaseExists initiated.
2018-11-22 07:06:01.428 1993-1993/? D/OADB-HLPR: Database myshopping not found at /data/user/0/mjt.openassetdb/databases/myshopping so attempting to copy from assets.
2018-11-22 07:06:01.428 1993-1993/? D/OADB-HLPR: copyDatabaseFromAssets initiated
2018-11-22 07:06:01.428 1993-1993/? D/OADB-HLPR: copyDatabaseFromAssets attempting to find asset databases/shopper
2018-11-22 07:06:01.428 1993-1993/? D/OADB-HLPR: copyDatabaseFromAssets asset databases/shopper located successfully with a size of 262144
2018-11-22 07:06:01.428 1993-1993/? D/OADB-HLPR: copyDatabaseFromAssets copying asset database myshopping into buffer of size 262144
2018-11-22 07:06:01.429 1993-1993/? D/OADB-HLPR: copyDatabaseFromAssets closing asset database myshopping
2018-11-22 07:06:01.429 1993-1993/? D/OADB-HLPR: copyDatabaseFromAssets attempting to open new database file /data/user/0/mjt.openassetdb/databases/myshopping
2018-11-22 07:06:01.429 1993-1993/? D/OADB-HLPR: copyDatabaseFromAssets writing new database file /data/user/0/mjt.openassetdb/databases/myshopping
2018-11-22 07:06:01.429 1993-1993/? D/OADB-HLPR: copyDatabaseFromAssets flushing new database file /data/user/0/mjt.openassetdb/databases/myshopping
2018-11-22 07:06:01.429 1993-1993/? D/OADB-HLPR: copyDatabaseFromAssets closing new database file /data/user/0/mjt.openassetdb/databases/myshopping
2018-11-22 07:06:01.429 1993-1993/? D/OADB-HLPR: copyDatabaseFromAssets completed.
2018-11-22 07:06:01.429 1993-1993/? D/OADB-HLPR: Successfully Copied Database from Assets.
2018-11-22 07:06:01.440 1993-1993/? D/OADB-HLPR: onCreate initiated.
2018-11-22 07:06:01.440 1993-1993/? D/OADB-HLPR: onCreate completed.
2018-11-22 07:06:01.443 1993-1993/? D/OADB-HLPR: logDatabaseTableInformation initiated.
2018-11-22 07:06:01.444 1993-1993/? D/OADB-HLPR: Database contains Table shops created by SQL CREATE TABLE shops (_id INTEGER PRIMARY KEY , shopname TEXT , shoporder INTEGER DEFAULT 100 , shopstreet TEXT , shopcity TEXT , shopstate TEXT , shopphone TEXT , shopnotes TEXT )
2018-11-22 07:06:01.445 1993-1993/? D/OADB-HLPR: Table is shops Column Count = 8 Row Count = 4
2018-11-22 07:06:01.445 1993-1993/? D/OADB-HLPR: Columns are :- _id shopname shoporder shopstreet shopcity shopstate shopphone shopnotes
2018-11-22 07:06:01.446 1993-1993/? D/OADB-HLPR: Database contains Table aisles created by SQL CREATE TABLE aisles (_id INTEGER PRIMARY KEY , aislename TEXT , aisleorder INTEGER DEFAULT 100 , aisleshopref INTEGER )
2018-11-22 07:06:01.448 1993-1993/? D/OADB-HLPR: Table is aisles Column Count = 4 Row Count = 20
2018-11-22 07:06:01.448 1993-1993/? D/OADB-HLPR: Columns are :- _id aislename aisleorder aisleshopref
2018-11-22 07:06:01.448 1993-1993/? D/OADB-HLPR: Database contains Table products created by SQL CREATE TABLE products (_id INTEGER PRIMARY KEY , productname TEXT , productorder INTEGER DEFAULT 100 , productaisleref INTEGER , productuses INTEGER DEFAULT 0 , productnotes TEXT )
2018-11-22 07:06:01.449 1993-1993/? D/OADB-HLPR: Table is products Column Count = 6 Row Count = 10
2018-11-22 07:06:01.449 1993-1993/? D/OADB-HLPR: Columns are :- _id productname productorder productaisleref productuses productnotes
2018-11-22 07:06:01.449 1993-1993/? D/OADB-HLPR: Database contains Table productusage created by SQL CREATE TABLE productusage (productailseref INTEGER , productproductref INTEGER , productcost REAL DEFAULT 1.00 , productbuycount INTEGER DEFAULT 0 , productfirstbuydate INTEGER DEFAULT 0 , productlatestbuydate INTEGER DEFAULT 0 , mincost REAL , PRIMARY KEY (productailseref, productproductref))
2018-11-22 07:06:01.451 1993-1993/? D/OADB-HLPR: Table is productusage Column Count = 7 Row Count = 20
2018-11-22 07:06:01.451 1993-1993/? D/OADB-HLPR: Columns are :- productailseref productproductref productcost productbuycount productfirstbuydate productlatestbuydate mincost
2018-11-22 07:06:01.451 1993-1993/? D/OADB-HLPR: Database contains Table rules created by SQL CREATE TABLE rules (ruleid INTEGER PRIMARY KEY , rulename TEXT , ruletype INTEGER , rulepromptflag INTEGER , ruleperiod INTEGER , rulemultiplier INTEGER , ruleactiveon INTEGER , ruleproductref INTEGER , ruleaisleref INTEGER )
2018-11-22 07:06:01.452 1993-1993/? D/OADB-HLPR: Table is rules Column Count = 9 Row Count = 0
2018-11-22 07:06:01.452 1993-1993/? D/OADB-HLPR: Columns are :- ruleid rulename ruletype rulepromptflag ruleperiod rulemultiplier ruleactiveon ruleproductref ruleaisleref
2018-11-22 07:06:01.452 1993-1993/? D/OADB-HLPR: Database contains Table shoplist created by SQL CREATE TABLE "shoplist" ("_id" INTEGER PRIMARY KEY NOT NULL , "productref" INTEGER, "dateadded" INTEGER, "numbertoget" INTEGER, "done" BOOL, "dategot" INTEGER, "cost" REAL, "productusageref" INTEGER, "aisleref" INTEGER)
2018-11-22 07:06:01.453 1993-1993/? D/OADB-HLPR: Table is shoplist Column Count = 9 Row Count = 4
2018-11-22 07:06:01.454 1993-1993/? D/OADB-HLPR: Columns are :- _id productref dateadded numbertoget done dategot cost productusageref aisleref
2018-11-22 07:06:01.454 1993-1993/? D/OADB-HLPR: logDatabaseTableInformation completed.
2018-11-22 07:06:01.454 1993-1993/? D/OADB-HLPR: OpenAssetDBHelper constructed.
answered Nov 21 '18 at 20:12
MikeTMikeT
17.3k112643
17.3k112643
I tester your database adapter and it is working. I will investigate my own code later. Thank you very much for your reply!
– Ulrich_Peters
Nov 26 '18 at 15:54
Ok. Somehow it is not working anymore. I simply get an D/OADB-HLPR: copyDatabaseFromAssets Did not locate asset NewDATABASE.db even though i have NewDATABASE.db in my assets folder.
– Ulrich_Peters
Nov 29 '18 at 5:58
@Ulrich_Peters, I've added an explanatory answer (had to add another due to size restriction). I would initially suspect that you have specified a directory but not placed the asset in the directory or vice-versa. What you have/have not specified will be in the log before and after the line you have shown (there's no way that that is the only line in the log, unless you've made numerous changes)
– MikeT
Nov 29 '18 at 8:22
@Ulrich_Peters also note that file and directory names are case dependant.
– MikeT
Nov 29 '18 at 8:59
add a comment |
I tester your database adapter and it is working. I will investigate my own code later. Thank you very much for your reply!
– Ulrich_Peters
Nov 26 '18 at 15:54
Ok. Somehow it is not working anymore. I simply get an D/OADB-HLPR: copyDatabaseFromAssets Did not locate asset NewDATABASE.db even though i have NewDATABASE.db in my assets folder.
– Ulrich_Peters
Nov 29 '18 at 5:58
@Ulrich_Peters, I've added an explanatory answer (had to add another due to size restriction). I would initially suspect that you have specified a directory but not placed the asset in the directory or vice-versa. What you have/have not specified will be in the log before and after the line you have shown (there's no way that that is the only line in the log, unless you've made numerous changes)
– MikeT
Nov 29 '18 at 8:22
@Ulrich_Peters also note that file and directory names are case dependant.
– MikeT
Nov 29 '18 at 8:59
I tester your database adapter and it is working. I will investigate my own code later. Thank you very much for your reply!
– Ulrich_Peters
Nov 26 '18 at 15:54
I tester your database adapter and it is working. I will investigate my own code later. Thank you very much for your reply!
– Ulrich_Peters
Nov 26 '18 at 15:54
Ok. Somehow it is not working anymore. I simply get an D/OADB-HLPR: copyDatabaseFromAssets Did not locate asset NewDATABASE.db even though i have NewDATABASE.db in my assets folder.
– Ulrich_Peters
Nov 29 '18 at 5:58
Ok. Somehow it is not working anymore. I simply get an D/OADB-HLPR: copyDatabaseFromAssets Did not locate asset NewDATABASE.db even though i have NewDATABASE.db in my assets folder.
– Ulrich_Peters
Nov 29 '18 at 5:58
@Ulrich_Peters, I've added an explanatory answer (had to add another due to size restriction). I would initially suspect that you have specified a directory but not placed the asset in the directory or vice-versa. What you have/have not specified will be in the log before and after the line you have shown (there's no way that that is the only line in the log, unless you've made numerous changes)
– MikeT
Nov 29 '18 at 8:22
@Ulrich_Peters, I've added an explanatory answer (had to add another due to size restriction). I would initially suspect that you have specified a directory but not placed the asset in the directory or vice-versa. What you have/have not specified will be in the log before and after the line you have shown (there's no way that that is the only line in the log, unless you've made numerous changes)
– MikeT
Nov 29 '18 at 8:22
@Ulrich_Peters also note that file and directory names are case dependant.
– MikeT
Nov 29 '18 at 8:59
@Ulrich_Peters also note that file and directory names are case dependant.
– MikeT
Nov 29 '18 at 8:59
add a comment |
Additional - Asset not found example
using
mShopper = OpenAssetDBHelper.getInstance(DB3_INDEX,
this,
DBNAME3,
DBVERSION,
"Shopper.lite", // not the asset name
new String{"databases"}
);
Where
- DBNAME3 resolves to rumplestiltskin (the final database name)
- DBVERSION is 1
- and the asset filename is Shopper.lite which should be in the databases folder (doesn't exist though).
The resultant log is :-
11-29 07:46:22.603 4816-4816/? D/OADB-HLPR: OpenAssetDBHelper constructed.
11-29 07:46:22.603 4816-4816/? D/OADB-HLPR: OpenAssetDBHelper being constructed.
11-29 07:46:22.603 4816-4816/? D/OADB-HLPR: ifDatabaseExists initiated.
11-29 07:46:22.603 4816-4816/? D/OADB-HLPR: Database rumplestilskin not found at /data/data/mjt.openassetdb/databases/rumplestilskin so attempting to copy from assets.
11-29 07:46:22.603 4816-4816/? D/OADB-HLPR: copyDatabaseFromAssets initiated
11-29 07:46:22.603 4816-4816/? D/OADB-HLPR: copyDatabaseFromAssets attempting to find asset databases/Shopper.lite
11-29 07:46:22.603 4816-4816/? D/OADB-HLPR: copyDatabaseFromAssets Did not locate asset databases/Shopper.lite
11-29 07:46:22.603 4816-4816/? W/System.err: java.io.FileNotFoundException: databases/Shopper.lite
11-29 07:46:22.603 4816-4816/? W/System.err: at android.content.res.AssetManager.openAsset(Native Method)
11-29 07:46:22.603 4816-4816/? W/System.err: at android.content.res.AssetManager.open(AssetManager.java:315)
11-29 07:46:22.603 4816-4816/? W/System.err: at android.content.res.AssetManager.open(AssetManager.java:289)
11-29 07:46:22.603 4816-4816/? W/System.err: at mjt.openassetdb.OpenAssetDBHelper.copyDatabaseFromAssets(OpenAssetDBHelper.java:187)
11-29 07:46:22.603 4816-4816/? W/System.err: at mjt.openassetdb.OpenAssetDBHelper.<init>(OpenAssetDBHelper.java:117)
11-29 07:46:22.603 4816-4816/? W/System.err: at mjt.openassetdb.OpenAssetDBHelper.getInstance(OpenAssetDBHelper.java:80)
11-29 07:46:22.603 4816-4816/? W/System.err: at mjt.openassetdb.MainActivity.onCreate(MainActivity.java:87)
11-29 07:46:22.603 4816-4816/? W/System.err: at android.app.Activity.performCreate(Activity.java:5008)
11-29 07:46:22.603 4816-4816/? W/System.err: at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1079)
11-29 07:46:22.603 4816-4816/? W/System.err: at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2023)
11-29 07:46:22.603 4816-4816/? W/System.err: at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2084)
11-29 07:46:22.603 4816-4816/? W/System.err: at android.app.ActivityThread.access$600(ActivityThread.java:130)
11-29 07:46:22.603 4816-4816/? W/System.err: at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1195)
11-29 07:46:22.603 4816-4816/? W/System.err: at android.os.Handler.dispatchMessage(Handler.java:99)
11-29 07:46:22.603 4816-4816/? W/System.err: at android.os.Looper.loop(Looper.java:137)
11-29 07:46:22.603 4816-4816/? W/System.err: at android.app.ActivityThread.main(ActivityThread.java:4745)
11-29 07:46:22.603 4816-4816/? W/System.err: at java.lang.reflect.Method.invokeNative(Native Method)
11-29 07:46:22.603 4816-4816/? W/System.err: at java.lang.reflect.Method.invoke(Method.java:511)
11-29 07:46:22.603 4816-4816/? W/System.err: at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:786)
11-29 07:46:22.603 4816-4816/? W/System.err: at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:553)
11-29 07:46:22.603 4816-4816/? W/System.err: at dalvik.system.NativeStart.main(Native Method)
11-29 07:46:22.603 4816-4816/? D/AndroidRuntime: Shutting down VM
11-29 07:46:22.603 4816-4816/? W/dalvikvm: threadid=1: thread exiting with uncaught exception (group=0xa6265288)
11-29 07:46:22.603 4816-4816/? E/AndroidRuntime: FATAL EXCEPTION: main
java.lang.RuntimeException: Unable to start activity ComponentInfo{mjt.openassetdb/mjt.openassetdb.MainActivity}: java.lang.RuntimeException: No Database Available.
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2059)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2084)
at android.app.ActivityThread.access$600(ActivityThread.java:130)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1195)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loop(Looper.java:137)
at android.app.ActivityThread.main(ActivityThread.java:4745)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:511)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:786)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:553)
at dalvik.system.NativeStart.main(Native Method)
Caused by: java.lang.RuntimeException: No Database Available.
at mjt.openassetdb.OpenAssetDBHelper.<init>(OpenAssetDBHelper.java:120)
at mjt.openassetdb.OpenAssetDBHelper.getInstance(OpenAssetDBHelper.java:80)
at mjt.openassetdb.MainActivity.onCreate(MainActivity.java:87)
at android.app.Activity.performCreate(Activity.java:5008)
at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1079)
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2023)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2084)
at android.app.ActivityThread.access$600(ActivityThread.java:130)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1195)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loop(Looper.java:137)
at android.app.ActivityThread.main(ActivityThread.java:4745)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:511)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:786)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:553)
at dalvik.system.NativeStart.main(Native Method)
The first pertinent line is D/OADB-HLPR: copyDatabaseFromAssets attempting to find asset databases/Shopper.lite
This provides the path within the assets folder where the asset is expected to be found (in this example the filename is expected to be Shopper.lite in the databases subfolder/directory)
The line D/OADB-HLPR: copyDatabaseFromAssets Did not locate asset databases/Shopper.lite
reports that the asset file was not found.
This is followed by the trapped exception (not the actual crash)
Processing continues until the final crash as reported by :-
E/AndroidRuntime: FATAL EXCEPTION: main
java.lang.RuntimeException: Unable to start activity ComponentInfo{mjt.openassetdb/mjt.openassetdb.MainActivity}: java.lang.RuntimeException: No Database Available.
add a comment |
Additional - Asset not found example
using
mShopper = OpenAssetDBHelper.getInstance(DB3_INDEX,
this,
DBNAME3,
DBVERSION,
"Shopper.lite", // not the asset name
new String{"databases"}
);
Where
- DBNAME3 resolves to rumplestiltskin (the final database name)
- DBVERSION is 1
- and the asset filename is Shopper.lite which should be in the databases folder (doesn't exist though).
The resultant log is :-
11-29 07:46:22.603 4816-4816/? D/OADB-HLPR: OpenAssetDBHelper constructed.
11-29 07:46:22.603 4816-4816/? D/OADB-HLPR: OpenAssetDBHelper being constructed.
11-29 07:46:22.603 4816-4816/? D/OADB-HLPR: ifDatabaseExists initiated.
11-29 07:46:22.603 4816-4816/? D/OADB-HLPR: Database rumplestilskin not found at /data/data/mjt.openassetdb/databases/rumplestilskin so attempting to copy from assets.
11-29 07:46:22.603 4816-4816/? D/OADB-HLPR: copyDatabaseFromAssets initiated
11-29 07:46:22.603 4816-4816/? D/OADB-HLPR: copyDatabaseFromAssets attempting to find asset databases/Shopper.lite
11-29 07:46:22.603 4816-4816/? D/OADB-HLPR: copyDatabaseFromAssets Did not locate asset databases/Shopper.lite
11-29 07:46:22.603 4816-4816/? W/System.err: java.io.FileNotFoundException: databases/Shopper.lite
11-29 07:46:22.603 4816-4816/? W/System.err: at android.content.res.AssetManager.openAsset(Native Method)
11-29 07:46:22.603 4816-4816/? W/System.err: at android.content.res.AssetManager.open(AssetManager.java:315)
11-29 07:46:22.603 4816-4816/? W/System.err: at android.content.res.AssetManager.open(AssetManager.java:289)
11-29 07:46:22.603 4816-4816/? W/System.err: at mjt.openassetdb.OpenAssetDBHelper.copyDatabaseFromAssets(OpenAssetDBHelper.java:187)
11-29 07:46:22.603 4816-4816/? W/System.err: at mjt.openassetdb.OpenAssetDBHelper.<init>(OpenAssetDBHelper.java:117)
11-29 07:46:22.603 4816-4816/? W/System.err: at mjt.openassetdb.OpenAssetDBHelper.getInstance(OpenAssetDBHelper.java:80)
11-29 07:46:22.603 4816-4816/? W/System.err: at mjt.openassetdb.MainActivity.onCreate(MainActivity.java:87)
11-29 07:46:22.603 4816-4816/? W/System.err: at android.app.Activity.performCreate(Activity.java:5008)
11-29 07:46:22.603 4816-4816/? W/System.err: at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1079)
11-29 07:46:22.603 4816-4816/? W/System.err: at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2023)
11-29 07:46:22.603 4816-4816/? W/System.err: at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2084)
11-29 07:46:22.603 4816-4816/? W/System.err: at android.app.ActivityThread.access$600(ActivityThread.java:130)
11-29 07:46:22.603 4816-4816/? W/System.err: at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1195)
11-29 07:46:22.603 4816-4816/? W/System.err: at android.os.Handler.dispatchMessage(Handler.java:99)
11-29 07:46:22.603 4816-4816/? W/System.err: at android.os.Looper.loop(Looper.java:137)
11-29 07:46:22.603 4816-4816/? W/System.err: at android.app.ActivityThread.main(ActivityThread.java:4745)
11-29 07:46:22.603 4816-4816/? W/System.err: at java.lang.reflect.Method.invokeNative(Native Method)
11-29 07:46:22.603 4816-4816/? W/System.err: at java.lang.reflect.Method.invoke(Method.java:511)
11-29 07:46:22.603 4816-4816/? W/System.err: at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:786)
11-29 07:46:22.603 4816-4816/? W/System.err: at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:553)
11-29 07:46:22.603 4816-4816/? W/System.err: at dalvik.system.NativeStart.main(Native Method)
11-29 07:46:22.603 4816-4816/? D/AndroidRuntime: Shutting down VM
11-29 07:46:22.603 4816-4816/? W/dalvikvm: threadid=1: thread exiting with uncaught exception (group=0xa6265288)
11-29 07:46:22.603 4816-4816/? E/AndroidRuntime: FATAL EXCEPTION: main
java.lang.RuntimeException: Unable to start activity ComponentInfo{mjt.openassetdb/mjt.openassetdb.MainActivity}: java.lang.RuntimeException: No Database Available.
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2059)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2084)
at android.app.ActivityThread.access$600(ActivityThread.java:130)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1195)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loop(Looper.java:137)
at android.app.ActivityThread.main(ActivityThread.java:4745)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:511)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:786)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:553)
at dalvik.system.NativeStart.main(Native Method)
Caused by: java.lang.RuntimeException: No Database Available.
at mjt.openassetdb.OpenAssetDBHelper.<init>(OpenAssetDBHelper.java:120)
at mjt.openassetdb.OpenAssetDBHelper.getInstance(OpenAssetDBHelper.java:80)
at mjt.openassetdb.MainActivity.onCreate(MainActivity.java:87)
at android.app.Activity.performCreate(Activity.java:5008)
at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1079)
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2023)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2084)
at android.app.ActivityThread.access$600(ActivityThread.java:130)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1195)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loop(Looper.java:137)
at android.app.ActivityThread.main(ActivityThread.java:4745)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:511)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:786)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:553)
at dalvik.system.NativeStart.main(Native Method)
The first pertinent line is D/OADB-HLPR: copyDatabaseFromAssets attempting to find asset databases/Shopper.lite
This provides the path within the assets folder where the asset is expected to be found (in this example the filename is expected to be Shopper.lite in the databases subfolder/directory)
The line D/OADB-HLPR: copyDatabaseFromAssets Did not locate asset databases/Shopper.lite
reports that the asset file was not found.
This is followed by the trapped exception (not the actual crash)
Processing continues until the final crash as reported by :-
E/AndroidRuntime: FATAL EXCEPTION: main
java.lang.RuntimeException: Unable to start activity ComponentInfo{mjt.openassetdb/mjt.openassetdb.MainActivity}: java.lang.RuntimeException: No Database Available.
add a comment |
Additional - Asset not found example
using
mShopper = OpenAssetDBHelper.getInstance(DB3_INDEX,
this,
DBNAME3,
DBVERSION,
"Shopper.lite", // not the asset name
new String{"databases"}
);
Where
- DBNAME3 resolves to rumplestiltskin (the final database name)
- DBVERSION is 1
- and the asset filename is Shopper.lite which should be in the databases folder (doesn't exist though).
The resultant log is :-
11-29 07:46:22.603 4816-4816/? D/OADB-HLPR: OpenAssetDBHelper constructed.
11-29 07:46:22.603 4816-4816/? D/OADB-HLPR: OpenAssetDBHelper being constructed.
11-29 07:46:22.603 4816-4816/? D/OADB-HLPR: ifDatabaseExists initiated.
11-29 07:46:22.603 4816-4816/? D/OADB-HLPR: Database rumplestilskin not found at /data/data/mjt.openassetdb/databases/rumplestilskin so attempting to copy from assets.
11-29 07:46:22.603 4816-4816/? D/OADB-HLPR: copyDatabaseFromAssets initiated
11-29 07:46:22.603 4816-4816/? D/OADB-HLPR: copyDatabaseFromAssets attempting to find asset databases/Shopper.lite
11-29 07:46:22.603 4816-4816/? D/OADB-HLPR: copyDatabaseFromAssets Did not locate asset databases/Shopper.lite
11-29 07:46:22.603 4816-4816/? W/System.err: java.io.FileNotFoundException: databases/Shopper.lite
11-29 07:46:22.603 4816-4816/? W/System.err: at android.content.res.AssetManager.openAsset(Native Method)
11-29 07:46:22.603 4816-4816/? W/System.err: at android.content.res.AssetManager.open(AssetManager.java:315)
11-29 07:46:22.603 4816-4816/? W/System.err: at android.content.res.AssetManager.open(AssetManager.java:289)
11-29 07:46:22.603 4816-4816/? W/System.err: at mjt.openassetdb.OpenAssetDBHelper.copyDatabaseFromAssets(OpenAssetDBHelper.java:187)
11-29 07:46:22.603 4816-4816/? W/System.err: at mjt.openassetdb.OpenAssetDBHelper.<init>(OpenAssetDBHelper.java:117)
11-29 07:46:22.603 4816-4816/? W/System.err: at mjt.openassetdb.OpenAssetDBHelper.getInstance(OpenAssetDBHelper.java:80)
11-29 07:46:22.603 4816-4816/? W/System.err: at mjt.openassetdb.MainActivity.onCreate(MainActivity.java:87)
11-29 07:46:22.603 4816-4816/? W/System.err: at android.app.Activity.performCreate(Activity.java:5008)
11-29 07:46:22.603 4816-4816/? W/System.err: at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1079)
11-29 07:46:22.603 4816-4816/? W/System.err: at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2023)
11-29 07:46:22.603 4816-4816/? W/System.err: at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2084)
11-29 07:46:22.603 4816-4816/? W/System.err: at android.app.ActivityThread.access$600(ActivityThread.java:130)
11-29 07:46:22.603 4816-4816/? W/System.err: at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1195)
11-29 07:46:22.603 4816-4816/? W/System.err: at android.os.Handler.dispatchMessage(Handler.java:99)
11-29 07:46:22.603 4816-4816/? W/System.err: at android.os.Looper.loop(Looper.java:137)
11-29 07:46:22.603 4816-4816/? W/System.err: at android.app.ActivityThread.main(ActivityThread.java:4745)
11-29 07:46:22.603 4816-4816/? W/System.err: at java.lang.reflect.Method.invokeNative(Native Method)
11-29 07:46:22.603 4816-4816/? W/System.err: at java.lang.reflect.Method.invoke(Method.java:511)
11-29 07:46:22.603 4816-4816/? W/System.err: at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:786)
11-29 07:46:22.603 4816-4816/? W/System.err: at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:553)
11-29 07:46:22.603 4816-4816/? W/System.err: at dalvik.system.NativeStart.main(Native Method)
11-29 07:46:22.603 4816-4816/? D/AndroidRuntime: Shutting down VM
11-29 07:46:22.603 4816-4816/? W/dalvikvm: threadid=1: thread exiting with uncaught exception (group=0xa6265288)
11-29 07:46:22.603 4816-4816/? E/AndroidRuntime: FATAL EXCEPTION: main
java.lang.RuntimeException: Unable to start activity ComponentInfo{mjt.openassetdb/mjt.openassetdb.MainActivity}: java.lang.RuntimeException: No Database Available.
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2059)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2084)
at android.app.ActivityThread.access$600(ActivityThread.java:130)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1195)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loop(Looper.java:137)
at android.app.ActivityThread.main(ActivityThread.java:4745)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:511)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:786)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:553)
at dalvik.system.NativeStart.main(Native Method)
Caused by: java.lang.RuntimeException: No Database Available.
at mjt.openassetdb.OpenAssetDBHelper.<init>(OpenAssetDBHelper.java:120)
at mjt.openassetdb.OpenAssetDBHelper.getInstance(OpenAssetDBHelper.java:80)
at mjt.openassetdb.MainActivity.onCreate(MainActivity.java:87)
at android.app.Activity.performCreate(Activity.java:5008)
at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1079)
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2023)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2084)
at android.app.ActivityThread.access$600(ActivityThread.java:130)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1195)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loop(Looper.java:137)
at android.app.ActivityThread.main(ActivityThread.java:4745)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:511)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:786)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:553)
at dalvik.system.NativeStart.main(Native Method)
The first pertinent line is D/OADB-HLPR: copyDatabaseFromAssets attempting to find asset databases/Shopper.lite
This provides the path within the assets folder where the asset is expected to be found (in this example the filename is expected to be Shopper.lite in the databases subfolder/directory)
The line D/OADB-HLPR: copyDatabaseFromAssets Did not locate asset databases/Shopper.lite
reports that the asset file was not found.
This is followed by the trapped exception (not the actual crash)
Processing continues until the final crash as reported by :-
E/AndroidRuntime: FATAL EXCEPTION: main
java.lang.RuntimeException: Unable to start activity ComponentInfo{mjt.openassetdb/mjt.openassetdb.MainActivity}: java.lang.RuntimeException: No Database Available.
Additional - Asset not found example
using
mShopper = OpenAssetDBHelper.getInstance(DB3_INDEX,
this,
DBNAME3,
DBVERSION,
"Shopper.lite", // not the asset name
new String{"databases"}
);
Where
- DBNAME3 resolves to rumplestiltskin (the final database name)
- DBVERSION is 1
- and the asset filename is Shopper.lite which should be in the databases folder (doesn't exist though).
The resultant log is :-
11-29 07:46:22.603 4816-4816/? D/OADB-HLPR: OpenAssetDBHelper constructed.
11-29 07:46:22.603 4816-4816/? D/OADB-HLPR: OpenAssetDBHelper being constructed.
11-29 07:46:22.603 4816-4816/? D/OADB-HLPR: ifDatabaseExists initiated.
11-29 07:46:22.603 4816-4816/? D/OADB-HLPR: Database rumplestilskin not found at /data/data/mjt.openassetdb/databases/rumplestilskin so attempting to copy from assets.
11-29 07:46:22.603 4816-4816/? D/OADB-HLPR: copyDatabaseFromAssets initiated
11-29 07:46:22.603 4816-4816/? D/OADB-HLPR: copyDatabaseFromAssets attempting to find asset databases/Shopper.lite
11-29 07:46:22.603 4816-4816/? D/OADB-HLPR: copyDatabaseFromAssets Did not locate asset databases/Shopper.lite
11-29 07:46:22.603 4816-4816/? W/System.err: java.io.FileNotFoundException: databases/Shopper.lite
11-29 07:46:22.603 4816-4816/? W/System.err: at android.content.res.AssetManager.openAsset(Native Method)
11-29 07:46:22.603 4816-4816/? W/System.err: at android.content.res.AssetManager.open(AssetManager.java:315)
11-29 07:46:22.603 4816-4816/? W/System.err: at android.content.res.AssetManager.open(AssetManager.java:289)
11-29 07:46:22.603 4816-4816/? W/System.err: at mjt.openassetdb.OpenAssetDBHelper.copyDatabaseFromAssets(OpenAssetDBHelper.java:187)
11-29 07:46:22.603 4816-4816/? W/System.err: at mjt.openassetdb.OpenAssetDBHelper.<init>(OpenAssetDBHelper.java:117)
11-29 07:46:22.603 4816-4816/? W/System.err: at mjt.openassetdb.OpenAssetDBHelper.getInstance(OpenAssetDBHelper.java:80)
11-29 07:46:22.603 4816-4816/? W/System.err: at mjt.openassetdb.MainActivity.onCreate(MainActivity.java:87)
11-29 07:46:22.603 4816-4816/? W/System.err: at android.app.Activity.performCreate(Activity.java:5008)
11-29 07:46:22.603 4816-4816/? W/System.err: at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1079)
11-29 07:46:22.603 4816-4816/? W/System.err: at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2023)
11-29 07:46:22.603 4816-4816/? W/System.err: at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2084)
11-29 07:46:22.603 4816-4816/? W/System.err: at android.app.ActivityThread.access$600(ActivityThread.java:130)
11-29 07:46:22.603 4816-4816/? W/System.err: at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1195)
11-29 07:46:22.603 4816-4816/? W/System.err: at android.os.Handler.dispatchMessage(Handler.java:99)
11-29 07:46:22.603 4816-4816/? W/System.err: at android.os.Looper.loop(Looper.java:137)
11-29 07:46:22.603 4816-4816/? W/System.err: at android.app.ActivityThread.main(ActivityThread.java:4745)
11-29 07:46:22.603 4816-4816/? W/System.err: at java.lang.reflect.Method.invokeNative(Native Method)
11-29 07:46:22.603 4816-4816/? W/System.err: at java.lang.reflect.Method.invoke(Method.java:511)
11-29 07:46:22.603 4816-4816/? W/System.err: at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:786)
11-29 07:46:22.603 4816-4816/? W/System.err: at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:553)
11-29 07:46:22.603 4816-4816/? W/System.err: at dalvik.system.NativeStart.main(Native Method)
11-29 07:46:22.603 4816-4816/? D/AndroidRuntime: Shutting down VM
11-29 07:46:22.603 4816-4816/? W/dalvikvm: threadid=1: thread exiting with uncaught exception (group=0xa6265288)
11-29 07:46:22.603 4816-4816/? E/AndroidRuntime: FATAL EXCEPTION: main
java.lang.RuntimeException: Unable to start activity ComponentInfo{mjt.openassetdb/mjt.openassetdb.MainActivity}: java.lang.RuntimeException: No Database Available.
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2059)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2084)
at android.app.ActivityThread.access$600(ActivityThread.java:130)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1195)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loop(Looper.java:137)
at android.app.ActivityThread.main(ActivityThread.java:4745)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:511)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:786)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:553)
at dalvik.system.NativeStart.main(Native Method)
Caused by: java.lang.RuntimeException: No Database Available.
at mjt.openassetdb.OpenAssetDBHelper.<init>(OpenAssetDBHelper.java:120)
at mjt.openassetdb.OpenAssetDBHelper.getInstance(OpenAssetDBHelper.java:80)
at mjt.openassetdb.MainActivity.onCreate(MainActivity.java:87)
at android.app.Activity.performCreate(Activity.java:5008)
at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1079)
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2023)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2084)
at android.app.ActivityThread.access$600(ActivityThread.java:130)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1195)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loop(Looper.java:137)
at android.app.ActivityThread.main(ActivityThread.java:4745)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:511)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:786)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:553)
at dalvik.system.NativeStart.main(Native Method)
The first pertinent line is D/OADB-HLPR: copyDatabaseFromAssets attempting to find asset databases/Shopper.lite
This provides the path within the assets folder where the asset is expected to be found (in this example the filename is expected to be Shopper.lite in the databases subfolder/directory)
The line D/OADB-HLPR: copyDatabaseFromAssets Did not locate asset databases/Shopper.lite
reports that the asset file was not found.
This is followed by the trapped exception (not the actual crash)
Processing continues until the final crash as reported by :-
E/AndroidRuntime: FATAL EXCEPTION: main
java.lang.RuntimeException: Unable to start activity ComponentInfo{mjt.openassetdb/mjt.openassetdb.MainActivity}: java.lang.RuntimeException: No Database Available.
answered Nov 29 '18 at 8:17
MikeTMikeT
17.3k112643
17.3k112643
add a comment |
add a comment |
Thanks for contributing an answer to Stack Overflow!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53414789%2fandroid-sqlite-errorcopyingdatabase-error%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Possible duplicate of Android : Error Copying database (Sqliite) From Asset Folder
– Lekr0
Nov 21 '18 at 15:11
It is not a duplicate since the presented soulutions in that topic already is in my code. Please see my first post.
– Ulrich_Peters
Nov 21 '18 at 15:20