某些Android设备中未正确复制SQLite数据库
我开发了一个使用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;
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和更高版本上的一个问题。