我的应用程序中有一个现有的sqlite数据库。它运行成功。现在我需要使用sqlcipher加密数据库。我的问题是在将sqlite转换为加密时我遇到了以下异常。
net.sqlcipher.database.SQLiteException: table android_metadata already exists
at net.sqlcipher.database.SQLiteDatabase.native_rawExecSQL(Native Method)
at net.sqlcipher.database.SQLiteDatabase.rawExecSQL(SQLiteDatabase.java:1851)
at com.x.y.convert_sqlite_to_sqlcipher(Practitioner_menu.java:2626)
at com.x.y$AdminProcess.doInBackground(Practitioner_menu.java:1659)
at com.x.y$AdminProcess.doInBackground(Practitioner_menu.java:1)
at android.os.AsyncTask$2.call(AsyncTask.java:287)
at java.util.concurrent.FutureTask.run(FutureTask.java:234)
at android.os.AsyncTask$SerialExecutor$1.run(AsyncTask.java:230)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1080)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:573)
at java.lang.Thread.run(Thread.java:856)
我的转换代码:
File old_sqliteFile = getDatabasePath("old_db.sqlite");
File databaseFile = getDatabasePath("new_db.db");
databaseFile.mkdirs();
databaseFile.delete();
database = SQLiteDatabase.openOrCreateDatabase(databaseFile,
"password", null);
database.rawExecSQL(String.format(
"ATTACH DATABASE '%s' AS encrypted KEY '%s'",
databaseFile.getAbsolutePath(), "password");
database.rawExecSQL("select sqlcipher_export('encrypted')");
database.rawExecSQL("DETACH DATABASE encrypted");
database.close();
请有人帮我弄清楚我做错了什么?
答案 0 :(得分:6)
您正在使用databaseFile
两次。我们应该openOrCreateDatabase()
要求old_sqliteFile
,而不是databaseFile
。
这是一种用加密替换替换未加密数据库文件的方法:
public static void encrypt(Context ctxt, String dbName,
String passphrase) throws IOException {
File originalFile=ctxt.getDatabasePath(dbName);
if (originalFile.exists()) {
File newFile=
File.createTempFile("sqlcipherutils", "tmp",
ctxt.getCacheDir());
SQLiteDatabase db=
SQLiteDatabase.openDatabase(originalFile.getAbsolutePath(),
"", null,
SQLiteDatabase.OPEN_READWRITE);
db.rawExecSQL(String.format("ATTACH DATABASE '%s' AS encrypted KEY '%s';",
newFile.getAbsolutePath(), passphrase));
db.rawExecSQL("SELECT sqlcipher_export('encrypted')");
db.rawExecSQL("DETACH DATABASE encrypted;");
int version=db.getVersion();
db.close();
db=
SQLiteDatabase.openDatabase(newFile.getAbsolutePath(),
passphrase, null,
SQLiteDatabase.OPEN_READWRITE);
db.setVersion(version);
db.close();
originalFile.delete();
newFile.renameTo(originalFile);
}
}
答案 1 :(得分:0)
谢谢,它很棒。 我添加了此代码来加密,解密和更改密码。
@Override
public synchronized SQLiteDatabase getWritableDatabase(String password) {
SQLiteDatabase sqLiteDatabase;
try{
sqLiteDatabase = super.getWritableDatabase(password);
}catch(Exception e){
try {
encrypt(context,DATABASE_NAME,PWOLD,PWNEW);
} catch (IOException e1) {
e1.printStackTrace();
}
sqLiteDatabase = super.getWritableDatabase(password);
}
return sqLiteDatabase;
}
@Override
public synchronized SQLiteDatabase getReadableDatabase(String password) {
SQLiteDatabase sqLiteDatabase;
try{
sqLiteDatabase = super.getReadableDatabase(password);
}catch(Exception e){
try {
encrypt(context, DATABASE_NAME, PWOLD, PWNEW);
} catch (IOException e1) {
e1.printStackTrace();
}
sqLiteDatabase = super.getReadableDatabase(password);
}
return sqLiteDatabase;
}
public static void encrypt(Context context, String dbName,
String oldPass, String newPass) throws IOException {
if(!newPass.isEmpty()) Log.d(TAG,"Encrypt DB...");
else Log.d(TAG,"Decrypt DB...");
File originalFile=context.getDatabasePath(dbName);
if (originalFile.exists()) {
File newFile = File.createTempFile("sqlcipherutils", "tmp",
context.getCacheDir());
SQLiteDatabase db = SQLiteDatabase.openDatabase(originalFile.getAbsolutePath(),
oldPass, null,
SQLiteDatabase.OPEN_READWRITE);
db.rawExecSQL(String.format("ATTACH DATABASE '%s' AS encrypted KEY '%s';",
newFile.getAbsolutePath(), newPass));
db.rawExecSQL("SELECT sqlcipher_export('encrypted')");
db.rawExecSQL("DETACH DATABASE encrypted;");
int version=db.getVersion();
db.close();
db = SQLiteDatabase.openDatabase(newFile.getAbsolutePath(),
newPass, null,
SQLiteDatabase.OPEN_READWRITE);
db.setVersion(version);
db.close();
originalFile.delete();
newFile.renameTo(originalFile);
}
}