1

If a user requests a restore of the data I do a restore from the internal sd-card to the apps data directory with "FileInputStream" and "FileOutputStream".

This is working on Android 8 and lower, but since Android 9 it does not work anymore. I don't get any security or other related exception.
It finished without errors, but the data (Database) is still the old one with the older entries.

This is how I write the database file:

byte[] buffer = new byte[1024];
int length;
while ((length = input.read(buffer)) > 0) {
        output.write(buffer, 0, length);
}

input = FileInputStream of the path '/storage/emulated/0/appname/backupAuto_180913120029.db' output = FileOutputStream of the path '/data/user/0/packagename/databases/data.db'

        output.flush();
        output.close();
        input.close();

UPDATE:
If I transfer after write/restore the data.db file from the device and open it via a SQLLite Tool I see the correct data.
But the app still display the old data. No matter what I do.

I am using a ContentProvider and inside getReadableDatabase() but it seems I get always a cached or an old database.

chrisonline
  • 6,949
  • 11
  • 42
  • 62
  • Are you closing the output stream? – niqueco Sep 13 '18 at 13:35
  • See my updated question. Yes I close the output stream. The code is working on version lower Android 9 since years. :-) – chrisonline Sep 13 '18 at 13:58
  • @pskink: Will do, but as I wrote the data gets written because the data.db file has all the restored entries. Only the app does not get it. – chrisonline Sep 13 '18 at 13:59
  • are you certain the file does not have an exclusive lock, due to having it open? what happens, what you try to delete it first, instead of attempting to overwrite it? – Martin Zeitler Oct 31 '18 at 02:25

2 Answers2

4

I find the answer at:

Android P - 'SQLite: No Such Table Error' after copying database from assets

solved the issue by adding this to my SQLiteOpenHelper:

@Override
public void onOpen(SQLiteDatabase db) {
    super.onOpen(db);
    db.disableWriteAheadLogging();
}
Stephen Rauch
  • 47,830
  • 31
  • 106
  • 135
smxbird
  • 71
  • 3
  • Great thanks. The problem seems is the WAL. Android P enabled this by default and on older version is it disabled. Will test this. – chrisonline Oct 31 '18 at 16:08
0

Solution without disabling the WAL.

Android 9 introduces a special mode of SQLiteDatabase called Compatibility WAL (write-ahead loggin) that allows a database to use "journal_mode=WAL" while preserving the behavior of keeping a maximum of one connection per database.

In Detail here:
https://source.android.com/devices/tech/perf/compatibility-wal

The SQLite WAL mode is explained in detail here:
https://www.sqlite.org/wal.html

As of the official docs the WAL mode adds a second database file called databasename and "-wal". So if your database is named "data.db" it is called "data-wal.db" in the same directory.

The solution is now to save and restore BOTH files (data.db and data-wal.db) on Android 9.

Afterwards it is working as in earlier versions.

chrisonline
  • 6,949
  • 11
  • 42
  • 62