Sqlcipher __ CREATE TABLE android_metadata失败 [英] Sqlcipher __ CREATE TABLE android_metadata failed
问题描述
我想在我的Android应用程序附加现有sqlcipher数据库(加密),但在我的目录拷贝后不能使用打开SQLiteDatabase.openDatabase(......)
我试过code在正常sqlite的,它工作正常,但是当我用sqlcipher API我得到这个错误信息
// CREATE TABLE android_metadata失败
//失败的setLocale()施工时,关闭数据库
// net.sqlcipher.database.SQLiteException:文件被加密或不是一个数据库
我用里面SQLiteOpenHelper类以下code:
如果(!dbExist1)
{
this.getWritableDatabase(密码);
this.openDatabase();
尝试
{
this.close();
copyDataBase();
}
赶上(IOException异常E)
{
抛出新的错误(错误复制数据库);
}
}
公共SQLiteDatabase的openDatabase()抛出的SQLException {
字符串DBPATH = DATABASE_PATH + DATABASE_NAME;
MyDatabase的= SQLiteDatabase.openDatabase(DBPATH,密码为空,
SQLiteDatabase.NO_LOCALIZED_COLLATORS);
返回MyDatabase的;
}
和我用下面的code活性类中:
SQLiteDatabase.loadLibs(本);
DataBaseHelper myDbHelper;
myDbHelper =新DataBaseHelper(本);
SQLiteDatabase DB = myDbHelper.openDatabase();
我试图用该解决方案但还是同样的错误
块引用
非常感谢尼克·帕克,其实我用从样品code片段,我创建了一个新的类重presenting的复制SqlCipherAssestHelper加密从资产数据库,以在设备中的另一个位置,并宣读了新的复制/写入使用该数据库的样本中1x.db的这里
这是助手CALSS:
包com.example.readdbfromas;
进口的java.io.File;
进口java.io.FileOutputStream中;
进口java.io.IOException异常;
进口的java.io.InputStream;
进口java.io.OutputStream中;
进口net.sqlcipher.SQLException;
进口net.sqlcipher.database.SQLiteDatabase;
进口net.sqlcipher.database.SQLiteDatabaseHook;
进口net.sqlcipher.database.SQLiteException;
进口net.sqlcipher.database.SQLiteOpenHelper;
进口android.content.Context;
进口android.os.Environment;
进口android.util.Log;
公共类DataBaseHelper扩展SQLiteOpenHelper {
私有静态最后弦乐DATABASE_NAME =1x.db; //加密数据库
私有静态最后弦乐SUB_DATABASE_FOLDER =/ DatabaseCipher /; //子文件夹数据库位置
公共静态字符串DATABASE_PATH;
公共静态最终诠释DATABASE_VERSION = 1;
私人SQLiteDatabase MyDatabase的;
私人最终上下文的背景下;
私人字符串密码=;
私人字符串FULL_DB_Path;
公共DataBaseHelper(上下文的背景下){
超(背景下,DATABASE_NAME,空,DATABASE_VERSION);
DATABASE_PATH = Environment.getExternalStorageDirectory()
.getAbsolutePath()的toString()
+ SUB_DATABASE_FOLDER; //获取设备根目录下复制数据的基础上就可以了
this.context =背景;
SQLiteDatabase.loadLibs(context.getApplicationContext()); //负荷SqlCipher库
FULL_DB_Path = DATABASE_PATH + DATABASE_NAME; //完整的数据库路径
}
公共SQLiteDatabase开(字符串密码){
this.password =密码;
如果(!checkDataBase()){//如果数据库不存在
copyDataBase();
}
MyDatabase的= getExistDataBaseFile();
返回MyDatabase的;
}
私人SQLiteDatabase getExistDataBaseFile(){//这个函数打开一个存在的数据库
SQLiteDatabaseHook挂钩=新SQLiteDatabaseHook(){
公共无效pre键(SQLiteDatabase数据库){
}
公共无效postKey(SQLiteDatabase数据库){
database.rawExecSQL(杂cipher_migrate;);
}
};
返回SQLiteDatabase.openOrCreateDatabase(FULL_DB_Path,密码,
空,钩);
}
私人布尔checkDataBase(){//检查数据库文件已经存在或不
布尔CHECKDB = FALSE;
尝试 {
文件DBFILE =新的文件(FULL_DB_Path);
CHECKDB = dbfile.exists();
}赶上(SQLiteException E){
}
返回CHECKDB;
}
公共无效db_delete(){//删除数据库
档案文件=新的文件(FULL_DB_Path);
如果(file.exists()){
file.delete();
的System.out.println(删除数据库文件。);
}
}
私人无效copyDataBase(){//做一个子文件夹数据库位置和数据库复制
尝试 {
文件FOFO =新的文件(DATABASE_PATH);
fofo.mkdirs();
extractAssetToDatabaseDirectory(DATABASE_NAME);
}赶上(IOException异常E){
e.printStackTrace();
}
}
市民同步无效closeDataBase()抛出的SQLException {
如果(MyDatabase的!= NULL)
myDataBase.close();
super.close();
}
公共无效extractAssetToDatabaseDirectory(字符串文件名)
抛出IOException异常{//复制数据库
INT长;
InputStream的sourceDatabase = context.getAssets()打开(文件名)。
文件的DestinationPath =新的文件(FULL_DB_Path);
OutputStream的目标=新的FileOutputStream(的DestinationPath);
byte []的缓冲区=新的字节[4096];
而((长度= sourceDatabase.read(缓冲液))大于0){
destination.write(缓冲液,0,长度);
}
sourceDatabase.close();
destination.flush();
destination.close();
}
公共无效onUpgrade(SQLiteDatabase分贝,INT oldVersion,诠释静态网页){
}
公共无效的onCreate(SQLiteDatabase DB){
}
公共布尔的ChangePassword(字符串NEWPASSWORD){//数据库必须
//前开
//改变密码
尝试 {
如果(MyDatabase的空=&安培;!&安培; myDataBase.isOpen()){
myDataBase.rawExecSQL(立即开始交易;);
myDataBase.rawExecSQL(杂密钥更新='+新密码+;);
this.close();
myDataBase.close();
返回true;
} 其他 {
Log.e(布尔的ChangePassword(),
更改密码错误:数据库为空或不开!);
返回false;
}
}赶上(例外五){
Log.e(布尔的ChangePassword(),
更改密码错误:ExecSQL错误!);
返回false;
}
}
}
和内部活动这一code:
SQLiteDatabase分贝;
DataBaseHelper myDbHelper =新DataBaseHelper(MainActivity.this);
DB = myDbHelper.open(测试);
光标光标= db.rawQuery(SELECT * FROM T1,NULL);
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.openDatabase(...)"
I tried the code in normal sqlite and it works correctly but when I used sqlcipher API i got this error message
//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
I used the following code inside SQLiteOpenHelper Class :
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;
}
And I used the following code inside Activity Class :
SQLiteDatabase.loadLibs(this);
DataBaseHelper myDbHelper ;
myDbHelper = new DataBaseHelper(this);
SQLiteDatabase db=myDbHelper.openDatabase();
i tried to use this solution but still same error
Blockquote
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);
这篇关于Sqlcipher __ CREATE TABLE android_metadata失败的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!