Я полагаю, что это проблема, связанная с тем, что SQLiteAssetHelper не справляется с введением баз данных SQLite с использованием WAL (запись в журнал с опережением записи) по умолчанию (режим журнала использовался по умолчанию до API 28).
Если нет, то, по сути, файл molmassen.file (названный именно так) не находится в папке assets / database .В любом случае приведенное ниже исправление будет работать, если файл базы данных называется molmassen.db И он находится в папке базы данных в папке ресурсов.
Поэтому я бы предложил изменить метод копирования, отличный от SQLiteAssetHelper, для копированиябазы данных.
Например, рассмотрим следующий альтернативный помощник по базам данных, а именно: DatabaseOpenHelperAlt
public class DatabaseOpenHelperAlt extends SQLiteOpenHelper {
private static final String DATABASE_NAME = "molmassen.db";
private static final int DATABASE_VERSION = 1;
Context myContext;
int buffer_size = 1024 * 4, blocks_copied = 0, bytes_copied = 0;
public DatabaseOpenHelperAlt(Context context){
super(context, DATABASE_NAME, null, DATABASE_VERSION);
myContext = context;
if (!checkDataBase()) {
try {
copyDataBase();
} catch (IOException e) {
e.printStackTrace();
throw new RuntimeException("Error copy database file " + DATABASE_NAME + " - see stack-trace above" );
}
}
}
@Override
public void onCreate(SQLiteDatabase db) {
}
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
}
private boolean checkDataBase() {
/**
* Does not open the database instead checks to see if the file exists
* also creates the databases directory if it does not exists
* (the real reason why the database is opened, which appears to result in issues)
*/
File db = new File(myContext.getDatabasePath(DATABASE_NAME).getPath()); //Get the file name of the database
Log.d("DBPATH","DB Path is " + db.getPath()); //TODO remove for Live App
if (db.exists()) return true; // If it exists then return doing nothing
// Get the parent (directory in which the database file would be)
File dbdir = db.getParentFile();
// If the directory does not exits then make the directory (and higher level directories)
if (!dbdir.exists()) {
db.getParentFile().mkdirs();
dbdir.mkdirs();
}
return false;
}
private void copyDataBase() throws IOException {
final String TAG = "COPYDATABASE";
//Open your local db as the input stream
Log.d(TAG,"Initiated Copy of the database file " + DATABASE_NAME + " from the assets folder."); //TODO remove for Live App
//Note how the databases folder is hard coded (to suit the same location as used by SQLiteAssetHelper)
InputStream myInput = myContext.getAssets().open("databases" + File.separator + DATABASE_NAME); // Open the Asset file
String dbpath = myContext.getDatabasePath(DATABASE_NAME).getPath();
Log.d(TAG,"Asset file " + DATABASE_NAME + " found so attmepting to copy to " + dbpath); //TODO remove for Live App
// Path to the just created empty db
//String outFileName = DB_PATH + DB_NAME;
//Open the empty db as the output stream
File outfile = new File(myContext.getDatabasePath(DATABASE_NAME).toString());
Log.d("DBPATH","path is " + outfile.getPath()); //TODO remove for Live App
//outfile.setWritable(true); // NOT NEEDED as permission already applies
//OutputStream myoutputx2 = new FileOutputStream(outfile);
/* Note done in checkDatabase method
if (!outfile.getParentFile().exists()) {
outfile.getParentFile().mkdirs();
}
*/
OutputStream myOutput = new FileOutputStream(outfile);
//transfer bytes from the inputfile to the outputfile
byte[] buffer = new byte[buffer_size];
int length;
while ((length = myInput.read(buffer))>0) {
blocks_copied++;
Log.d(TAG,"Ateempting copy of block " + String.valueOf(blocks_copied) + " which has " + String.valueOf(length) + " bytes."); //TODO remove for Live App
myOutput.write(buffer, 0, length);
bytes_copied += length;
}
Log.d(TAG,
"Finished copying Database " + DATABASE_NAME +
" from the assets folder, to " + dbpath +
String.valueOf(bytes_copied) + "were copied, in " +
String.valueOf(blocks_copied) + " blocks of size " +
String.valueOf(buffer_size) + "."
); //TODO remove for Live App
//Close the streams
myOutput.flush();
myOutput.close();
myInput.close();
Log.d(TAG,"All Streams have been flushed and closed."); //TODO remove for Live App
}
}
Использование вышеупомянутого вместе с измененным классом DatabaseAccess (для вызова альтернативного DatabaseHelper итакже метод для получения базовой базы данных SQLite для тестирования без необходимости иметь точно такую же базу данных, как у вас) проверить комментарии : -
public class DatabaseAccess {
private SQLiteOpenHelper openHelper;
private SQLiteDatabase db;
private static DatabaseAccess instance;
Cursor c = null;
public DatabaseAccess(Context context){
//this.openHelper = new DatabaseOpenHelper(context); //<<<<<<<<<< OLD REPLACED
this.openHelper = new DatabaseOpenHelperAlt(context); //<<<<<<<<<< NEW
db = this.openHelper.getWritableDatabase(); //<<<<<<<<<< force open
}
//!!!!!!!!! ADDED for simple testing
public SQLiteDatabase getDB() {
return db;
}
public static DatabaseAccess getInstance (Context context){
if (instance == null){
instance = new DatabaseAccess(context);
}
return instance;
}
public void open(){
this.db=openHelper.getWritableDatabase();
}
public void close(){
if(db!=null){
this.db.close();
}
}
public String getMolmasse(String kürzel){
c=db.rawQuery("select Molmasse from Molmassen where Kürzel = '"+kürzel+"'",new String[]{});
StringBuffer buffer = new StringBuffer();
while (c.moveToNext()){
String masse = c.getString(0);
buffer.append(""+masse);
}
return buffer.toString();
}
}
Работающее приложение со следующим фрагментом (уменьшено для удобства): -
public class MolassesFragment extends Fragment {
public DatabaseAccess databaseAccess;
private MolassesViewModel mViewModel;
public static MolassesFragment newInstance() {
return new MolassesFragment();
}
@Nullable
@Override
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container,
@Nullable Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.molasses_fragment, container, false);
databaseAccess = new DatabaseAccess(getContext());
SQLiteDatabase db = databaseAccess.getDB();
Cursor csr = db.query("sqlite_master",null,null,null,null,null,null);
DatabaseUtils.dumpCursor(csr);
csr.close();
return view;
}
@Override
public void onActivityCreated(@Nullable Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
mViewModel = ViewModelProviders.of(this).get(MolassesViewModel.class);
// TODO: Use the ViewModel
}
}
Для первого запуска (запуска, который копирует базу данных), он работает, и журнал показывает: -
2019-03-26 12:14:15.419 7929-7929/aaa.so55342826preexistdbassethelperexample D/DBPATH: DB Path is /data/user/0/aaa.so55342826preexistdbassethelperexample/databases/molmassen.db
2019-03-26 12:14:15.419 7929-7929/aaa.so55342826preexistdbassethelperexample D/COPYDATABASE: Initiated Copy of the database file molmassen.db from the assets folder.
2019-03-26 12:14:15.419 7929-7929/aaa.so55342826preexistdbassethelperexample D/COPYDATABASE: Asset file molmassen.db found so attmepting to copy to /data/user/0/aaa.so55342826preexistdbassethelperexample/databases/molmassen.db
2019-03-26 12:14:15.419 7929-7929/aaa.so55342826preexistdbassethelperexample D/DBPATH: path is /data/user/0/aaa.so55342826preexistdbassethelperexample/databases/molmassen.db
2019-03-26 12:14:15.419 7929-7929/aaa.so55342826preexistdbassethelperexample D/COPYDATABASE: Ateempting copy of block 1 which has 4096 bytes.
2019-03-26 12:14:15.420 7929-7929/aaa.so55342826preexistdbassethelperexample D/COPYDATABASE: Ateempting copy of block 2 which has 4096 bytes.
.....
2019-03-26 12:14:15.422 7929-7929/aaa.so55342826preexistdbassethelperexample D/COPYDATABASE: Ateempting copy of block 27 which has 4096 bytes.
2019-03-26 12:14:15.422 7929-7929/aaa.so55342826preexistdbassethelperexample D/COPYDATABASE: Finished copying Database molmassen.db from the assets folder, to /data/user/0/aaa.so55342826preexistdbassethelperexample/databases/molmassen.db110592were copied, in 27 blocks of size 4096.
2019-03-26 12:14:15.423 7929-7929/aaa.so55342826preexistdbassethelperexample D/COPYDATABASE: All Streams have been flushed and closed.
2019-03-26 12:14:15.452 7929-7929/aaa.so55342826preexistdbassethelperexample
.......... остальная часть журнала опущена как слишком большая, но достаточно сказать, что ожидаемые таблицы были отображены.