Код ошибки указывает, что вы не закрыли базу данных, а затем повторно приняли ее согласно
(1032) SQLITE_READONLY_DBMOVED
Код ошибки SQLITE_READONLY_DBMOVED - это расширенный код ошибки для SQLITE_READONLY.
Код ошибки SQLITE_READONLY_DBMOVED указывает, что база данных не может быть
изменен, потому что файл базы данных был перемещен с момента его открытия,
и поэтому любая попытка изменить базу данных может привести к базе данных
повреждение процессов, если происходит сбой, потому что журнал отката
не быть правильно названным. Коды результатов и ошибок
То есть SQLite принимает решение, что его можно только читать, а не файл только для чтения.
Вы должны убедиться, что база данных закрыта или, что еще более важно, вы не пытаетесь получить доступ к базе данных через существующее открытие (с учетом того, что SQLiteOpenHelper использует то же открытие) согласно: -
После успешного открытия база данных кэшируется, поэтому вы можете вызывать этот метод каждый раз, когда вам нужно выполнить запись в базу данных. getWritableDatabase
Я бы также рекомендовал вместо того, чтобы удалять исходную базу данных в качестве первого шага, вместо того чтобы копировать или переименовывать ее, а затем удалять после успешного завершения копирования, это позволяет восстановить оригинал в случае возникновения проблем.
Я лично, чтобы обеспечить чистую ситуацию, перезапустить приложение после восстановления.
Ниже приведена основная часть кода восстановления, который у меня есть (что может оказаться полезным, перезапуск приложения в конце): -
/**************************************************************************
* method dorestore - Restore Database in 3 stages
* 1) make a copy of the databasefile
* 2) delete the database
* 3) create the database populating by copying from the designated backup
* If an IOexception occurs and the database has been deleted revert to the
* copy
*/
private void doDBRestore() {
final String methodname = new Object(){}.getClass().getEnclosingMethod().getName();
LogMsg.LogMsg(LogMsg.LOGTYPE_INFORMATIONAL,LOGTAG,"Invoked",this,methodname);
confirmaction = true;
logtag = "DB RESTORE";
//ArrayList<String> errorlist = new ArrayList<>();
resulttitle = "Restore Failed.";
errlist.clear();
dbfile = new File(currentdbfilename);
LogMsg.LogMsg(LogMsg.LOGTYPE_INFORMATIONAL,LOGTAG,"In Progress set and dispalyed",this,methodname);
busy.show();
LogMsg.LogMsg(LogMsg.LOGTYPE_INFORMATIONAL,LOGTAG,"New Thread Started",this,methodname);
new Thread(new Runnable() {
@Override
public void run() {
try {
// Stage 1 Create a copy of the database
String msg = "Stage 1 (make Copy of current DB)Starting";
LogMsg.LogMsg(LogMsg.LOGTYPE_INFORMATIONAL,LOGTAG,msg,THISCLASS,methodname);
FileInputStream fis = new FileInputStream(dbfile);
OutputStream backup = new FileOutputStream(copydbfilename);
while ((copylength = fis.read(buffer)) > 0) {
backup.write(buffer, 0, copylength);
}
backup.flush();
backup.close();
fis.close();
bkpfile = new File(copydbfilename);
msg = "Stage 1 - Complete. Copy made of current DB.";
LogMsg.LogMsg(LogMsg.LOGTYPE_INFORMATIONAL,LOGTAG,msg,THISCLASS,methodname);
copytaken = true;
// Stage 2 - Delete the database file
if (dbfile.delete()) {
msg = "Stage 2 - Completed. Original DB deleted.";
LogMsg.LogMsg(LogMsg.LOGTYPE_INFORMATIONAL,LOGTAG,msg,THISCLASS,methodname);
origdeleted = true;
// Added for Android 9+ to delete shm and wal file if they exist
File dbshm = new File(dbfile.getPath() + "-shm");
File dbwal = new File(dbfile.getPath()+ "-wal");
if (dbshm.exists()) {
dbshm.delete();
}
if (dbwal.exists()) {
dbwal.delete();
}
}
// Stage 3 copy from the backup to the deleted database file i.e. create it
msg = "Stage 3 - (Create new DB from backup) Starting.";
LogMsg.LogMsg(LogMsg.LOGTYPE_INFORMATIONAL,LOGTAG,msg,THISCLASS,methodname);
FileInputStream bkp = new FileInputStream(backupfilename);
OutputStream restore = new FileOutputStream(currentdbfilename);
copylength = 0;
while ((copylength = bkp.read(buffer)) > 0) {
restore.write(buffer, 0, copylength);
}
msg = "Stage 3 - Data Written";
LogMsg.LogMsg(LogMsg.LOGTYPE_INFORMATIONAL,LOGTAG,msg,THISCLASS,methodname);
restore.flush();
restore.close();
msg = "Stage 3 - New DB file flushed and closed";
LogMsg.LogMsg(LogMsg.LOGTYPE_INFORMATIONAL,LOGTAG,msg,THISCLASS,methodname);
restoredone = true;
bkp.close();
msg = "Stage 3 - Complete.";
LogMsg.LogMsg(LogMsg.LOGTYPE_INFORMATIONAL,LOGTAG,msg,THISCLASS,methodname);
} catch (IOException e) {
e.printStackTrace();
if(!copytaken) {
errlist.add("Restore failed copying current database. Error was " + e.getMessage());
} else {
if(!origdeleted) {
errlist.add("Restore failed to delete current database. Error was " + e.getMessage());
}
else {
if(!restoredone) {
errlist.add("Restore failed to recreate the database from the backup. Error was "+ e.getMessage());
errlist.add("Restore will attempt to revert to the original database.");
}
}
}
}
// Ouch restore not done but DB deleted so recover from
// copy by renaming copy
if (copytaken && origdeleted && !restoredone) {
String msg = "Restore failed. Recovering DB after failed restore from backup";
LogMsg.LogMsg(LogMsg.LOGTYPE_ERROR,LOGTAG,msg,THISCLASS,methodname);
//File rcvdbfile = new File(copydbfilename);
//noinspection ResultOfMethodCallIgnored
bkpfile.renameTo(dbfile);
msg = "Restore failed. DB Recovered from backup now in original state.";
LogMsg.LogMsg(LogMsg.LOGTYPE_ERROR,LOGTAG,msg,THISCLASS,methodname);
rolledback = true;
errlist.add("Database reverted to original.");
}
if (copytaken && !origdeleted) {
//noinspection ResultOfMethodCallIgnored
bkpfile.delete();
String msg = "Restore failed. Original DB not deleted so original\" +\n" +
" \" is being used.";
LogMsg.LogMsg(LogMsg.LOGTYPE_ERROR,LOGTAG,msg,THISCLASS,methodname);
}
if(!copytaken) {
String msg = "Restore failed. Attempt to Copy original DB failed.\" +\n" +
" \" Original DB is being used.";
LogMsg.LogMsg(LogMsg.LOGTYPE_ERROR,LOGTAG,msg,THISCLASS,methodname);
}
if(copytaken && origdeleted && restoredone) {
//noinspection ResultOfMethodCallIgnored
bkpfile.delete();
errlist.add("Database successfully restored.");
resulttitle = "Restore was successful. Application wil be restarted.";
DBHelper.reopen(context);
DBHelper.getHelper(context).expand(null,true);
}
StringBuilder fm = new StringBuilder(finalmessage);
for(int i = 0; i < errlist.size(); i++){
if(i > 0) {
fm.append("\n\n");
}
fm.append(errlist.get(i));
}
finalmessage = fm.toString();
runOnUiThread(new Runnable() {
@Override
public void run() {
busy.dismiss();
AlertDialog.Builder resultdialog = new AlertDialog.Builder(context);
resultdialog.setTitle(resulttitle);
resultdialog.setMessage(finalmessage);
resultdialog.setCancelable(true);
resultdialog.setPositiveButton("OK", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
if (copytaken && origdeleted && restoredone) {
Intent i = getBaseContext().getPackageManager()
.getLaunchIntentForPackage( getBaseContext().getPackageName() );
i.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
finish();
startActivity(i);
System.exit(0);
}
}
});
resultdialog.show();
}
});
}
}).start();
}
- LogMsg будет или не будет записывать сообщения в журнал (включен только для разработки и может быть включен / выключен на разных уровнях вплоть до класса)