【问题标题】:Sqlcipher __ CREATE TABLE android_metadata failedSqlcipher __ CREATE TABLE android_metadata 失败
【发布时间】:2013-12-04 10:40:09
【问题描述】:

我正在尝试在我的 android 应用程序中附加一个现有的 sqlcipher 数据库(加密),但是在将其复制到我的目录后,它无法使用“SQLiteDatabase.openDatabase(...)”打开

我在普通 sqlite 中尝试了代码,它工作正常,但是当我使用 sqlcipher API 时,我收到了这个错误消息

 //CREATE TABLE android_metadata failed
 //Failed to setLocale() when constructing, closing the database
 // net.sqlcipher.database.SQLiteException: file is encrypted or is not a database

我在 SQLiteOpenHelper 类中使用了以下代码:

      if(!dbExist1)
      {

            this.getWritableDatabase(password);
            this.openDatabase();
            try
            {
                  this.close();    
                  copyDataBase();
            }
            catch (IOException e)
            {

                  throw new Error("Error copying database");
            }
      }


        public SQLiteDatabase openDatabase() throws SQLException {
    String DBPath = DATABASE_PATH + DATABASE_NAME;

    myDataBase = SQLiteDatabase.openDatabase(DBPath, password, null,
            SQLiteDatabase.NO_LOCALIZED_COLLATORS);
    return myDataBase;
}

我在 Activity 类中使​​用了以下代码:

  SQLiteDatabase.loadLibs(this);
 DataBaseHelper myDbHelper ;
      myDbHelper = new DataBaseHelper(this);
  SQLiteDatabase db=myDbHelper.openDatabase();

我尝试使用this solution,但还是同样的错误

块引用

