2

I am unable to access the database on android pie after copying the database from assets folder. it works on all other versions. I am getting a no such column found error while doing database operations. Please help me to solve this. The below is the dbhelper class I am using :

public class DBHelper extends SQLiteOpenHelper {

    private static String DB_PATH = "/data/data/com.abc.xyz/databases/";    
    private static String DB_NAME = "db";    
    private SQLiteDatabase myDataBase;    
    private final Context myContext;

    public DBHelper(Context context) {    
        super(context, DB_NAME, null, 1);
        this.myContext = context;
    }

    /**
     * Creates an 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) {
                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 + DB_NAME;
            checkDB = SQLiteDatabase.openDatabase(myPath, null, SQLiteDatabase.OPEN_READONLY);
            checkDB.close();
        } catch(SQLiteException e) {

            //database does't exist yet.
        }

        if(checkDB != null) {
            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 {

        //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;
        //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 = DB_PATH + DB_NAME;
        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) {
    }

    @Override
    public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
    }
}
MikeT
  • 51,415
  • 16
  • 49
  • 68
Akhil Sudha
  • 53
  • 1
  • 9
  • Your copy database function has a few unrelated issues- it doesn't close the output stream if it throws an exception, so it can leak resources. – Gabe Sechan Dec 19 '18 at 19:44
  • Possible duplicate of [Disabling sqlite Write-Ahead logging in Android Pie](https://stackoverflow.com/questions/53659206/disabling-sqlite-write-ahead-logging-in-android-pie) – Martin Zeitler Dec 19 '18 at 23:49

3 Answers3

1

All I had to do was to close the DB connection after this.getReadableDatabase() in createDataBase():

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();
        this.close()
        try {
            copyDataBase();
        } catch (IOException e) {
            throw new Error("Error copying database");
        }
    }   
}
סטנלי גרונן
  • 2,917
  • 23
  • 46
  • 68
Akhil Sudha
  • 53
  • 1
  • 9
0

I believe that the following will address the issues of opening the the database when checking for it's existence, instead it checks to see if the database exists as a file (see comments) :-

public class DBHelper extends SQLiteOpenHelper {

    //private static String DB_PATH = "/data/data/com.abc.xyz/databases/"; //<<<<<<<<<< overwritten
    private static String DB_NAME = "db";
    private SQLiteDatabase myDataBase;
    private final Context myContext;

    private int bytes_copied = 0;
    private static int buffer_size = 1024;
    private int blocks_copied = 0;
    private boolean database_copied = false;
    private boolean database_existed = false;

    public DBHelper(Context context) {
        super(context, DB_NAME, null, 1);

        this.myContext = context;
        // Check for and create (copy DB from assets) when constructing the DBHelper
        if (!checkDataBase()) {
            bytes_copied = 0;
            blocks_copied = 0;
            createDataBase();
        } else {
            database_existed = true;
        }
    }

    /**
     * Creates an empty database on the system and rewrites it with your own database.
     * */
    public void createDataBase() {

        boolean dbExist = checkDataBase(); // Double check
        if(dbExist){
            //do nothing - database already exist
        } else {
            //By calling this method an 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) {
                File db = new File(myContext.getDatabasePath(DB_NAME).getPath());
                if (db.exists()) {
                    db.delete();
                }
                e.printStackTrace();
                throw new RuntimeException("Error copying database (see stack-trace above)");
            }
        }
    }

    /**
     * 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() {
        /**
         * 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(DB_NAME).getPath()); //Get the file name of the database
        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()) {
            dbdir.mkdirs();
        }
        return 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 {

        final String TAG = "COPYDATABASE";

        //Open your local db as the input stream
        Log.d(TAG,"Initiated Copy of the database file " + DB_NAME + " from the assets folder.");
        InputStream myInput = myContext.getAssets().open(DB_NAME); // Open the Asset file
        String dbpath = myContext.getDatabasePath(DB_NAME).getPath();
        Log.d(TAG,"Asset file " + DB_NAME + " found so attmepting to copy to " + dbpath);

        // Path to the just created empty db
        //String outFileName = DB_PATH + DB_NAME;
        //Open the empty db as the output stream
        OutputStream myOutput = new FileOutputStream(dbpath);
        //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.");
            myOutput.write(buffer, 0, length);
            bytes_copied += length;
        }
        Log.d(TAG,
                "Finished copying Database " + DB_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) + "."
        );
        //Close the streams
        myOutput.flush();
        myOutput.close();
        myInput.close();
        Log.d(TAG,"All Streams have been flushed and closed.");
    }

    public void openDataBase() throws SQLException {
        //Open the database
        //String myPath = DB_PATH + DB_NAME;
        String myPath = myContext.getDatabasePath(DB_NAME).getPath();
        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) {
    }

    @Override
    public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
    }


    @Override
    public void onConfigure(SQLiteDatabase db) {
        super.onConfigure(db);
        Log.d("DBCONFIGURE","Database has been configured ");
    }

    @Override
    public void onOpen(SQLiteDatabase db) {
        super.onOpen(db);
        Log.d("DBOPENED","Database has been opened.");
    }
}

Testing

The following activity was used for testing the above (note Instantiating the DBHelper object myDBHlpr initiates the database check/copy) :-

public class MainActivity extends AppCompatActivity {

    DBHelper myDBhlpr;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        Log.d("VERSION","Build Version is " + String.valueOf(Build.VERSION.SDK_INT));
        myDBhlpr = new DBHelper(this);
        Cursor csr = myDBhlpr.getWritableDatabase().query(
                "sqlite_master",
                null,null,null,null,null,null
        );
        while (csr.moveToNext()) {
            Log.d(
                    "DBITEMS",
                    "Found " + csr.getString(csr.getColumnIndex("name")) +
                            " which has a type of " + csr.getString(csr.getColumnIndex("type")) +
                            " the SQL used to create it, was :-\n\t" + csr.getString(csr.getColumnIndex("sql"))
            );
        }
        csr.close();
    }
}

Stage 1 - Run without the database file (db) in the assets folder :-

  • NOTE the line in the log /VERSION: Build Version is 28 i.e. Android Pie

An exception occurs that includes the stack-trace that points to an error with InputStream myInput = myContext.getAssets().open(DB_NAME); (i.e. the asset doesn't exist, so as expected.) :-

2019-01-25 17:51:12.303 30371-30371/so.cdfa D/VERSION: Build Version is 28
2019-01-25 17:51:12.304 30371-30371/so.cdfa D/COPYDATABASE: Initiated Copy of the database file db from the assets folder.
2019-01-25 17:51:12.304 30371-30371/so.cdfa W/System.err: java.io.FileNotFoundException: db
2019-01-25 17:51:12.305 30371-30371/so.cdfa W/System.err:     at android.content.res.AssetManager.nativeOpenAsset(Native Method)
2019-01-25 17:51:12.305 30371-30371/so.cdfa W/System.err:     at android.content.res.AssetManager.open(AssetManager.java:744)
2019-01-25 17:51:12.305 30371-30371/so.cdfa W/System.err:     at android.content.res.AssetManager.open(AssetManager.java:721)
2019-01-25 17:51:12.305 30371-30371/so.cdfa W/System.err:     at so.cdfa.DBHelper.copyDataBase(DBHelper.java:101)
2019-01-25 17:51:12.305 30371-30371/so.cdfa W/System.err:     at so.cdfa.DBHelper.createDataBase(DBHelper.java:55)
2019-01-25 17:51:12.305 30371-30371/so.cdfa W/System.err:     at so.cdfa.DBHelper.<init>(DBHelper.java:36)
2019-01-25 17:51:12.305 30371-30371/so.cdfa W/System.err:     at so.cdfa.MainActivity.onCreate(MainActivity.java:18)
2019-01-25 17:51:12.305 30371-30371/so.cdfa W/System.err:     at android.app.Activity.performCreate(Activity.java:7136)
2019-01-25 17:51:12.305 30371-30371/so.cdfa W/System.err:     at android.app.Activity.performCreate(Activity.java:7127)
2019-01-25 17:51:12.305 30371-30371/so.cdfa W/System.err:     at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1271)
2019-01-25 17:51:12.305 30371-30371/so.cdfa W/System.err:     at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2893)
2019-01-25 17:51:12.306 30371-30371/so.cdfa W/System.err:     at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3048)
2019-01-25 17:51:12.306 30371-30371/so.cdfa W/System.err:     at android.app.servertransaction.LaunchActivityItem.execute(LaunchActivityItem.java:78)
2019-01-25 17:51:12.306 30371-30371/so.cdfa W/System.err:     at android.app.servertransaction.TransactionExecutor.executeCallbacks(TransactionExecutor.java:108)
2019-01-25 17:51:12.306 30371-30371/so.cdfa W/System.err:     at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:68)
2019-01-25 17:51:12.306 30371-30371/so.cdfa W/System.err:     at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1808)
2019-01-25 17:51:12.306 30371-30371/so.cdfa W/System.err:     at android.os.Handler.dispatchMessage(Handler.java:106)
2019-01-25 17:51:12.306 30371-30371/so.cdfa W/System.err:     at android.os.Looper.loop(Looper.java:193)
2019-01-25 17:51:12.307 30371-30371/so.cdfa W/System.err:     at android.app.ActivityThread.main(ActivityThread.java:6669)
2019-01-25 17:51:12.307 30371-30371/so.cdfa W/System.err:     at java.lang.reflect.Method.invoke(Native Method)
2019-01-25 17:51:12.307 30371-30371/so.cdfa W/System.err:     at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:493)
2019-01-25 17:51:12.307 30371-30371/so.cdfa W/System.err:     at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:858)
2019-01-25 17:51:12.307 30371-30371/so.cdfa D/AndroidRuntime: Shutting down VM
2019-01-25 17:51:12.312 30371-30371/so.cdfa E/AndroidRuntime: FATAL EXCEPTION: main
    Process: so.cdfa, PID: 30371
    java.lang.RuntimeException: Unable to start activity ComponentInfo{so.cdfa/so.cdfa.MainActivity}: java.lang.RuntimeException: Error copying database (see stack-trace above)
        at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2913)
        at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3048)
        at android.app.servertransaction.LaunchActivityItem.execute(LaunchActivityItem.java:78)
        at android.app.servertransaction.TransactionExecutor.executeCallbacks(TransactionExecutor.java:108)
        at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:68)
        at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1808)
        at android.os.Handler.dispatchMessage(Handler.java:106)
        at android.os.Looper.loop(Looper.java:193)
        at android.app.ActivityThread.main(ActivityThread.java:6669)
        at java.lang.reflect.Method.invoke(Native Method)
        at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:493)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:858)
     Caused by: java.lang.RuntimeException: Error copying database (see stack-trace above)
        at so.cdfa.DBHelper.createDataBase(DBHelper.java:62)
        at so.cdfa.DBHelper.<init>(DBHelper.java:36)
        at so.cdfa.MainActivity.onCreate(MainActivity.java:18)
        at android.app.Activity.performCreate(Activity.java:7136)
        at android.app.Activity.performCreate(Activity.java:7127)
        at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1271)
        at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2893)
        at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3048) 
        at android.app.servertransaction.LaunchActivityItem.execute(LaunchActivityItem.java:78) 
        at android.app.servertransaction.TransactionExecutor.executeCallbacks(TransactionExecutor.java:108) 
        at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:68) 
        at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1808) 
        at android.os.Handler.dispatchMessage(Handler.java:106) 
        at android.os.Looper.loop(Looper.java:193) 
        at android.app.ActivityThread.main(ActivityThread.java:6669) 
        at java.lang.reflect.Method.invoke(Native Method) 
        at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:493) 
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:858) 
2019-01-25 17:51:12.330 30371-30371/so.cdfa I/Process: Sending signal. PID: 30371 SIG: 9

Step2 - Run after copying a database into the assets folder.

An arbritary sqlite database file as copied into the assets folder and renamed to db. The database is copied and it's items (tables indexes etc) are written to the log e.g. :-

Again note the Build Version and logging

2019-01-25 17:54:51.734 30587-30587/so.cdfa D/VERSION: Build Version is 28
2019-01-25 17:54:51.735 30587-30587/so.cdfa D/COPYDATABASE: Initiated Copy of the database file db from the assets folder.
2019-01-25 17:54:51.735 30587-30587/so.cdfa D/COPYDATABASE: Asset file db found so attmepting to copy to /data/user/0/so.cdfa/databases/db
2019-01-25 17:54:51.736 30587-30587/so.cdfa D/COPYDATABASE: Ateempting copy of block 1 which has 1024 bytes.
............. lines removed from brevity 
2019-01-25 17:54:51.746 30587-30587/so.cdfa D/COPYDATABASE: Ateempting copy of block 40 which has 1024 bytes.
2019-01-25 17:54:51.746 30587-30587/so.cdfa D/COPYDATABASE: Finished copying Database db from the assets folder, to  /data/user/0/so.cdfa/databases/db40960were copied, in 40 blocks of size 1024.
2019-01-25 17:54:51.746 30587-30587/so.cdfa D/COPYDATABASE: All Streams have been flushed and closed.
2019-01-25 17:54:51.770 30587-30587/so.cdfa D/DBCONFIGURE: Database has been configured 
2019-01-25 17:54:51.772 30587-30587/so.cdfa D/DBOPENED: Database has been opened.
2019-01-25 17:54:51.772 30587-30587/so.cdfa D/DBITEMS: Found sqlite_sequence which has a type of table the SQL used to create it, was :-
        CREATE TABLE sqlite_sequence(name,seq)
2019-01-25 17:54:51.773 30587-30587/so.cdfa D/DBITEMS: Found Schedules which has a type of table the SQL used to create it, was :-
        CREATE TABLE `Schedules` (
      `id` INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
      `date` REAL
    )
2019-01-25 17:54:51.773 30587-30587/so.cdfa D/DBITEMS: Found type_affinity_example which has a type of table the SQL used to create it, was :-
        CREATE TABLE type_affinity_example (
        id INTEGER PRIMARY KEY, -- <<<<<<<< MUST BE INTEGER VALUE ELSE INVALID DATATYPE
        col1 rumplestiltskin,
        col2 BLOB,
        col3 INTEGER,
        col4 NUMERIC,
        col5 REAL,
        col6 REALINT, -- because of rule 1 will be INTEGER type affinity NOT REAL!!!!
        col7 TEXT
    )
2019-01-25 17:54:51.773 30587-30587/so.cdfa D/DBITEMS: Found OHLCV_Components which has a type of table the SQL used to create it, was :-
        CREATE TABLE OHLCV_Components (symbol TEXT, tradeDate TEXT, openPrice REAL, highPrice REAL, lowPrice REAL, closePrice REAL, volume INTEGER)
2019-01-25 17:54:51.773 30587-30587/so.cdfa D/DBITEMS: Found league which has a type of table the SQL used to create it, was :-
        CREATE TABLE league (league_id INTEGER PRIMARY KEY, league_name TEXT)
2019-01-25 17:54:51.773 30587-30587/so.cdfa D/DBITEMS: Found team which has a type of table the SQL used to create it, was :-
        CREATE TABLE team (team_id INTEGER PRIMARY KEY, team_name TEXT)
2019-01-25 17:54:51.773 30587-30587/so.cdfa D/DBITEMS: Found player which has a type of table the SQL used to create it, was :-
        CREATE TABLE player (player_id INTEGER PRIMARY KEY, player_name)
2019-01-25 17:54:51.773 30587-30587/so.cdfa D/DBITEMS: Found team_league_history which has a type of table the SQL used to create it, was :-
        CREATE TABLE team_league_history (
        tlh_team_reference INTEGER, 
        tlh_league_reference INTEGER, 
        tlh_from_date TEXT DEFAULT CURRENT_DATE, 
        tlh_to_date TEXT DEFAULT '3000-12-31'
    )
2019-01-25 17:54:51.773 30587-30587/so.cdfa D/DBITEMS: Found player_team_history which has a type of table the SQL used to create it, was :-
        CREATE TABLE player_team_history (
        pth_player_reference INTEGER, 
        pth_team_reference INTEGER, 
        pth_from_date TEXT DEFAULT CURRENT_DATE, 
        pth_to_date TEXT DEFAULT '3000-12-31'
    )
2019-01-25 17:54:51.774 30587-30587/so.cdfa D/DBITEMS: Found android_metadata which has a type of table the SQL used to create it, was :-
        CREATE TABLE android_metadata (locale TEXT)
  • Note in it's simple form as above it is possible to copy a non sqlite database file (any file) which would then result in a corrupt database exception. Checking the first 16 bytes of the file to see if they adhere to SQlite File Header (The header string: "SQLite format 3\000") Database File Format can negate such an issue.

  • Note as the database itself (albeit it empty) has been created you will need to delete it, You can do this by deleting the App's data or uninstalling the App (you may also be able delete it via Device Explorer).

Step3 - Subsequent run (database exists) :-

2019-01-25 17:59:32.868 30666-30666/so.cdfa D/VERSION: Build Version is 28
2019-01-25 17:59:32.873 30666-30666/so.cdfa D/DBCONFIGURE: Database has been configured 
2019-01-25 17:59:32.874 30666-30666/so.cdfa D/DBOPENED: Database has been opened.
2019-01-25 17:59:32.875 30666-30666/so.cdfa D/DBITEMS: Found sqlite_sequence which has a type of table the SQL used to create it, was :-
        CREATE TABLE sqlite_sequence(name,seq)
2019-01-25 17:59:32.875 30666-30666/so.cdfa D/DBITEMS: Found Schedules which has a type of table the SQL used to create it, was :-
        CREATE TABLE `Schedules` (
      `id` INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
      `date` REAL
...........
MikeT
  • 51,415
  • 16
  • 49
  • 68
  • still no luck on android pie – Akhil Sudha Jan 16 '19 at 09:35
  • See the last note – MikeT Jan 16 '19 at 09:40
  • i actually didnt understand that. can you please explain me that ? – Akhil Sudha Jan 18 '19 at 03:56
  • the file successfully copied into system folder but still showing no such table error. :( – Akhil Sudha Jan 18 '19 at 05:05
  • @AkhilSudha you need to read and follow the answer in it's entirety. – MikeT Jan 18 '19 at 05:28
  • @MikeTDone everything as you suggested. But still no luck. file is in the system folder and i can read it using sqlitemanager app. but still getting no such table error. it works perfectly on all other versions except 9.0. dont know what to do. :( – Akhil Sudha Jan 19 '19 at 05:30
  • Add a Log e.e (Log.d("ONCREATE","Ouchh I should not be here!!!!!!!")) in the empty **onCreate** method of the DBHelper. Delete the App's data or uninstall the App and try again. Does the log show that message? If so then for some reason the copied database is being deleted. I'd suggest adding such Logging to all pertinent places. – MikeT Jan 19 '19 at 05:49
  • @AkhilSudha then you aren't following the example but are opening the database, either by not using the **checkDataBase** method as per the example (which in the example, as per the comments, does not open the database, but checks for the existence of the database file, not that that such lines are commented out in the example so you could see the differences) or by calling the **openDataBase** method prematurely, again not as per the example. (the example never uses this method). – MikeT Jan 19 '19 at 08:50
  • I used the exact code you gave and tried to query data from the DB and it works perfectly on all other versions except 9.0. I am still getting no such table error. Can you please try this code on 9.0 as I am can't understand the actual problem. – Akhil Sudha Jan 25 '19 at 05:25
  • @AkhilSudha I believe I did use Android 9 (answer edited as proof as it now writes version to the log). At a guess your issue is that you are using the flawed (hard coded path) openDatabase method which may well open another database (changed above anyway). The newer code will log some pertinent info.I'm not going to answer any more unless you show the full log, which would mean editing this question or asking another. I'd suggest the latter. – MikeT Jan 25 '19 at 07:19
0

I have been struggling with this for days. Just solved it by removing the following line of code from the createDatabase() method:

this.getReadableDataBase();

Seems to work OK now with APIs 27 and 28.

Charlie
  • 51
  • 5