Sqlcipher __ CREATE TABLE android_metadata failed

前端 未结 2 1187
Happy的楠姐
Happy的楠姐 2021-01-22 20:28

I\'m trying to attach a existing sqlcipher database(encrypted) in my android application but after copying it in my directory it cannot be opened using \"SQLiteDatabase.openData

2条回答
  •  感情败类
    2021-01-22 20:59

    Thanks a lot Nick Parker ,actually i used a code snippet from your sample and i created a new class representing SqlCipherAssestHelper that copy the encrypted DataBase from assets to another location in the device and read/write from the new copy using the database in the sample "1x.db" here

    this is the Helper Calss:

    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;
    
            }
    
        }
    
    }
    

    and this code inside activity :

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

提交回复
热议问题