【问题讨论】:

    标签: android sqlite sqlcipher


    【解决方案1】:

    非常感谢 Nick Parker,实际上我使用了您示例中的代码 sn-p,我创建了一个代表 SqlCipherAssestHelper 的新类,它将加密的数据库从资产复制到设备中的另一个位置,并使用从新副本读取/写入样本“1x.db”中的数据库here

    这是 Helper Cals:

    package com.example.readdbfromas;
    
    import java.io.File;
    import java.io.FileOutputStream;
    import java.io.IOException;
    import java.io.InputStream;
    import java.io.OutputStream;
    
    import net.sqlcipher.SQLException;
    import net.sqlcipher.database.SQLiteDatabase;
    import net.sqlcipher.database.SQLiteDatabaseHook;
    import net.sqlcipher.database.SQLiteException;
    import net.sqlcipher.database.SQLiteOpenHelper;
    import android.content.Context;
    import android.os.Environment;
    import android.util.Log;
    
    public class DataBaseHelper extends SQLiteOpenHelper {
    
        private static final String DATABASE_NAME = "1x.db";// Encrypted Database
        private static final String SUB_DATABASE_FOLDER = "/DatabaseCipher/";// a sub folder for database location
        public static String DATABASE_PATH;
        public static final int DATABASE_VERSION = 1;
        private SQLiteDatabase myDataBase;
        private final Context context;
        private String password = "";
        private String FULL_DB_Path;
    
        public DataBaseHelper(Context context) {
    
            super(context, DATABASE_NAME, null, DATABASE_VERSION);
    
            DATABASE_PATH = Environment.getExternalStorageDirectory()
                    .getAbsolutePath().toString()
                    + SUB_DATABASE_FOLDER;//get the device root Directory to copy data base on it 
    
            this.context = context;
            SQLiteDatabase.loadLibs(context.getApplicationContext());//load SqlCipher libraries
    
            FULL_DB_Path = DATABASE_PATH + DATABASE_NAME;//full database path
        }
    
        public SQLiteDatabase open(String password) {
            this.password = password;
    
            if (!checkDataBase()) {// if Database Not Exist
                copyDataBase();
            }
    
            myDataBase = getExistDataBaseFile();
    
            return myDataBase;
        }
    
        private SQLiteDatabase getExistDataBaseFile() {// this function to open an Exist database 
    
            SQLiteDatabaseHook hook = new SQLiteDatabaseHook() {
                public void preKey(SQLiteDatabase database) {
                }
    
                public void postKey(SQLiteDatabase database) {
                    database.rawExecSQL("PRAGMA cipher_migrate;");
    
                }
            };
            return SQLiteDatabase.openOrCreateDatabase(FULL_DB_Path, password,
                    null, hook);
    
        }
    
    
        private boolean checkDataBase() {// Check database file is already exist or not
            boolean checkDB = false;
            try {
                File dbfile = new File(FULL_DB_Path);
                checkDB = dbfile.exists();
            } catch (SQLiteException e) {
            }
            return checkDB;
        }
    
    
        public void db_delete() {// delete database
            File file = new File(FULL_DB_Path);
            if (file.exists()) {
                file.delete();
                System.out.println("delete database file.");
            }
        }
    
        private void copyDataBase() {//make a sub folder for database location and copy the database
            try {
                File fofo = new File(DATABASE_PATH);
                fofo.mkdirs();
                extractAssetToDatabaseDirectory(DATABASE_NAME);
            } catch (IOException e) {
                e.printStackTrace();
            }
    
        }
    
        public synchronized void closeDataBase() throws SQLException {
            if (myDataBase != null)
                myDataBase.close();
            super.close();
        }
    
        public void extractAssetToDatabaseDirectory(String fileName)
                throws IOException {// copy the database
    
            int length;
            InputStream sourceDatabase = context.getAssets().open(fileName);
            File destinationPath = new File(FULL_DB_Path);
            OutputStream destination = new FileOutputStream(destinationPath);
    
            byte[] buffer = new byte[4096];
            while ((length = sourceDatabase.read(buffer)) > 0) {
                destination.write(buffer, 0, length);
            }
            sourceDatabase.close();
            destination.flush();
            destination.close();
        }
    
        public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
        }
    
        public void onCreate(SQLiteDatabase db) {
        }
    
        public boolean changePassword(String newPassword) {// DataBase must be
                                                            // opened before
                                                            // changing Password
    
            try {
                if (myDataBase != null && myDataBase.isOpen()) {
    
                    myDataBase.rawExecSQL("BEGIN IMMEDIATE TRANSACTION;");
                    myDataBase.rawExecSQL("PRAGMA rekey = '" + newPassword + "';");
    
                    this.close();
                    myDataBase.close();
    
                    return true;
    
                } else {
    
                    Log.e("boolean changePassword()",
                            "Change Password Error : DataBase is null or not opened  !!");
                    return false;
                }
            } catch (Exception e) {
    
                Log.e("boolean changePassword()",
                        "Change Password Error :ExecSQL Error !!");
                return false;
    
            }
    
        }
    
    }
    

    这个代码在活动中:

         SQLiteDatabase db;
    DataBaseHelper myDbHelper = new DataBaseHelper(MainActivity.this);
           db=myDbHelper.open("test");
    
    
      Cursor cursor=db.rawQuery("select * from t1", null);
    

    【讨论】:

    • 使用 SQLiteDatabaseHook 作为 openOrCreateDatabase(...) 的参数节省了我的时间...我以前使用的是非加密数据库,但在使用加密数据库时遇到了麻烦。
    【解决方案2】:

    您确定您向数据库提供了正确的密码吗?您的数据库是否具有与默认 SQLCipher 分布不同的配置(即密码、页面大小、kdf 迭代长度等)?我有一个在测试套件中附加另一个 SQLCipher 数据库here 的示例,您可以考虑在本地运行测试套件进行比较。您也可以考虑在SQLCipher mailing list 上发布此问题以及您的其他详细信息。

    【讨论】:

    • 非常感谢它正常工作;实际上我使用了测试套件示例中的步骤;我第一次能够从 db 读取\写入,但是当第二次启动应用程序时,它给出了以下错误:(( net.sqlcipher.database.SQLiteException: file is encrypted or is not a database: , while编译:select * from koko)) ___ 所以请你在这个问题上帮助我们。提前致谢
    • 我在没有复制和“附加”的情况下使用了相同的代码,但我有这个错误______ CREATE TABLE android_metadata failed Failed to setLocale() when construction, close the database net.sqlcipher.database.SQLiteException: file已加密或不是数据库
    猜你喜欢
    • 1970-01-01
    • 2015-10-09
    • 2020-02-08
    • 1970-01-01
    • 1970-01-01
    • 2012-08-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多