当前位置: 首页 > 知识库问答 >
问题:

资产文件夹中的SQLite数据库在Android Pie即API 28中不起作用

孟和怡
2023-03-14

我在我的资产文件夹中添加了sqlite文件,并在我的应用程序中使用了sqlite文件中的数据。它在API 27即牛轧糖中运行良好。但该应用程序正在因Android Pie即API 28而崩溃。我在我的数据库助手类中以以下方式使用以下方法。请帮帮我。

    public Database(Context context, String databaseName) {
             super(context, databaseName, null, DATABASE_VERSION);
             this.context = context;
             String packageName = context.getPackageName();
             DB_PATH = "/data/data/" + context.getPackageName() + "/databases/";
             DB_NAME = databaseName;
             openDataBase();
           }

         public void createDataBase() {
             boolean dbExist = checkDataBase();
             if (!dbExist) {
               this.getReadableDatabase();
               try {
                 copyDataBase();
               } catch (IOException e) {
                 Log.e(this.getClass().toString(), "Copying error");
                 throw new Error("Error copying database!");
               }
             }else{
               SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context);
               int dbVersion = prefs.getInt(SP_KEY_DB_VER, 1);
               if (DATABASE_VERSION != dbVersion) {
                 File dbFile = context.getDatabasePath(DB_NAME);
                 if (dbFile.delete()) {
                   database.deleteDatabase(new File(DB_PATH + DB_NAME));
                   openDataBase();
                 }
               }
             }
           }

 private boolean checkDataBase() {
     SQLiteDatabase checkDb = null;
     try {
       String path = DB_PATH + DB_NAME;
       //checkDb = SQLiteDatabase.openDatabase(path, null, SQLiteDatabase.OPEN_READONLY);
       checkDb = SQLiteDatabase.openDatabase(path, null, SQLiteDatabase.OPEN_READONLY);
     } catch (SQLException e) {
       Log.d(TAG, "Error while checking db");
     }
     if (checkDb != null) {
       checkDb.close();
     }
     return checkDb != null;
   }

   private void copyDataBase() throws IOException {
     InputStream externalDbStream = context.getAssets().open(DB_NAME);

     String outFileName = DB_PATH + DB_NAME;

     OutputStream localDbStream = new FileOutputStream(outFileName);

     byte[] buffer = new byte[1024];
     int bytesRead;
     while ((bytesRead = externalDbStream.read(buffer)) > 0) {
       localDbStream.write(buffer, 0, bytesRead);
     }
     SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context);
     SharedPreferences.Editor editor = prefs.edit();
     editor.putInt(SP_KEY_DB_VER, DATABASE_VERSION);
     editor.commit();
     localDbStream.close();
     externalDbStream.close();
   }


    public SQLiteDatabase openDataBase() throws SQLException {

         String path = DB_PATH + DB_NAME;
         if (database == null) {
         createDataBase();
         database = SQLiteDatabase.openDatabase(path, null, SQLiteDatabase.OPEN_READWRITE);
       }
      return database;
     }

这些是我正在使用的openDatabase,CopDatabase和创建数据库方法。

这是坠机日志-

Android数据库sqlite。SQLiteException:没有这样的表:quran_章(代码1 SQLITE_错误):,编译时:在android上从quran_章中选择*。数据库sqlite。SQLiteConnection。android上的nativePrepareStatement(本机方法)。数据库sqlite。SQLiteConnection。android上的acquirePreparedStatement(SQLiteConnection.java:903)。数据库sqlite。SQLiteConnection。在android上准备(SQLiteConnection.java:514)。数据库sqlite。SQLiteSession。在android上准备(SQLiteSession.java:588)。数据库sqlite。Sqlite程序。(SQLiteProgram.java:58)在android上。数据库sqlite。SQLiteQuery。(SQLiteQuery.java:37)在android上。数据库sqlite。SQLiteDirectCursorDriver。android上的查询(SQLiteDirectCursorDriver.java:46)。数据库sqlite。SQLITE数据库。android上的rawQueryWithFactory(SQLiteDatabase.java:1408)。数据库sqlite。SQLITE数据库。rawQuery(SQLiteDatabase.java:1347)

共有1个答案

武骁
2023-03-14

如果数据库不存在,则使用this.getReadableDatabase();这将创建数据库,并且由于您可能没有在onCreate方法中执行任何操作,因此数据库是空的。

然后,在数据库仍然打开的情况下,使用副本覆盖磁盘(通过this.getReadableDatabase() )空的无表数据库可能会完全保留在缓存中,因此会出现问题。

当数据库不存在时,使用一种方法打开数据库,似乎是试图绕过这样一个问题:当它是第一个数据库时,复制失败,并且在该阶段应用程序的存储没有名为databases的目录(打开它会创建目录)。

  • 注意:getReadableDatabase在大多数情况下都会获得一个可写数据库

就我个人而言,我更喜欢,也没有遇到任何问题,通过:-

>

  • 永远不要硬编码数据库路径,而是始终使用上下文的getDatabasePath方法。e、 g.:-mDBPath=context。getDatabasePath(数据库)。getPath()
  • 检查数据库文件是否存在以查看数据库是否存在,而不是打开数据库以查看它是否存在。(参见示例3)

    检查数据库的父级(即databases文件夹),查看它是否存在,以及是否使用文件的mkdirs方法创建数据库目录。e、 g:-

    private boolean ifDatabaseExists(String dbpath){File db=new File(dbpath);if(db.exists())返回true;File dir=new File(db.getParent());if(!dir.exists()){dir.mkdirs();}返回false;}

    将数据库从资源复制到在1处获得的路径指定的位置。

    >

  • 作为4我得到资产文件的一部分,检查前16个字节,看看它是否是一个有效的SQLite数据库(必须是SQLite格式3\u0000)。

    然后继续将数据库中的数据从资产复制到数据库文件。

  •  类似资料:
    • Android Studio又一次改变了项目架构……现在是了

    • 本文向大家介绍Android操作存放在assets文件夹下SQLite数据库的方法,包括了Android操作存放在assets文件夹下SQLite数据库的方法的使用技巧和注意事项,需要的朋友参考一下 本文实例讲述了Android操作存放在assets文件夹下SQLite数据库的方法。分享给大家供大家参考。具体如下: 因为这次的项目需要自带数据,所以就就把数据都放到一个SQLite的数据库文件中了,

    • 如果根文件夹项目中的文件夹, 示例: 我想重组我的文件夹,所以我创建一个新的文件夹叫做src,然后我创建一个子文件夹叫做assets,然后把我的图标放在那里 示例: 这是我在app.js文件中的代码 错误消息:这些文件都不存在 *注意:我已经检查了一遍以确保我没有打错字

    • 我在我的android应用程序中有一个webview,加载的html文件在服务器上,但是我需要从应用程序的资产文件夹地址一些文件。我想问一下如何处理这些文件。 谢谢

    • 我正试图将本地url加载到webview,但我不想使用assets文件夹,因为它是只读的,而且我需要从Web服务更新文件。 Web服务调用运行良好,并将html文件保存到设备上的文件夹中,使用 这将在应用程序的存储空间中创建一个文件夹'app_live',并用HTML填充该文件夹。 现在,当我把它加载到我的Webview中时,应用程序显示“网站不可用”,尽管livefolder.isdir()返回