简体   繁体   中英

Why isn't my SQLite database loading from Assets in Android Studio?

I'm trying to load an existing SQLite database into Android Studio. However, the database adapter is returning an empty database instead of giving me a copy of my populated database.

I've got my permissions

    <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />

My DBAdapter

package com.example.testbed;

import android.app.SearchManager;
import android.content.ContentValues;
import android.content.Context;
import android.content.ContextWrapper;
import android.content.Intent;
import android.database.Cursor;
import android.database.SQLException;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteException;
import android.database.sqlite.SQLiteOpenHelper;
import android.database.sqlite.SQLiteQueryBuilder;
import android.util.Log;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.ArrayList;

public class DBAdapter extends SQLiteOpenHelper{
    public static final String TAG = DBAdapter.class.getSimpleName();
    public static int flag;
    private static SQLiteDatabase db;
    private static String DB_NAME = "recipes.db";
    public static String TABLE_NAME = "DrinkRecipes_Loaded";
    public static String DB_PATH = "";
    public static String COL_WORD = "WORD";
    String outFileName = "";
    public static Context myContext;
    private String loadedTable = "DrinkRecipes_Loaded";
    private String specialtyTable = "DrinkRecipes_Specialty";
    private String beautyTable = "DrinkRecipes_Beauty";
    private String kidsTable = "DrinkRecipes_Kids";
    private String shakesTable = "DrinkRecipes_Shakes";



    public DBAdapter(Context context) {
        super(context, DB_NAME, null, 1);
        this.myContext = context;
        ContextWrapper cw = new ContextWrapper(context);
        DB_PATH = "/data/data" + BuildConfig.APPLICATION_ID + "/databases/";
        Log.e(TAG, "Databasehelper: DB_PATH " + DB_PATH);
        outFileName = DB_PATH + DB_NAME;
        File file = new File(DB_PATH);
        Log.e(TAG, "Databasehelper: " + file.exists());
        if (!file.exists()) {
            file.mkdir();
        }
    }

