Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/sqlite/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
某些Android设备中未正确复制SQLite数据库_Android_Sqlite - Fatal编程技术网

某些Android设备中未正确复制SQLite数据库

某些Android设备中未正确复制SQLite数据库,android,sqlite,Android,Sqlite,我开发了一个使用SQLite数据库的应用程序。它会在新安装时复制到应用程序的数据文件夹中,并且每次更新应用程序时(因为数据库是只读的,所以我会覆盖上一个版本) 这是我正在使用的代码: public class IfcDatabase extends SQLiteOpenHelper { private static final Object lock = new Object(); private static volatile IfcDatabase mInstance;

我开发了一个使用SQLite数据库的应用程序。它会在新安装时复制到应用程序的数据文件夹中,并且每次更新应用程序时(因为数据库是只读的,所以我会覆盖上一个版本)

这是我正在使用的代码:

public class IfcDatabase extends SQLiteOpenHelper {

    private static final Object lock = new Object();
    private static volatile IfcDatabase mInstance;
    private SQLiteDatabase db = null;
    private Context ctxt;

    public static final int DATABASE_VERSION = 22;
    public static final String DATABASE_NAME = "mydatabase.sqlite";
    public static String DB_PATH = "";

    public static IfcDatabase getInstance(Context ctx) {

        IfcDatabase r = mInstance;
        if (r == null) {
            synchronized (lock)
            {    // While we were waiting for the lock, another
                r = mInstance;        // thread may have instantiated the object.
                if (r == null)
                {
                    DB_PATH = ctx.getDatabasePath(DATABASE_NAME).getParent()+"/";
                    Log.e("logs", "DB_PATH="+DB_PATH);
                    r = new IfcDatabase(ctx.getApplicationContext());
                    mInstance = r;
                }
            }
        }
        return r;
    }


    private IfcDatabase(Context context) {
        //super(context, DATABASE_NAME, null, DATABASE_VERSION);
        super(context, DB_PATH+DATABASE_NAME, null, DATABASE_VERSION);
        ctxt = context;
        try {
            if (!existsDatabase()) {
                SQLiteDatabase tempDb = getWritableDatabase();
                Log.e("logs", "Just before copying database");
                copyDatabase();
                Log.e("logs", "Just after copying database");
            }
        } catch (SQLException eSQL) {
            Log.e("logs", "Error: Can not open database");
        } catch (IOException IOe) {
            Log.e("logs", "Error: Can not copy initial database");
        }
    }

    private boolean existsDatabase() {
        File dbFile = new File(DB_PATH + DATABASE_NAME);
        return dbFile.exists();
    }

    public void copyDatabase() throws IOException {
        AssetManager _asset = ctxt.getAssets();
        InputStream myInput = _asset.open(DATABASE_NAME);
        String outFileName = DB_PATH + DATABASE_NAME;
        Log.e("logs", "OUTFILENAME="+outFileName);
        OutputStream myOutput = new FileOutputStream(outFileName);
        byte[] buffer = new byte[1024];
        int length;
        while ((length = myInput.read(buffer)) > 0) {
            myOutput.write(buffer, 0, length);
        }
        myOutput.flush();
        myOutput.close();
        myInput.close();
    }

    @Override
    public void onCreate(SQLiteDatabase db) {
    }

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

    public void openDatabase() {
        db = getWritableDatabase();
        Log.e("logs", "Checking if table exists (checking if database has been successfully copied)");
        if(!checkIfTableExists("mytable"))
            Log.e("logs", "At this moment this table doesn't exist");
        else
            Log.e("logs", "At this moment this table exists");
        Log.e("logs", "OPEN BBDD "+db);
    }

    private boolean checkIfTableExists(String table_name)
    {
        Cursor _cursor = db.rawQuery("SELECT name FROM sqlite_master WHERE type='table' AND name='"+table_name+"'", null);
        int count = _cursor.getCount();
        _cursor.close();
        if(count > 0)
            return true;
        else
            return false;
    }

    public void closeDatabase() {
        if (db != null)
            db.close();
    }

    ...

}
应用程序启动时以及用户登录时调用:

IfcDatabase.getInstance(this).openDatabase();
IfcDatabase.getInstance(this).closeDatabase();
只有当用户注销时,它才会调用:

IfcDatabase.getInstance(this).openDatabase();
IfcDatabase.getInstance(this).closeDatabase();
在调用openDatabase的新安装中,数据库从资产复制到数据文件夹,用户可以开始对数据库进行查询。以下是日志:

DB_PATH=/data/user/0/com.mypackage.myapp/databases/
Just before copying database
OUTFILENAME=/data/user/0/com.mypackage.myapp/databases/mydatabase.sqlite
Just after copying database
Checking if table exists (checking if database has been successfully copied)
At this moment this table exists
OPEN BBDD SQLiteDatabase: /data/user/0/com.mypackage.myapp/databases/mydatabase.sqlite
DB_PATH=/data/user/0/com.mypackage.myapp/databases/
Just before copying database
OUTFILENAME=/data/user/0/com.mypackage.myapp/databases/mydatabase.sqlite
Just after copying database
Checking if table exists (checking if database has been successfully copied)
At this moment this table doesn't exist
好吧,除了一些特定的Android机型(谷歌Pixel和一些中兴通讯)之外,几乎所有情况下都会发生这种情况(这是正常工作的)。在这些情况下,此代码似乎无法正确复制数据库。在这些情况下,新安装的日志如下:

DB_PATH=/data/user/0/com.mypackage.myapp/databases/
Just before copying database
OUTFILENAME=/data/user/0/com.mypackage.myapp/databases/mydatabase.sqlite
Just after copying database
Checking if table exists (checking if database has been successfully copied)
At this moment this table exists
OPEN BBDD SQLiteDatabase: /data/user/0/com.mypackage.myapp/databases/mydatabase.sqlite
DB_PATH=/data/user/0/com.mypackage.myapp/databases/
Just before copying database
OUTFILENAME=/data/user/0/com.mypackage.myapp/databases/mydatabase.sqlite
Just after copying database
Checking if table exists (checking if database has been successfully copied)
At this moment this table doesn't exist
如您所见,数据库似乎为空或不存在。当用户进行查询时,应用程序崩溃,出现以下异常:

java.lang.IllegalStateException: attempt to re-open an already-closed object: SQLiteDatabase: /data/user/0/com.mypackage.myapp/databases/mydatabase.sqlite
那么,谷歌Pixel和中兴通讯是否可能以不同的方式使用SQLite数据库,而我的代码在这些情况下不起作用

非常感谢你和亲切的问候

---编辑---

我应该补充一点,我一直在想这是否是权限的问题。我请求写入外部存储权限,如果用户拒绝,我请求确认,如果用户一直拒绝,则用户无法使用该应用程序。但我几乎可以肯定这与我的问题无关

---新编辑---

我发现了一个新的问题:这似乎不仅仅是谷歌像素的问题,而是安卓p的谷歌像素。这让我非常担心,因为如果这是安卓p相关的问题,那么将来所有设备都会出现这种情况

目前我没有安装安卓p的设备,也没有阅读安卓p规范的设备,我看不到任何与数据库或内部文件相关的东西。
有人知道安卓P是否更改了与数据库、资产、数据文件夹等相关的任何内容吗?

也许您可以将其添加到您的SQLiteOpenHelper中来解决

@Override
public void onOpen(SQLiteDatabase db) {
    super.onOpen(db);
    db.disableWriteAheadLogging();
}

也许您可以通过将其添加到SQLiteOpenHelper中来解决这个问题

@Override
public void onOpen(SQLiteDatabase db) {
    super.onOpen(db);
    db.disableWriteAheadLogging();
}

SQLiteOpenHelper
假设数据库由事务内部的
onCreate
填充。如果您不使用该机制,请直接使用
SQLiteDatabase
。但是在这种情况下,我的机制怎么可能在其他设备中工作?
SQLiteOpenHelper
假设数据库由事务内部的
onCreate
填充。如果您不使用该机制,请直接使用
SQLiteDatabase
。但是在这种情况下,我的机制怎么可能在其他设备中工作?这就是我必须要做的。某些设备默认启用了写前日志记录,这意味着所有数据不仅包含在database.db中,还包含在.db shm和.db wal文件中。我试着将这些文件和database.db文件一起复制,但一直遇到问题。谢谢,这对我很有帮助,为什么这不是公认的答案?很难找到这个信息!我应该补充一点,你可能必须检查操作系统的版本,因为这只是安卓9和更高版本上的一个问题。这是我必须做的。某些设备默认启用了写前日志记录,这意味着所有数据不仅包含在database.db中,还包含在.db shm和.db wal文件中。我试着将这些文件和database.db文件一起复制,但一直遇到问题。谢谢,这对我很有帮助,为什么这不是公认的答案?很难找到这个信息!我应该补充一点,你可能需要检查操作系统的版本,因为这只是安卓9和更高版本上的一个问题。