Я решил реструктурировать свою базу данных. Также я решил использовать Room для организации сотрудничества между моей БД и моим APP, вместо использования SQL запросов и курсоров. Моя база данных находится в папке Assets в Android Studio, а также в папке assets / files на эмуляторе. Мой класс, который копирует DB из ресурсов в папку assets / files внизу.
public class DatabaseHelper extends SQLiteOpenHelper implements TypeOfTest {
private static String DB_PATH;
private static String DB_NAME;
private static final int SCHEMA = 2;
public static final String DB_OLD = "ForEastory.db";
public static final String DB_NEW = "ForEastory2.db";
private Context myContext;
public DatabaseHelper(Context context, String dbName) {
super(context, DB_NAME, null, SCHEMA);
this.myContext = context;
DB_NAME = dbName;
DB_PATH = context.getFilesDir().getPath() + "/"+ DB_NAME;
Log.d("files dir + name", DB_PATH);
}
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
}
public void create_db(){
InputStream myInput;
OutputStream myOutput;
try {
File file = new File(DB_PATH);
if (!file.exists()) {
this.getReadableDatabase();
myInput = myContext.getAssets().open(DB_NAME);
String outFileName = DB_PATH;
myOutput = new FileOutputStream(outFileName);
byte[] buffer = new byte[1024];
int length;
while ((length = myInput.read(buffer)) > 0) {
myOutput.write(buffer, 0, length);
}
myOutput.flush();
myOutput.close();
myInput.close();
}
}
catch(IOException ex){
ex.printStackTrace();
}
}
public SQLiteDatabase open() throws SQLException {
return SQLiteDatabase.openDatabase(DB_PATH, null, SQLiteDatabase.OPEN_READWRITE);
}
@Override
public void onCreate(SQLiteDatabase db) {
}
}
Как вы можете видеть, здесь у меня есть названия баз данных. Этот класс работы с моей старой БД. Кроме того, используя Device FIle Explorer, я вижу, что база данных на самом деле находится в папке assets / files на эмуляторе. Возможно, проблема в классе Room Database, где я пытаюсь использовать свою подготовленную базу данных.
@androidx.room.Database(entities = {Question.class, Topic.class, Test.class}, version = 1, exportSchema = false)
public abstract class Database extends RoomDatabase {
private static Database instance;
public abstract TestDao testDao();
public static String ASSET_DIR;
public static synchronized Database getInstance(Context context) {
if (instance == null) {
try {
ASSET_DIR = context.getFilesDir().getPath() + "/"+ DatabaseHelper.DB_NEW;
instance = Room.databaseBuilder(context.getApplicationContext(),
Database.class,
"AppDB")
.createFromAsset(ASSET_DIR)
.build();
}
catch (Exception e) {
e.printStackTrace();
}
}
return instance;
}
}
Вот мой класс TestDao.
@Dao
public interface TestDao {
@Query("SELECT * FROM tests WHERE topic_id = :id")
TopicWithQuestions getTopicWithQuestionsById(int id);
}
И как мне вообще это использовать.
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.test);
testNum = findViewById(R.id.testNum);
getQuestions = findViewById(R.id.get_questions);
DatabaseHelper databaseHelper = new DatabaseHelper(getApplicationContext(), DatabaseHelper.DB_NEW);
databaseHelper.create_db();
try {
myDb = databaseHelper.open();
} catch (SQLException e) {
e.printStackTrace();
}
db = Database.getInstance(getApplicationContext());
testDao = db.testDao();
getQuestions.setOnClickListener(v -> {
try {
int id = Integer.parseInt(testNum.getText().toString());
//In this place i've catched the exception (RoomTest.java:61)
TopicWithQuestions topicWithQuestions = testDao.getTopicWithQuestionsById(id);
List<Question> questionList = topicWithQuestions.getQuestion();
for (Question question : questionList) {
System.out.println(question.getQuestion());
}
} catch (Exception e) {
e.printStackTrace();
}
});
}
Наконец, logcat:
W/System.err: java.lang.RuntimeException: Unable to copy database file.
at androidx.room.SQLiteCopyOpenHelper.verifyDatabaseFile(SQLiteCopyOpenHelper.java:131)
at androidx.room.SQLiteCopyOpenHelper.getWritableDatabase(SQLiteCopyOpenHelper.java:87)
at androidx.room.RoomDatabase.inTransaction(RoomDatabase.java:476)
at androidx.room.RoomDatabase.assertNotSuspendingTransaction(RoomDatabase.java:281)
at com.prodadimhaski.eastory2.Room.Dao.TestDao_Impl.getTopicWithQuestionsById(TestDao_Impl.java:33)
at com.prodadimhaski.eastory2.Room.RoomTest.lambda$onCreate$0$RoomTest(RoomTest.java:61)
at com.prodadimhaski.eastory2.Room.-$$Lambda$RoomTest$6iMa7yj1shnTdXRtmzsROKAwX-w.onClick(lambda)
at android.view.View.performClick(View.java:4438)
at android.view.View$PerformClick.run(View.java:18422)
at android.os.Handler.handleCallback(Handler.java:733)
at android.os.Handler.dispatchMessage(Handler.java:95)
at android.os.Looper.loop(Looper.java:136)
at android.app.ActivityThread.main(ActivityThread.java:5001)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:515)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:785)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:601)
at dalvik.system.NativeStart.main(Native Method)
Caused by: java.io.FileNotFoundException: /data/data/com.prodadimhaski.eastory2/files/ForEastory2.db
at android.content.res.AssetManager.openAsset(Native Method)
at android.content.res.AssetManager.open(AssetManager.java:316)
at android.content.res.AssetManager.open(AssetManager.java:290)
at androidx.room.SQLiteCopyOpenHelper.copyDatabaseFile(SQLiteCopyOpenHelper.java:178)
at androidx.room.SQLiteCopyOpenHelper.verifyDatabaseFile(SQLiteCopyOpenHelper.java:128)
... 17 more
Этот __db.assertNotSuspendingTransaction();
является фрагментом кода в TestDao_Impl. java: 33