    /**
     * 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
        } 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 {
            checkDB = SQLiteDatabase.openDatabase(outFileName, null, SQLiteDatabase.OPEN_READONLY);
        } catch (SQLiteException e) {
            try {
                copyDataBase();
            } catch (IOException e1) {
                e1.printStackTrace();
            }
        }

        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 {

        Log.i("Database",
                "New database is being copied to device!");
        byte[] buffer = new byte[1024];
        OutputStream myOutput = null;
        int length;
        // Open your local db as the input stream
        InputStream myInput = null;
        try {
            myInput = myContext.getAssets().open(DB_NAME);
            // transfer bytes from the inputfile to the
            // outputfile
            myOutput = new FileOutputStream(DB_PATH + DB_NAME);
            while ((length = myInput.read(buffer)) > 0) {
                myOutput.write(buffer, 0, length);
            }
            myOutput.close();
            myOutput.flush();
            myInput.close();
            Log.i("Database",
                    "New database has been copied to device!");
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    public void openDataBase() throws SQLException {
        //Open the database
        String myPath = DB_PATH + DB_NAME;
        db = SQLiteDatabase.openDatabase(myPath, null, SQLiteDatabase.OPEN_READONLY);
        Log.e(TAG, "openDataBase: Open " + db.isOpen());
    }

    // we have created a new method for reading loaded recipes.
    public ArrayList<recipeModal> readLoadedRecipes() {
        // on below line we are creating a
        // database for reading our database.
        SQLiteDatabase db = this.getReadableDatabase();

        // on below line we are creating a cursor with query to read data from database.
        Cursor cursorRecipes = db.rawQuery("SELECT * FROM " + TABLE_NAME, null);

        // on below line we are creating a new array list.
        ArrayList<recipeModal> recipeModalArrayList = new ArrayList<>();

        // moving our cursor to first position.
        if (cursorRecipes.moveToFirst()) {
            do {
                // on below line we are adding the data from cursor to our array list.
                recipeModalArrayList.add(new recipeModal(cursorRecipes.getString(0),
                        cursorRecipes.getString(1),
                        cursorRecipes.getString(2),
                        cursorRecipes.getString(3),
                        cursorRecipes.getString(4),
                        cursorRecipes.getString(5),
                        cursorRecipes.getString(6),
                        cursorRecipes.getString(7),
                        cursorRecipes.getString(8)));
            } while (cursorRecipes.moveToNext());
            // moving our cursor to next.
        }
        // at last closing our cursor
        // and returning our array list.
        cursorRecipes.close();
        return recipeModalArrayList;
    }

    // we have created a new method for reading loaded recipes.
    public ArrayList<beautyModal> readBeautyRecipes() {
        // on below line we are creating a
        // database for reading our database.
        SQLiteDatabase db = this.getReadableDatabase();

        // on below line we are creating a cursor with query to read data from database.
        Cursor beautyRecipes = db.rawQuery("SELECT * FROM " + beautyTable, null);

        // on below line we are creating a new array list.
        ArrayList<beautyModal> beautyModalArrayList = new ArrayList<>();

        // moving our cursor to first position.
        if (beautyRecipes.moveToFirst()) {
            do {
                // on below line we are adding the data from cursor to our array list.
                beautyModalArrayList.add(new beautyModal(beautyRecipes.getString(0),
                        beautyRecipes.getString(1),
                        beautyRecipes.getString(2),
                        beautyRecipes.getString(3),
                        beautyRecipes.getString(4),
                        beautyRecipes.getString(5)));
            } while (beautyRecipes.moveToNext());
            // moving our cursor to next.
        }
        // at last closing our cursor
        // and returning our array list.
        beautyRecipes.close();
        return beautyModalArrayList;
    }

    // we have created a new method for reading loaded recipes.
    public ArrayList<specialtyModal> readSpecialtyRecipes() {
        // on below line we are creating a
        // database for reading our database.
        SQLiteDatabase db = this.getReadableDatabase();

        // on below line we are creating a cursor with query to read data from database.
        Cursor specialtyRecipes = db.rawQuery("SELECT * FROM " + specialtyTable, null);

        // on below line we are creating a new array list.
        ArrayList<specialtyModal> specialtyModalArrayList = new ArrayList<>();

        // moving our cursor to first position.
        if (specialtyRecipes.moveToFirst()) {
            do {
                // on below line we are adding the data from cursor to our array list.
                specialtyModalArrayList.add(new specialtyModal(specialtyRecipes.getString(0),
                        specialtyRecipes.getString(1),
                        specialtyRecipes.getString(2),
                        specialtyRecipes.getString(3),
                        specialtyRecipes.getString(4),
                        specialtyRecipes.getString(5),
                        specialtyRecipes.getString(6),
                        specialtyRecipes.getString(7)));
            } while (specialtyRecipes.moveToNext());
            // moving our cursor to next.
        }
        // at last closing our cursor
        // and returning our array list.
        specialtyRecipes.close();
        return specialtyModalArrayList;
    }

    // we have created a new method for reading loaded recipes.
    public ArrayList<kidsModal> readKidsRecipes() {
        // on below line we are creating a
        // database for reading our database.
        SQLiteDatabase db = this.getReadableDatabase();

        // on below line we are creating a cursor with query to read data from database.
        Cursor kidsRecipes = db.rawQuery("SELECT * FROM " + kidsTable, null);

        // on below line we are creating a new array list.
        ArrayList<kidsModal> kidsModalArrayList = new ArrayList<>();

        // moving our cursor to first position.
        if (kidsRecipes.moveToFirst()) {
            do {
                // on below line we are adding the data from cursor to our array list.
                kidsModalArrayList.add(new kidsModal(kidsRecipes.getString(0),
                        kidsRecipes.getString(1),
                        kidsRecipes.getString(2),
                        kidsRecipes.getString(3),
                        kidsRecipes.getString(4)));
            } while (kidsRecipes.moveToNext());
            // moving our cursor to next.
        }
        // at last closing our cursor
        // and returning our array list.
        kidsRecipes.close();
        return kidsModalArrayList;
    }

    // we have created a new method for reading loaded recipes.
    public ArrayList<shakesModal> readShakesRecipes() {
        // on below line we are creating a
        // database for reading our database.
        SQLiteDatabase db = this.getReadableDatabase();

        // on below line we are creating a cursor with query to read data from database.
        Cursor shakesRecipes = db.rawQuery("SELECT * FROM " + shakesTable, null);

        // on below line we are creating a new array list.
        ArrayList<shakesModal> shakesModalArrayList = new ArrayList<>();

        // moving our cursor to first position.
        if (shakesRecipes.moveToFirst()) {
            do {
                // on below line we are adding the data from cursor to our array list.
                shakesModalArrayList.add(new shakesModal(shakesRecipes.getString(0),
                        shakesRecipes.getString(1),
                        shakesRecipes.getString(2),
                        shakesRecipes.getString(3),
                        shakesRecipes.getString(4)));
            } while (shakesRecipes.moveToNext());
            // moving our cursor to next.
        }
        // at last closing our cursor
        // and returning our array list.
        shakesRecipes.close();
        return shakesModalArrayList;
    }


    @Override
    public synchronized void close() {
        if (db != null)
            db.close();
        super.close();
    }

    public void onCreate(SQLiteDatabase arg0) {


    }

    @Override
    public void onUpgrade(SQLiteDatabase arg0, int arg1, int arg2) {

    }
}

And when I call it, the only thing that I get is a crashing application and an empty database written to the correct path. I'm very desperate for some solutions to this problem and would appreciate any feedback.

I've tried a few different solutions that seemed promising on Google, but no luck.

EDIT: Stack trace at error


    E/SQLiteLog: (1) no such table: DrinkRecipes_Loaded in "SELECT * FROM DrinkRecipes_Loaded"
    D/AndroidRuntime: Shutting down VM
    E/AndroidRuntime: FATAL EXCEPTION: main
        Process: com.example.testbed, PID: 4732
        java.lang.RuntimeException: Unable to start activity ComponentInfo{com.example.testbed/com.example.testbed.ViewRecipes}: android.database.sqlite.SQLiteException: no such table: DrinkRecipes_Loaded (code 1 SQLITE_ERROR[1]): , while compiling: SELECT * FROM DrinkRecipes_Loaded
            at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:3851)
            at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:4027)
            at android.app.servertransaction.LaunchActivityItem.execute(LaunchActivityItem.java:85)
            at android.app.servertransaction.TransactionExecutor.executeCallbacks(TransactionExecutor.java:135)
            at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:95)
            at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2336)
            at android.os.Handler.dispatchMessage(Handler.java:106)
            at android.os.Looper.loop(Looper.java:247)
            at android.app.ActivityThread.main(ActivityThread.java:8676)
            at java.lang.reflect.Method.invoke(Native Method)
            at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:602)
            at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1130)
         Caused by: android.database.sqlite.SQLiteException: no such table: DrinkRecipes_Loaded (code 1 SQLITE_ERROR[1]): , while compiling: SELECT * FROM DrinkRecipes_Loaded
            at android.database.sqlite.SQLiteConnection.nativePrepareStatement(Native Method)
            at android.database.sqlite.SQLiteConnection.acquirePreparedStatement(SQLiteConnection.java:1463)
            at android.database.sqlite.SQLiteConnection.prepare(SQLiteConnection.java:901)
            at android.database.sqlite.SQLiteSession.prepare(SQLiteSession.java:590)
            at android.database.sqlite.SQLiteProgram.<init>(SQLiteProgram.java:62)
            at android.database.sqlite.SQLiteQuery.<init>(SQLiteQuery.java:37)
            at android.database.sqlite.SQLiteDirectCursorDriver.query(SQLiteDirectCursorDriver.java:46)
            at android.database.sqlite.SQLiteDatabase.rawQueryWithFactory(SQLiteDatabase.java:2063)
            at android.database.sqlite.SQLiteDatabase.rawQuery(SQLiteDatabase.java:2002)
            at com.example.testbed.DBAdapter.readLoadedRecipes(DBAdapter.java:128)
            at com.example.testbed.ViewRecipes.onCreate(ViewRecipes.java:84)
            at android.app.Activity.performCreate(Activity.java:8215)
            at android.app.Activity.performCreate(Activity.java:8199)
            at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1309)
            at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:3824)
            at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:4027) 
            at android.app.servertransaction.LaunchActivityItem.execute(LaunchActivityItem.java:85) 
            at android.app.servertransaction.TransactionExecutor.executeCallbacks(TransactionExecutor.java:135) 
            at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:95) 
            at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2336) 
            at android.os.Handler.dispatchMessage(Handler.java:106) 
            at android.os.Looper.loop(Looper.java:247) 
            at android.app.ActivityThread.main(ActivityThread.java:8676) 
            at java.lang.reflect.Method.invoke(Native Method) 
            at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:602) 
            at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1130) 

There are a few issues with your code.

  1. You are trying to make the database file a directory rather than making the parent the directory.

  2. You are not catering for later android versions that default to using WAL (write-ahead logging) as opposed to journal logging by using getReabableDatabase when creating (copying the asset).

  • getReadableDatabase will do as it says and create the database. The copy then overwrites this (if it works).
  • However , in WAL mode two additional files are created for the WAL logging and populated accordingly. Then:
  • After the asset has been copied SQLite determines that the WAL file is not the WAL file for the copied database and therefore fails to open the potentially corrupt database.
  • The Android API detects this failure but does what it has been asked and creates an empty database and hence the Table not found .

Using getReadableDatabase just to circumvent the databases directory not existing is overkill/inefficient as all the processing to create a new database is undertaken.

Here's a rewrite of your code noting that:-

  • all of the access methods have been commented out (rather than create all the classes)
  • the createDatabase and checkDatabase methods have been commented out. They have been replaced by the getDatabase method.
  • the CopyDatabase method has been changed to return false if an io error occurs (getDatabase then throws a runTimeException)

The getDatabase method

  • checks to see if the database exists and returns if it does. Otherwise, it
  • checks to see if the parentFile (databases directory) exists,
    • if not then it makes the directory (and potentially other ones although they should always exist)
  • calls the CopyDatabase method

So the code (with much of the original code commented out) is:-

public class DBAdapter extends SQLiteOpenHelper {
   public static final String TAG = DBAdapter.class.getSimpleName();
   public static int flag;
   private static SQLiteDatabase db;
   private static String DB_NAME = "recipes.db";
   public static String TABLE_NAME = "DrinkRecipes_Loaded";
   public static String DB_PATH = "";
   public static String COL_WORD = "WORD";
   String outFileName = "";
   public static Context myContext;
   private String loadedTable = "DrinkRecipes_Loaded";
   private String specialtyTable = "DrinkRecipes_Specialty";
   private String beautyTable = "DrinkRecipes_Beauty";
   private String kidsTable = "DrinkRecipes_Kids";
   private String shakesTable = "DrinkRecipes_Shakes";



   public DBAdapter(Context context) {
      super(context, DB_NAME, null, 1);
      this.myContext = context;
      //ContextWrapper cw = new ContextWrapper(context); Not used
      DB_PATH = context.getDatabasePath(DB_NAME).getPath();  // no need to hard code anything bar the DB name
      /*
      //DB_PATH = "/data/data" + BuildConfig.APPLICATION_ID + "/databases/";
      Log.e(TAG, "Databasehelper: DB_PATH " + DB_PATH);
      outFileName = DB_PATH + DB_NAME;
      File file = new File(DB_PATH);
      Log.e(TAG, "Databasehelper: " + file.exists());
      if (!file.exists()) {
         file.getParentFile().mkdirs(); // CHANGED you don't want the database to be a directory
      }
       */
      getDatabase(context);
   }

   /*<<<<< ADDED >>>>>*/
   private void getDatabase(Context context) {
      File dbFile = new File(context.getDatabasePath((DB_NAME)).getPath());
      if (dbFile.exists()) return; // Database found so all done
      // Otherwise ensure that the database directory exists (does not by default until later versions)
      if (!dbFile.getParentFile().exists()) {
         dbFile.getParentFile().mkdirs();
      }
      if (!copyDataBase()) {
         throw new RuntimeException("Unable to copy database from the asset (check the stack-trace).");
      }
   }

   /**
    * Creates a empty database on the system and rewrites it with your own database.
    */
   /* NOTE NEEDED/UNSAFE as getDatabase create a database and for later version of Android it will be in WAL mode
      thus the additional WAL files are created. When the database is then opened SQLite see that the WAL files are not
      for the copied database and thus the open fails. Android's API then creates an new empty database file
    */
   /*
   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(); // Causes issues if in WAL mode and result in database
         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 {
         checkDB = SQLiteDatabase.openDatabase(outFileName, null, SQLiteDatabase.OPEN_READONLY);
      } catch (SQLiteException e) {
         try {
            copyDataBase();
         } catch (IOException e1) {
            e1.printStackTrace();
         }
      }

      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 boolean /* <<<<< CHANGED SIGNATURE */ copyDataBase() {
      Log.i("Database",
              "New database is being copied to device!");
      byte[] buffer = new byte[4096]; //Probably more efficient as default page size will be 4k
      OutputStream myOutput = null;
      int length;
      // Open your local db as the input stream
      InputStream myInput = null;
      try {
         myInput = myContext.getAssets().open(DB_NAME);
         // transfer bytes from the inputfile to the
         // outputfile
         myOutput = new FileOutputStream(DB_PATH);
         while ((length = myInput.read(buffer)) > 0) {
            myOutput.write(buffer, 0, length);
         }
         myOutput.close();
         myOutput.flush();
         myInput.close();
         Log.i("Database",
                 "New database has been copied to device!");
      } catch (IOException e) {
         e.printStackTrace();
         return false;
      }
      return true;
   }

   public void openDataBase() throws SQLException {
      //Open the database
      String myPath = DB_PATH + DB_NAME;
      db = SQLiteDatabase.openDatabase(myPath, null, SQLiteDatabase.OPEN_READONLY);
      Log.e(TAG, "openDataBase: Open " + db.isOpen());
   }
   /*
   // we have created a new method for reading loaded recipes.
   public ArrayList<recipeModal> readLoadedRecipes() {
      // on below line we are creating a
      // database for reading our database.
      SQLiteDatabase db = this.getReadableDatabase();

      // on below line we are creating a cursor with query to read data from database.
      Cursor cursorRecipes = db.rawQuery("SELECT * FROM " + TABLE_NAME, null);

      // on below line we are creating a new array list.
      ArrayList<recipeModal> recipeModalArrayList = new ArrayList<>();

      // moving our cursor to first position.
      if (cursorRecipes.moveToFirst()) {
         do {
            // on below line we are adding the data from cursor to our array list.
            recipeModalArrayList.add(new recipeModal(cursorRecipes.getString(0),
                    cursorRecipes.getString(1),
                    cursorRecipes.getString(2),
                    cursorRecipes.getString(3),
                    cursorRecipes.getString(4),
                    cursorRecipes.getString(5),
                    cursorRecipes.getString(6),
                    cursorRecipes.getString(7),
                    cursorRecipes.getString(8)));
         } while (cursorRecipes.moveToNext());
         // moving our cursor to next.
      }
      // at last closing our cursor
      // and returning our array list.
      cursorRecipes.close();
      return recipeModalArrayList;
   }

   // we have created a new method for reading loaded recipes.
   public ArrayList<beautyModal> readBeautyRecipes() {
      // on below line we are creating a
      // database for reading our database.
      SQLiteDatabase db = this.getReadableDatabase();

      // on below line we are creating a cursor with query to read data from database.
      Cursor beautyRecipes = db.rawQuery("SELECT * FROM " + beautyTable, null);

      // on below line we are creating a new array list.
      ArrayList<beautyModal> beautyModalArrayList = new ArrayList<>();

      // moving our cursor to first position.
      if (beautyRecipes.moveToFirst()) {
         do {
            // on below line we are adding the data from cursor to our array list.
            beautyModalArrayList.add(new beautyModal(beautyRecipes.getString(0),
                    beautyRecipes.getString(1),
                    beautyRecipes.getString(2),
                    beautyRecipes.getString(3),
                    beautyRecipes.getString(4),
                    beautyRecipes.getString(5)));
         } while (beautyRecipes.moveToNext());
         // moving our cursor to next.
      }
      // at last closing our cursor
      // and returning our array list.
      beautyRecipes.close();
      return beautyModalArrayList;
   }

   // we have created a new method for reading loaded recipes.
   public ArrayList<specialtyModal> readSpecialtyRecipes() {
      // on below line we are creating a
      // database for reading our database.
      SQLiteDatabase db = this.getReadableDatabase();

      // on below line we are creating a cursor with query to read data from database.
      Cursor specialtyRecipes = db.rawQuery("SELECT * FROM " + specialtyTable, null);

      // on below line we are creating a new array list.
      ArrayList<specialtyModal> specialtyModalArrayList = new ArrayList<>();

      // moving our cursor to first position.
      if (specialtyRecipes.moveToFirst()) {
         do {
            // on below line we are adding the data from cursor to our array list.
            specialtyModalArrayList.add(new specialtyModal(specialtyRecipes.getString(0),
                    specialtyRecipes.getString(1),
                    specialtyRecipes.getString(2),
                    specialtyRecipes.getString(3),
                    specialtyRecipes.getString(4),
                    specialtyRecipes.getString(5),
                    specialtyRecipes.getString(6),
                    specialtyRecipes.getString(7)));
         } while (specialtyRecipes.moveToNext());
         // moving our cursor to next.
      }
      // at last closing our cursor
      // and returning our array list.
      specialtyRecipes.close();
      return specialtyModalArrayList;
   }

   // we have created a new method for reading loaded recipes.
   public ArrayList<kidsModal> readKidsRecipes() {
      // on below line we are creating a
      // database for reading our database.
      SQLiteDatabase db = this.getReadableDatabase();

      // on below line we are creating a cursor with query to read data from database.
      Cursor kidsRecipes = db.rawQuery("SELECT * FROM " + kidsTable, null);

      // on below line we are creating a new array list.
      ArrayList<kidsModal> kidsModalArrayList = new ArrayList<>();

      // moving our cursor to first position.
      if (kidsRecipes.moveToFirst()) {
         do {
            // on below line we are adding the data from cursor to our array list.
            kidsModalArrayList.add(new kidsModal(kidsRecipes.getString(0),
                    kidsRecipes.getString(1),
                    kidsRecipes.getString(2),
                    kidsRecipes.getString(3),
                    kidsRecipes.getString(4)));
         } while (kidsRecipes.moveToNext());
         // moving our cursor to next.
      }
      // at last closing our cursor
      // and returning our array list.
      kidsRecipes.close();
      return kidsModalArrayList;
   }

   // we have created a new method for reading loaded recipes.
   public ArrayList<shakesModal> readShakesRecipes() {
      // on below line we are creating a
      // database for reading our database.
      SQLiteDatabase db = this.getReadableDatabase();

      // on below line we are creating a cursor with query to read data from database.
      Cursor shakesRecipes = db.rawQuery("SELECT * FROM " + shakesTable, null);

      // on below line we are creating a new array list.
      ArrayList<shakesModal> shakesModalArrayList = new ArrayList<>();

      // moving our cursor to first position.
      if (shakesRecipes.moveToFirst()) {
         do {
            // on below line we are adding the data from cursor to our array list.
            shakesModalArrayList.add(new shakesModal(shakesRecipes.getString(0),
                    shakesRecipes.getString(1),
                    shakesRecipes.getString(2),
                    shakesRecipes.getString(3),
                    shakesRecipes.getString(4)));
         } while (shakesRecipes.moveToNext());
         // moving our cursor to next.
      }
      // at last closing our cursor
      // and returning our array list.
      shakesRecipes.close();
      return shakesModalArrayList;
   }


    */

   @Override
   public synchronized void close() {
      if (db != null)
         db.close();
      super.close();
   }

   public void onCreate(SQLiteDatabase arg0) {
   }

   @Override
   public void onUpgrade(SQLiteDatabase arg0, int arg1, int arg2) {
   }
}

The above has been tested but using a substitute database renamed to recipes.db (NorthWind as it's pretty large) the log for a new install:-

2022-03-27 10:22:11.223 I/Database: New database is being copied to device!
2022-03-27 10:22:11.455 I/Database: New database has been copied to device!

AppInspection confirms that the database has been successfully copied ( albeit not your database ):-

在此处输入图像描述

Likewise Device File Explorer shows:- 在此处输入图像描述

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM