简体   繁体   English

为什么我的 SQLite 数据库没有从 Android Studio 中的资产加载?

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

I'm trying to load an existing SQLite database into Android Studio.我正在尝试将现有的 SQLite 数据库加载到 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.我尝试了几种在 Google 上看起来很有前途的不同解决方案,但没有成功。

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).您不适合后来的 android 版本,这些版本默认使用 WAL(预写日志记录),而不是在创建(复制资产)时使用getReabableDatabase进行日志记录。

  • getReadableDatabase will do as it says and create the database. getReadableDatabase将按照它所说的那样创建数据库。 The copy then overwrites this (if it works).然后副本会覆盖它(如果有效)。
  • However , in WAL mode two additional files are created for the WAL logging and populated accordingly.但是,在 WAL 模式下,会为 WAL 日志记录创建两个附加文件并相应地进行填充。 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.复制资产后,SQLite 确定 WAL 文件不是复制数据库的 WAL 文件,因此无法打开可能损坏的数据库。
  • The Android API detects this failure but does what it has been asked and creates an empty database and hence the Table not found . Android API 检测到此故障,但按照要求执行并创建一个空数据库,因此找不到表

Using getReadableDatabase just to circumvent the databases directory not existing is overkill/inefficient as all the processing to create a new database is undertaken.使用getReadableDatabase只是为了绕过不存在的数据库目录是矫枉过正/效率低下的,因为创建新数据库的所有处理都已进行。

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. createDatabasecheckDatabase方法已被注释掉。 They have been replaced by the getDatabase method.它们已被getDatabase方法取代。
  • the CopyDatabase method has been changed to return false if an io error occurs (getDatabase then throws a runTimeException)如果发生 io 错误, CopyDatabase方法已更改为返回 false(getDatabase 然后抛出 runTimeException)

The getDatabase method getDatabase方法

  • checks to see if the database exists and returns if it does.检查数据库是否存在,如果存在则返回。 Otherwise, it否则,它
  • checks to see if the parentFile (databases directory) exists,检查 parentFile(数据库目录)是否存在,
    • if not then it makes the directory (and potentially other ones although they should always exist)如果不是,那么它会生成目录(可能还有其他目录,尽管它们应该始终存在)
  • calls the CopyDatabase method调用CopyDatabase方法

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:-以上已经过测试,但使用重命名为 recipes.db 的替代数据库(NorthWind,因为它非常大)新安装的日志:-

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 ):- AppInspection 确认数据库已成功复制(尽管不是您的数据库):-

在此处输入图像描述

Likewise Device File Explorer shows:-同样,设备文件资源管理器显示:- 在此处输入图像描述

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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