Ваш код в порядке.
Я скопировал весь код, который вы предоставили, и попытался воссоздать ошибки, которые у вас есть.
Сначала следует ожидать трассировки стека, которую вы показываете, поскольку это результат перехвата (перехваченного через catch), который неизбежен при использовании (в методе checkDB
): -
checkDB = SQLiteDatabase.openDatabase(myPath, null, SQLiteDatabase.OPEN_READONLY);
и база данных не существует. Трассировка стека не из ФАТАЛЬНОГО ИСКЛЮЧЕНИЯ. Однако сама трассировка стека выдается в методе openDatabase
, поэтому не может быть легко подавлена.
Таким образом, любое ФАТАЛЬНОЕ ИСКЛЮЧЕНИЕ должно быть в другом месте. Вы должны проверить журнал дальше.
Запуск вашего кода без правильно названного файла (например, FlagsQuiz.txt в отличие от FlagsQuiz ) приводит к (примечание, что в ваш код добавлено ведение журнала)
т.е.. два файла, используемые для тестирования (расширение NOTADB не является базой данных sqlite, расширение txt является допустимой базой данных sqlite с добавленным расширением): -

Результат: -
08-29 01:01:19.323 2602-2602/? D/CHKDB: Issuing openDatabase for path :- /data/data/so52053932.so52053932/databases/FlagsQuiz
08-29 01:01:19.331 2602-2602/? E/SQLiteLog: (14) cannot open file at line 30174 of [00bb9c9ce4]
(14) os_unix.c:30174: (2) open(/data/data/so52053932.so52053932/databases/FlagsQuiz) -
08-29 01:01:19.331 2602-2602/? E/SQLiteDatabase: Failed to open database '/data/data/so52053932.so52053932/databases/FlagsQuiz'.
android.database.sqlite.SQLiteCantOpenDatabaseException: unknown error (code 14): Could not open database
at android.database.sqlite.SQLiteConnection.nativeOpen(Native Method)
at android.database.sqlite.SQLiteConnection.open(SQLiteConnection.java:209)
at android.database.sqlite.SQLiteConnection.open(SQLiteConnection.java:193)
at android.database.sqlite.SQLiteConnectionPool.openConnectionLocked(SQLiteConnectionPool.java:463)
at android.database.sqlite.SQLiteConnectionPool.open(SQLiteConnectionPool.java:185)
at android.database.sqlite.SQLiteConnectionPool.open(SQLiteConnectionPool.java:177)
at android.database.sqlite.SQLiteDatabase.openInner(SQLiteDatabase.java:804)
at android.database.sqlite.SQLiteDatabase.open(SQLiteDatabase.java:789)
at android.database.sqlite.SQLiteDatabase.openDatabase(SQLiteDatabase.java:694)
at android.database.sqlite.SQLiteDatabase.openDatabase(SQLiteDatabase.java:669)
at so52053932.so52053932.DataBaseHandler.checkDataBase(DataBaseHandler.java:89)
at so52053932.so52053932.DataBaseHandler.createDataBase(DataBaseHandler.java:48)
at so52053932.so52053932.DAO.<init>(DAO.java:17)
at so52053932.so52053932.MainActivity.onCreate(MainActivity.java:18)
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)
08-29 01:01:19.331 2602-2602/? D/CHECKDB: SQLiteException has bee caught.
08-29 01:01:19.339 2602-2602/? D/ONCREATE: New Database has been created so ONCREATE has been invoked.
08-29 01:01:19.339 2602-2602/? D/CPYDB: Database Copy Initiated. Trying to open InputStream i.e. asset database/FlagsQuiz
08-29 01:01:19.339 2602-2602/? W/System.err: java.io.FileNotFoundException: database/FlagsQuiz
at android.content.res.AssetManager.openAsset(Native Method)
at android.content.res.AssetManager.open(AssetManager.java:315)
at android.content.res.AssetManager.open(AssetManager.java:289)
at so52053932.so52053932.DataBaseHandler.copyDataBase(DataBaseHandler.java:119)
at so52053932.so52053932.DataBaseHandler.createDataBase(DataBaseHandler.java:62)
at so52053932.so52053932.DAO.<init>(DAO.java:17)
at so52053932.so52053932.MainActivity.onCreate(MainActivity.java:18)
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)
08-29 01:01:19.347 2602-2602/? W/System.err: 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)
08-29 01:01:19.347 2602-2602/? D/AndroidRuntime: Shutting down VM
08-29 01:01:19.347 2602-2602/? W/dalvikvm: threadid=1: thread exiting with uncaught exception (group=0xa62a0288)
08-29 01:01:19.347 2602-2602/? E/AndroidRuntime: FATAL EXCEPTION: main
java.lang.Error: Error copying database
at so52053932.so52053932.DataBaseHandler.createDataBase(DataBaseHandler.java:67)
at so52053932.so52053932.DAO.<init>(DAO.java:17)
at so52053932.so52053932.MainActivity.onCreate(MainActivity.java:18)
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)
- Было 3 исключения (середина, которая появляется как 2-ая, печатает трассировку стека, когда последнее исключение было поймано / захвачено).
- Первое исключение не является ФАТАЛЬНЫМ и является таким, как описано выше (т.е. ожидаемое исключение из метода
checkDB
)
- Второе исключение является фактическим исключением, вызывающим проблему. Тем не менее, он был захвачен (и из-за того, что был напечатан дополнительный код, поэтому он не будет отображаться в вашем коде, так как он не печатается), в этом случае это связано с тем, что файл ресурса не найден (т. Е. Код ожидая FlagsQuiz не FlagsQuiz.txt или FlagsQuixk.NOTADB ).
- Третье исключение соответствует
throw new Error("Error copying database");
в методе createDatabase
. (Не очень полезно, поскольку в вашем коде реальная причина / позиция в коде скрыта).
ПРИМЕЧАНИЕ На данном этапе базовая база данных фактически создана. **
согласно 08-29 01:01:19.339 2602-2602/? D/ONCREATE: New Database has been created so ONCREATE has been invoked.
например. Device Explorer показывает: -
Таким образом, последующий запуск не будет пытаться скопировать базу данных из активов, поскольку она существует. Однако , база данных, которая существует, НЕ будет иметь никаких таблиц, кроме sqlite_master и android_metadata . То есть, по сути, база данных пуста с точки зрения приложения (вы ожидаете по крайней мере 16 КБ (если я правильно помню) как еще одну страницу 4 КБ для любой другой таблицы)).

Поэтому, по-видимому, ваша настоящая проблема - это другая проблема. Возможно, я бы предложил изменить ваш код, чтобы включить временную отладку согласно (см. // <<<<< </strong> комментарии): -
DAO.java
public class DAO {
DataBaseHandler dbHandler;
public DAO(Context context) {
dbHandler = new DataBaseHandler(context);
try {
dbHandler.createDataBase();
} catch (IOException ioe) {
throw new Error("Unable to create database");
}
try {
dbHandler.openDataBase();
Log.d("DAO","Attempting to open the database."); //<<<<< ADDED
} catch (SQLException sqle) {
Log.d("DAOCONSTRUCTOR","Error attempting to Open Database."); //<<<<< ADDED
sqle.printStackTrace(); //<<<<< ADDED
throw sqle;
}
// Log.e("path2",
// context.getDatabasePath("FootballFlagQuiz").toString());
}
}
DataBaseHandler.java
public class DataBaseHandler extends SQLiteOpenHelper {
// The Androids default system path of your application database.
private static String DB_PATH;
private static String DB_NAME = "FlagsQuiz";
private SQLiteDatabase myDataBase;
private final Context myContext;
/**
* Constructor Takes and keeps a reference of the passed context in order to
* access to the application assets and resources.
*
* @param context
*/
public DataBaseHandler(Context context) {
super(context, DB_NAME, null, 1);
this.myContext = context;
DB_PATH = context.getDatabasePath(DB_NAME).toString();
// Log.e("path", DB_PATH);
}
// ==============================================================================
/**
* Creates a empty database on the system and rewrites it with your own
* database.
* */
public void createDataBase() throws IOException {
boolean dbExist = checkDataBase();
if (dbExist) {
// do nothing - database already exist
} else {
// By calling this method and empty database will be created into
// the default system path
// of your application so we are gonna be able to overwrite that
// database with our database.
this.getReadableDatabase();
try {
copyDataBase();
} catch (IOException e) {
e.printStackTrace(); //<<<<< ADDED
throw new Error("Error copying database");
}
}
}
// ==============================================================================
/**
* Check if the database already exist to avoid re-copying the file each
* time you open the application.
*
* @return true if it exists, false if it doesn't
*/
private boolean checkDataBase() {
SQLiteDatabase checkDB = null;
try {
String myPath = DB_PATH;
Log.d("CHKDB","Issuing openDatabase for path :- " + myPath); //<<<<< ADDED
checkDB = SQLiteDatabase.openDatabase(myPath, null, SQLiteDatabase.OPEN_READONLY);
boolean checkresult = checkDB != null; //<<<<< ADDED
Log.d("CHKDB", "Result of check is " + String.valueOf(checkresult)); //<<<<< ADDED
} catch (SQLiteException e) {
Log.d("CHECKDB", "SQLiteException has bee caught."); //<<<<< ADDED
// database does't exist yet.
}
if (checkDB != null) {
Log.d("CHECKDB","DB exists so closing the opened DB."); //<<<<< ADDED
checkDB.close();
}
return checkDB != null ? true : false;
}
// ==============================================================================
/**
* Copies your database from your local assets-folder to the just created
* empty database in the system folder, from where it can be accessed and
* handled. This is done by transfering bytestream.
* */
private void copyDataBase() throws IOException {
Log.d("CPYDB","Database Copy Initiated. Trying to open InputStream i.e. asset " + "database/" + DB_NAME); //<<<<< ADDED
// Open your local db as the input stream
InputStream myInput = myContext.getAssets().open("database/" + DB_NAME);
Log.d("CPYDB","InputStream Opened successfully. Now trying to open OutputStream path = " + DB_PATH); //<<<<< ADDED
// Path to the just created empty db
String outFileName = DB_PATH;
// Open the empty db as the output stream
OutputStream myOutput = new FileOutputStream(outFileName);
Log.d("CPYDB","OutputStream Opened successfully. Now trying to copy from InputStream to OutputStream."); //<<<<< ADDED
// transfer bytes from the inputfile to the outputfile
byte[] buffer = new byte[1024];
int length;
while ((length = myInput.read(buffer)) > 0) {
myOutput.write(buffer, 0, length);
Log.d("CPYDB","Copied " + String.valueOf(length) + " bytes."); //<<<<< ADDED
}
Log.d("CPYDB","Completed Copy from asset to DB. Flusing and closing Streams"); //<<<<< ADDED
// Close the streams
myOutput.flush();
myOutput.close();
myInput.close();
Log.d("CPYDB","Copy complete and all sterams flushed and closed. Copied " + String.valueOf(length) + "bytes."); //<<<<< ADDED
}
// ==============================================================================
public void openDataBase() throws SQLException {
// Open the database
String myPath = DB_PATH;
myDataBase = SQLiteDatabase.openDatabase(myPath, null, SQLiteDatabase.OPEN_READONLY);
}
// ==============================================================================
@Override
public synchronized void close() {
if (myDataBase != null)
myDataBase.close();
super.close();
}
// ==============================================================================
@Override
public void onCreate(SQLiteDatabase db) {
Log.d("ONCREATE","New Database has been created so ONCREATE has been invoked."); //<<<<< ADDED
}
// ==============================================================================
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
}
// Add your public helper methods to access and get content from the
// database.
// You could return cursors by doing "return myDataBase.query(....)" so it'd
// be easy
// to you to create adapters for your views.
}
С учетом вышеуказанных изменений и, возможно, лучшего понимания трассировки стека вы сможете точно определить реальную ошибку (и), с которой вы столкнулись.
Действительный прогон
Запуск вашего кода с действительной БД в файле ресурсов и использование следующего в качестве (вызывающего) MainActivity
: -
public class MainActivity extends AppCompatActivity {
DAO myDAO;
DataBaseHandler myDBhandler;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
myDAO = new DAO(this);
myDBhandler = myDAO.dbHandler;
SQLiteDatabase db = myDBhandler.getWritableDatabase();
Cursor csr = db.query("sqlite_master",null,null,null,null,null,null);
while (csr.moveToNext()) {
Log.d("COMPONENTS","Found " + csr.getString(csr.getColumnIndex("name")) + " Type is " + csr.getString(csr.getColumnIndex("type")));
}
csr.close();
}
}
Результат: -
08-29 01:14:06.139 2699-2699/? D/CHKDB: Issuing openDatabase for path :- /data/data/so52053932.so52053932/databases/FlagsQuiz
08-29 01:14:06.139 2699-2699/? E/SQLiteLog: (14) cannot open file at line 30174 of [00bb9c9ce4]
(14) os_unix.c:30174: (2) open(/data/data/so52053932.so52053932/databases/FlagsQuiz) -
08-29 01:14:06.139 2699-2699/? E/SQLiteDatabase: Failed to open database '/data/data/so52053932.so52053932/databases/FlagsQuiz'.
android.database.sqlite.SQLiteCantOpenDatabaseException: unknown error (code 14): Could not open database
at android.database.sqlite.SQLiteConnection.nativeOpen(Native Method)
at android.database.sqlite.SQLiteConnection.open(SQLiteConnection.java:209)
at android.database.sqlite.SQLiteConnection.open(SQLiteConnection.java:193)
at android.database.sqlite.SQLiteConnectionPool.openConnectionLocked(SQLiteConnectionPool.java:463)
at android.database.sqlite.SQLiteConnectionPool.open(SQLiteConnectionPool.java:185)
at android.database.sqlite.SQLiteConnectionPool.open(SQLiteConnectionPool.java:177)
at android.database.sqlite.SQLiteDatabase.openInner(SQLiteDatabase.java:804)
at android.database.sqlite.SQLiteDatabase.open(SQLiteDatabase.java:789)
at android.database.sqlite.SQLiteDatabase.openDatabase(SQLiteDatabase.java:694)
at android.database.sqlite.SQLiteDatabase.openDatabase(SQLiteDatabase.java:669)
at so52053932.so52053932.DataBaseHandler.checkDataBase(DataBaseHandler.java:89)
at so52053932.so52053932.DataBaseHandler.createDataBase(DataBaseHandler.java:48)
at so52053932.so52053932.DAO.<init>(DAO.java:17)
at so52053932.so52053932.MainActivity.onCreate(MainActivity.java:18)
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)
08-29 01:14:06.139 2699-2699/? D/CHECKDB: SQLiteException has bee caught.
08-29 01:14:06.151 2699-2699/? D/ONCREATE: New Database has been created so ONCREATE has been invoked.
08-29 01:14:06.151 2699-2699/? D/CPYDB: Database Copy Initiated. Trying to open InputStream i.e. asset database/FlagsQuiz
InputStream Opened successfully. Now trying to open OutputStream path = /data/data/so52053932.so52053932/databases/FlagsQuiz
OutputStream Opened successfully. Now trying to copy from InputStream to OutputStream.
Copied 1024 bytes.
Copied 1024 bytes.
Copied 1024 bytes.
Copied 1024 bytes.
Copied 1024 bytes.
Copied 1024 bytes.
Copied 1024 bytes.
Copied 1024 bytes.
Copied 1024 bytes.
Copied 1024 bytes.
Copied 1024 bytes.
Copied 1024 bytes.
Copied 1024 bytes.
Copied 1024 bytes.
Copied 1024 bytes.
Copied 1024 bytes.
Copied 1024 bytes.
Copied 1024 bytes.
Copied 1024 bytes.
Copied 1024 bytes.
Copied 1024 bytes.
Copied 1024 bytes.
Copied 1024 bytes.
Copied 1024 bytes.
Copied 1024 bytes.
Copied 1024 bytes.
Copied 1024 bytes.
Copied 1024 bytes.
Completed Copy from asset to DB. Flusing and closing Streams
Copy complete and all sterams flushed and closed. Copied -1bytes.
08-29 01:14:06.151 2699-2699/? D/DAO: Attempting to open the database.
08-29 01:14:06.159 2699-2699/? D/COMPONENTS: Found android_metadata Type is table
Found PrivateList Type is table
Found PrivateProduct Type is table
Found List_Product Type is table
Found sqlite_autoindex_List_Product_1 Type is index
Альтернативная проверка БД
Следующий код представляет собой альтернативный метод, который проверяет, существует ли БД (предполагается, что она является действительной БД) без выдачи SQLiteException. то есть он проверяет файл БД, а не БД ( он также не будет создавать пустую базу данных в случае сбоя копирования ): -
private boolean ifDatabaseExists(String dbpath) {
File db = new File(dbpath);
if(db.exists()) return true;
File dir = new File(db.getParent());
if (!dir.exists()) {
dir.mkdirs();
}
return false;
}
- это можно использовать в качестве альтернативы методу
checkDB
.