Android error with sqlcipher on version android 4.

2019-07-23 06:13发布

问题:

I have a problem when i try to launch my project on Android 4.2.2. Here is the stacktrace :

08-06 11:00:50.041: E/AndroidRuntime(10606): Caused by: net.sqlcipher.database.SQLiteException: not an error
08-06 11:00:50.041: E/AndroidRuntime(10606):    at net.sqlcipher.database.SQLiteDatabase.dbopen(Native Method)
08-06 11:00:50.041: E/AndroidRuntime(10606):    at net.sqlcipher.database.SQLiteDatabase.<init>(SQLiteDatabase.java:1951)
08-06 11:00:50.041: E/AndroidRuntime(10606):    at de.greenrobot.dao.wrapper.SQLiteDatabaseWrapper.<init>(SQLiteDatabaseWrapper.java:61)
08-06 11:00:50.041: E/AndroidRuntime(10606):    at de.greenrobot.dao.wrapper.SQLiteDatabaseWrapper.openDatabase(SQLiteDatabaseWrapper.java:224)
08-06 11:00:50.041: E/AndroidRuntime(10606):    at de.greenrobot.dao.wrapper.SQLiteDatabaseWrapper.openOrCreateDatabase(SQLiteDatabaseWrapper.java:276)
08-06 11:00:50.041: E/AndroidRuntime(10606):    at de.greenrobot.dao.wrapper.SQLiteOpenHelperWrapper.getWritableDatabase(SQLiteOpenHelperWrapper.java:95)
08-06 11:00:50.041: E/AndroidRuntime(10606):    at com.e_i.bad.utils.DAOManager.DAOInit(DAOManager.java:62)

This worked fine on an Android 4.0.4 but when i launch on Android 4.2 thats all time crash with that exception. I give the source of sqlcipher in official web site and i hope that was the last source that i have taken (name was SQLCipher+for+android+2.2.0), i don't saw a latest version of this project.

Thanks in advance for your answer (and i hope that isn't a duplication question caused i search and don't find answer...)

Edit : Source :

helper = new DaoMaster.DevOpenHelper(getContext(), id, password, null);
            db = helper.getWritableDatabase();
            daoMaster = new DaoMaster(db);
            daoSession = daoMaster.newSession();

public static class DevOpenHelper extends OpenHelper {

    public DevOpenHelper(Context context, String name, String password, CursorFactory factory) {
        super(context, name, password, factory);
    }

    @Override
    public void onUpgrade(SQLiteDatabaseWrapper db, int oldVersion, int newVersion) {
        dropAllTables(db, true);
        onCreate(db);
    }
}

public static abstract class OpenHelper extends SQLiteOpenHelperWrapper {

    public OpenHelper(Context context, String name, String password, CursorFactory factory) {
        super(context, name, password, factory, SCHEMA_VERSION);
    }

    @Override
    public void onCreate(SQLiteDatabaseWrapper db) {
        createAllTables(db, false);
    }
}

public synchronized SQLiteDatabaseWrapper getWritableDatabase() {
    if (mDatabase != null && mDatabase.isOpen() && !mDatabase.isReadOnly()) {
        return mDatabase; // The database is already open for business
    }

    if (mIsInitializing) {
        throw new IllegalStateException("getWritableDatabase called recursively");
    }

    // If we have a read-only database open, someone could be using it
    // (though they shouldn't), which would cause a lock to be held on
    // the file, and our attempts to open the database read-write would
    // fail waiting for the file lock. To prevent that, we acquire the
    // lock on the read-only database, which shuts out other users.

    boolean success = false;
    SQLiteDatabaseWrapper db = null;
    if (mDatabase != null)
        mDatabase.lock();
    try {
        mIsInitializing = true;
        if (mName == null) {
            db = SQLiteDatabaseWrapper.create(null, mPassword);
        } else {
            String path = mContext.getDatabasePath(mName).getPath();

            File dbPathFile = new File(path);
            if (!dbPathFile.exists())
                dbPathFile.getParentFile().mkdirs();

            db = SQLiteDatabaseWrapper.openOrCreateDatabase(path, mPassword, mFactory);
        }

        int version = db.getVersion();
        if (version != mNewVersion) {
            db.beginTransaction();
            try {
                if (version == 0) {
                    onCreate(db);
                } else {
                    if (version > mNewVersion) {
                        Log.w(TAG, "Can't downgrade read-only database from version " + version + " to " + mNewVersion + ": " + db.getPath());
                    }
                    onUpgrade(db, version, mNewVersion);
                }
                db.setVersion(mNewVersion);
                db.setTransactionSuccessful();
            } finally {
                db.endTransaction();
            }
        }

        onOpen(db);
        success = true;
        return db;
    } finally {
        mIsInitializing = false;
        if (success) {
            if (mDatabase != null) {
                try {
                    mDatabase.close();
                } catch (Exception e) {
                }
                mDatabase.unlock();
            }
            mDatabase = db;
        } else {
            if (mDatabase != null)
                mDatabase.unlock();
            if (db != null)
                db.close();
        }
    }
}

public SQLiteOpenHelperWrapper(Context context, String name, String password, CursorFactory factory, int version) {
    if (version < 1)
        throw new IllegalArgumentException("Version must be >= 1, was " + version);

    mContext = context;
    mName = name;
    mPassword = password;
    mFactory = factory;
    mNewVersion = version;

    if (mPassword != null && mPassword.length() > 0) {
        // Load SQLcipher libraries if needed
        SQLiteDatabaseWrapper.loadLibs(mContext);
    }
}

Edit 2 :

SQLiteDatabase.loadLibs(getContext());
        String path = "";
        try {
            path = getContext().getDatabasePath(pathDB + ".db").getPath();
        } catch (NullPreferencesException e) {

        }
        File dbPathFile = new File(path);
        if (!dbPathFile.exists()) {
            dbPathFile.getParentFile().mkdirs();
        }
        SQLiteDatabase database = SQLiteDatabase.openOrCreateDatabase(path, "123456", null);
        db = new SQLiteDatabaseWrapper(database);

        daoMaster = new DaoMaster(db);
        daoSession = daoMaster.newSession();

回答1:

Finaly thats work. For this i just take greenDao replace all import library android.database by net.sqlcipher then i export this new greenDao in .jar i take the SQLCipher.jar don't forgot to import commons-codec.jar and guavra-r09.jar plus folder armeabi and folder x86 from SQLCipher and in folder assets the file icudt46l.zip.

In my case i have a project daocore that contains the SQLCipher and is dependancies and my project Android dependant of that daocore project thats worked in Android 4.1 and less but not in 4.2 and more so the problem was the dependencies between project, i don't know why but if you import all in the source project thats work in all Android thats it.