Я полагаю, что ваша проблема может быть связана с изменением Android Pie с режима журнала по умолчанию на запись с опережением записи.Когда создается пустая база данных (это делается для создания каталога баз данных, если он не существует) перед копированием файлов -shm и -wal, которые используются WAL.Когда база данных затем открывается, она считается недействительной из-за несоответствия между ними и скопированной базой данных, поэтому открывается пустая база данных.
Исправление: не использовать: -
//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();
, но вместо этого получить родительский путь к базе данных в виде файла (то есть путь к папке с базами данных) и затем выполнить mkdirs .
Я бы такжепредлагаем не использовать жестко закодированный путь, а использовать метод контекста getDatabasePath .
Также я бы предложил не пытаться открыть базу данных, а вместо этого проверить, существует ли файл базы данных.
Ниже приведен метод, который проверяет существование файла базы данных, а также создает каталог баз данных, готовый для копирования, и, таким образом, открывает базу данных до того, как копия не требуется.
/**
* Check if the database already exists. NOTE will create the databases folder is it doesn't exist
* @return true if it exists, false if it doesn't
*/
public static boolean checkDataBase(Context context, String dbname) {
File db = new File(context.getDatabasePath(dbname).getPath()); //Get the file name of the database
Log.d("DBPATH","DB Path is " + db.getPath()); //TODO remove if publish 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;
}
Протестированный код
Согласно комментарию
Я удалил строку;//this.getReadableDatabase ();и заменил checkDataBase своим code.boolean dbExist = checkDataBase (myContext, DB_NAME) ;.Сбой при отладке D / DBPATH: путь к БД: /data/user/0/com.silverfernsolutions.steelsections/databases.Я не могу вставить все, поскольку оно превышает лимит комментариев, и я не знаю, как обойти это
Выше было проверено и работало (результаты ниже), используя: -
DataBaseHelperReign.java
public class DataBaseHelperReign extends SQLiteOpenHelper {
//private static String DB_PATH = "/data/data/com.silverfernsolutions.steelsections/databases/"; //<<<<<<<<<< REMOVED
private static String DB_NAME = "SteelSectionProperties";
private SQLiteDatabase myDataBase;
private final Context myContext;
public DataBaseHelperReign(Context context) {
super(context, DB_NAME, null, 1);
this.myContext = context;
}
/**
* 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
Log.e("createDB.", " dbExists=true");
} 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();
Log.e("copying db helper ", "db copied");
} catch (IOException e) {
Log.e("copying db helper ", "Error copying DB");
throw new Error("Error copying database");
}
}
}
/*****************************************************************************************************
* NEW
****************************************************************************************************/
public boolean checkDataBase() {
File db = new File(myContext.getDatabasePath(DB_NAME).getPath()); //Get the file name of the database
Log.d("DBPATH","DB Path is " + db.getPath()); //TODO remove if publish 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 {
Log.e("helper copyDB ", " opening input stream");
//Open your local db as the input stream
InputStream myInput = myContext.getAssets().open(DB_NAME);
// Path to the just created empty db
//String outFileName = DB_PATH + DB_NAME; //<<<<<<<<<< COMMENTED OUT BUT TESTED
String outFileName = myContext.getDatabasePath(DB_NAME).toString(); //<<<<<<<<<< PREFERRED
Log.e("helper outfileName", outFileName);
//Open the empty db as the output stream
OutputStream myOutput = new FileOutputStream(outFileName);
//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);
}
//Close the streams
myOutput.flush();
myOutput.close();
myInput.close();
}
public void openDataBase() throws SQLException {
//Open the database
String myPath = myContext.getDatabasePath(DB_NAME).toString(); //<<<<<<<<<<
Log.e("helper openDB path ", myPath);
myDataBase = SQLiteDatabase.openDatabase(myPath, null, SQLiteDatabase.OPEN_READONLY);
Log.e("helper openDataBase ", "after SQLiteDatabase.openDatabase");
}
@Override
public synchronized void close() {
if (myDataBase != null)
myDataBase.close();
super.close();
}
@Override
public void onCreate(SQLiteDatabase db) {}
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) { }
public Cursor getTablecontents(String table) {
String q = "SELECT * FROM " + table;
Cursor mCursor = myDataBase.rawQuery(q, null);
return mCursor;
}
public ArrayList<String[]> getDatabaseStructure() {
Cursor c = myDataBase.rawQuery("SELECT name FROM sqlite_master WHERE type='table'", null);
ArrayList<String[]> result = new ArrayList<String[]>();
int i = 0;
result.add(c.getColumnNames());
for (c.moveToFirst(); !c.isAfterLast(); c.moveToNext()) {
String[] temp = new String[c.getColumnCount()];
for (i = 0; i < temp.length; i++) {
temp[i] = c.getString(i);
System.out.println("TABLE - " + temp[i]);
Cursor c1 = myDataBase.rawQuery(
"SELECT * FROM " + temp[i], null);
c1.moveToFirst();
String[] COLUMNS = c1.getColumnNames();
for (int j = 0; j < COLUMNS.length; j++) {
c1.move(j);
System.out.println(" COLUMN - " + COLUMNS[j]);
}
}
result.add(temp);
}
return result;
}
}
- Комментарии для краткости удалены
MainActivity.java
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
DataBaseHelperReign myDbHelper = new DataBaseHelperReign(this);
myDbHelper = new DataBaseHelperReign(this);
try {
myDbHelper.createDataBase();
}catch (IOException ioe) {
throw new Error("Unable to create database");
}
try {
myDbHelper.openDataBase();
}catch(SQLException sqle){
throw sqle;
}
//This does not find the table SectionProps???
//Only the android_metadata table
myDbHelper.getDatabaseStructure();
//<<<<<<<<<<< commented out as test db does not have a SectionProps table
//This causes a crash
//myDbHelper.getTablecontents("SectionProps");
}
}
- Вышеуказанное относится к вашей деятельности, кромедля попытки получить содержимое таблицы
Результат
Выше было выполнено на двух эмуляторах с тестовой базой данных, переименованной в SteelSectionProperties и помещенной в папку ресурсов.,Очевидно, что базовые таблицы были разными, но, как видно, база данных не пуста и, следовательно, была скопирована из папки активов.Одним из эмуляторов был Android Lollipop, другой Android Pie.
Журнал содержит: -
2019-03-08 06:52:44.596 10351-10351/com.silverfernsolutions.steelsections D/DBPATH: DB Path is /data/user/0/com.silverfernsolutions.steelsections/databases/SteelSectionProperties
2019-03-08 06:52:44.596 10351-10351/com.silverfernsolutions.steelsections E/helper copyDB: opening input stream
2019-03-08 06:52:44.596 10351-10351/com.silverfernsolutions.steelsections E/helper outfileName: /data/user/0/com.silverfernsolutions.steelsections/databases/SteelSectionProperties
2019-03-08 06:52:44.597 10351-10351/com.silverfernsolutions.steelsections E/copying db helper: db copied
2019-03-08 06:52:44.598 10351-10351/com.silverfernsolutions.steelsections E/helper openDB path: /data/user/0/com.silverfernsolutions.steelsections/databases/SteelSectionProperties
2019-03-08 06:52:44.601 10351-10351/com.silverfernsolutions.steelsections E/helper openDataBase: after SQLiteDatabase.openDatabase
2019-03-08 06:52:44.602 10351-10351/com.silverfernsolutions.steelsections I/System.out: TABLE - android_metadata
2019-03-08 06:52:44.603 10351-10351/com.silverfernsolutions.steelsections I/System.out: COLUMN - locale
2019-03-08 06:52:44.603 10351-10351/com.silverfernsolutions.steelsections I/System.out: TABLE - retailer
2019-03-08 06:52:44.604 10351-10351/com.silverfernsolutions.steelsections I/System.out: COLUMN - _id
2019-03-08 06:52:44.604 10351-10351/com.silverfernsolutions.steelsections I/System.out: COLUMN - retailerName
2019-03-08 06:52:44.604 10351-10351/com.silverfernsolutions.steelsections I/System.out: TABLE - tariff
2019-03-08 06:52:44.605 10351-10351/com.silverfernsolutions.steelsections I/System.out: COLUMN - _id
2019-03-08 06:52:44.605 10351-10351/com.silverfernsolutions.steelsections I/System.out: COLUMN - planName
2019-03-08 06:52:44.605 10351-10351/com.silverfernsolutions.steelsections I/System.out: COLUMN - retailerReference
2019-03-08 06:52:44.605 10351-10351/com.silverfernsolutions.steelsections I/System.out: COLUMN - usage_rate_meter1
2019-03-08 06:52:44.605 10351-10351/com.silverfernsolutions.steelsections I/System.out: COLUMN - usage_rate_meter2
............
Примечание
Выше, согласно вашему коду, требуетсячто папка ресурсов содержит файл с именем SteelSectionProperties (и, очевидно, является допустимой базой данных SQLite).Файл не может быть в подкаталоге (согласно коду).Если файл не находится в папке ресурсов, вы получите сообщение об ошибке, например.
03-08 07:10:34.929 11420-11420/? D/DBPATH: DB Path is /data/data/com.silverfernsolutions.steelsections/databases/SteelSectionProperties
03-08 07:10:34.929 11420-11420/? E/helper copyDB: opening input stream
03-08 07:10:34.929 11420-11420/? E/copying db helper: Error copying DB
03-08 07:10:34.930 11420-11420/? D/AndroidRuntime: Shutting down VM
03-08 07:10:34.930 11420-11420/? E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.silverfernsolutions.steelsections, PID: 11420
java.lang.Error: Error copying database
at com.silverfernsolutions.steelsections.DataBaseHelperReign.createDataBase(DataBaseHelperReign.java:49)
at com.silverfernsolutions.steelsections.MainActivity.onCreate(MainActivity.java:20)
at android.app.Activity.performCreate(Activity.java:5990)
at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1106)
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2278)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2387)
at android.app.ActivityThread.access$800(ActivityThread.java:151)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1303)
at android.os.Handler.dispatchMessage(Handler.java:102)
at android.os.Looper.loop(Looper.java:135)
at android.app.ActivityThread.main(ActivityThread.java:5254)
at java.lang.reflect.Method.invoke(Native Method)
at java.lang.reflect.Method.invoke(Method.java:372)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:903)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:698)