SQLiteReadOnlyDatabaseException: attempt to write a readonly database (code 1032)

前端 未结 5 927
暗喜
暗喜 2020-12-31 07:59

So in some rare instances, I\'m seeing the \"attempt to write a readonly database\" message, and I can\'t figure out where the problem lies. I\'ll start with the stacktrace

5条回答
  •  予麋鹿
    予麋鹿 (楼主)
    2020-12-31 08:40

    I've had a similar issue. However, I was purposefully deleting the current database as part of a restore.

    What I think is happening is that SQLite flags the database as read only in order to offer protection against the file unlinked while open:.

    After the restore any updates would fail with the attempt to write a readonly database (code 1032).

    My solution would be to reinstantiate the DBHelper. I've done this by adding a reopen method that I call.

    e.g.

        public static void reopen(Context context) {
            instance = new DBHelper(context);
        }
    

    I then call/invoke this using

                    if(copytaken && origdeleted && restoredone) {
                        DBHelper.reopen(context);
                        DBHelper.getHelper(context).expand(null,true);
                    }
    

    The call to the expand method is my equivalent/getaround for onUpgrade/versions. It adds tables and columns according to a pseudo schema being compared against the actual database.

    The full DBHelper is :-

    /**
     * DBHelper
     */
    @SuppressWarnings("WeakerAccess")
    class DBHelper extends SQLiteOpenHelper {
    
        private static final String LOGTAG = "SW-DBHelper";
        private static final String DBNAME = DBConstants.DATABASE_NAME;
        private static final String dbcreated =
                "001I Database " + DBNAME + " created.";
        private static final String dbunusable =
                "002E Database " + DBNAME +
                " has been set as unusable (according to schema).";
        private   static final String dbexpanded =
                "003I Database " + DBNAME + " expanded.";
        private static final String dbexpandskipped =
                "004I Database " + DBNAME + " expand skipped - nothing to alter.";
        private static final String dbbuildskipped =
                "005I Database" + DBNAME + " build skipped - no tables to add";
        public static final String THISCLASS = DBHelper.class.getSimpleName();
    
        /**
         * Consrtuctor
         *
         * @param context activity context
         * @param name    database name
         * @param factory cursorfactory
         * @param version database version
         */
        DBHelper(Context context, @SuppressWarnings("SameParameterValue") String name, @SuppressWarnings("SameParameterValue") SQLiteDatabase.CursorFactory factory, @SuppressWarnings("SameParameterValue") int version) {
            super(context, name, factory, version);
        }
    
        /**
         * Instantiates a new Db helper.
         *
         * @param context the context
         */
        DBHelper(Context context) {
            super(context, DBConstants.DATABASE_NAME, null, 1);
        }
    
        private static DBHelper instance;
    
        /**
         * Gets helper.
         *
         * @param context the context
         * @return the helper
         */
        static synchronized DBHelper getHelper(Context context) {
            if(instance == null) {
                instance = new DBHelper(context);
            }
            return instance;
        }
    
        @Override
        public void onCreate(SQLiteDatabase db) {
            expand(db, false);
        }
    
    
        @Override
        public void onUpgrade(SQLiteDatabase db, int oldversion, int newversion) {
    
        }
    
        /**
         * expand create database tables
         *
         * @param db             SQLIte Database, if null then instance is used
         * @param buildandexpand to attempt both create and expand
         */
        void expand(SQLiteDatabase db, boolean buildandexpand) {
    
            String mode = "Create Mode.";
            if (buildandexpand) {
                mode = "Expand Mode.";
            }
            String msg = mode;
            String methodname = new Object(){}.getClass().getEnclosingMethod().getName();
            LogMsg.LogMsg(LogMsg.LOGTYPE_INFORMATIONAL,LOGTAG,msg,THISCLASS,methodname);
            // if no database has been passed then get the database
            if(db == null) {
                db = instance.getWritableDatabase();
            }
            // Build Tables to reflect schema (SHOPWISE) only if schema is usable
            if(DBConstants.SHOPWISE.isDBDatabaseUsable()) {
                // Check to see if any tables need to be added
                ArrayList buildsql = DBConstants.SHOPWISE.generateDBBuildSQL(db);
                if (!buildsql.isEmpty()) {
                    DBConstants.SHOPWISE.actionDBBuildSQL(db);
                    msg = dbcreated + buildsql.size() + " tables added.";
                    LogMsg.LogMsg(LogMsg.LOGTYPE_INFORMATIONAL,LOGTAG,msg,THISCLASS,methodname);
                } else {
                    msg = dbbuildskipped;
                    LogMsg.LogMsg(LogMsg.LOGTYPE_INFORMATIONAL,LOGTAG,msg,THISCLASS,methodname);
                }
                if(buildandexpand) {
                    ArrayList altersql = DBConstants.SHOPWISE.generateDBAlterSQL(db);
                    if(!altersql.isEmpty()) {
                        msg = dbexpanded + altersql.size() + " columns added.";
                        LogMsg.LogMsg(LogMsg.LOGTYPE_INFORMATIONAL,LOGTAG,msg,THISCLASS,methodname);
                        DBConstants.SHOPWISE.actionDBAlterSQL(db);
                    }  else {
                        msg = dbexpandskipped;
                        LogMsg.LogMsg(LogMsg.LOGTYPE_INFORMATIONAL,LOGTAG,msg,THISCLASS,methodname);
                    }
                }
            } else {
                msg = dbunusable + "\n" +
                        DBConstants.SHOPWISE.getAllDBDatabaseProblemMsgs();
                LogMsg.LogMsg(LogMsg.LOGTYPE_ERROR,LOGTAG,msg,THISCLASS,methodname);
            }
        }
        public static void reopen(Context context) {
            instance = new DBHelper(context);
        }
    }
    

提交回复
热议问题