gpt4 book ai didi

android - 重新打开 sqlcipher DB 时创建表 android_metadata 失败

转载 作者:塔克拉玛干 更新时间:2023-11-01 22:09:06 25 4
gpt4 key购买 nike

我有以下 SqlCipher 数据库。当我第一次安装该应用程序时它工作正常,但如果我关闭,从最近的历史记录中删除该应用程序(从堆栈中删除)并重新打开它崩溃并出现以下错误的应用程序。一旦遇到异常,数据库将不会打开,例如我在 Activity 中放置一个 1/0 以强制它崩溃,下面发生了同样的事情。

07-20 15:39:05.669: E/Database(21425): CREATE TABLE android_metadata failed
07-20 15:39:05.669: E/Database(21425): Failed to setLocale() when constructing, closing the database
07-20 15:39:05.669: E/Database(21425): net.sqlcipher.database.SQLiteException: file is encrypted or is not a database

.

我发现以下链接似乎可以解决问题(我不确定它是否是解决方案)但我不确定如何将其实现到我的代码中。谁能帮忙或告诉我为什么会出现此错误?

http://rootslash.net/88542/sqlcipher-cant-open-database-after-apprestart

这是我的数据库代码,我使用 SqlCipher SQLiteOpenHelper 创建数据库。我想我需要修改这段代码,以便它返回一个 DB 对象,如果它已经存在,如果它不存在则创建一个。我只是不确定如何。

提前致谢。

[编辑1]我有一个验证用户凭据的 LoginActivity。如果它们有效,它会加载 MenuActivity,我在其中放置了 1/0 以强制崩溃。崩溃后,如果我重新打开应用程序,它会在查询数据库用户表的行的 LoginActivity 中崩溃。

DBModel 是一个具有 SqliteOpenHelper 和 CRUD 方法的类。

所以它在 DBModel 类中的 checkUserInDB() 处崩溃,而后者又调用了 queryAllFromUser()。

07-25 13:45:43.043  10654-10654/? E/AppObj﹕ Build.SERIAL = SH43PWM07311
07-25 13:45:43.203 10654-10654/? E/AppObj﹕ secretKey = com.android.org.bouncycastle.jcajce.provider.symmetric.util.BCPBEKey@31a79cea
07-25 13:45:43.643 10654-10654/? E/Database﹕ CREATE TABLE android_metadata failed
07-25 13:45:43.643 10654-10654/? E/Database﹕ Failed to setLocale() when constructing, closing the database
net.sqlcipher.database.SQLiteException: file is encrypted or is not a database
at net.sqlcipher.database.SQLiteDatabase.native_setLocale(Native Method)
at net.sqlcipher.database.SQLiteDatabase.setLocale(SQLiteDatabase.java:2096)
at net.sqlcipher.database.SQLiteDatabase.<init>(SQLiteDatabase.java:1962)
at net.sqlcipher.database.SQLiteDatabase.openDatabase(SQLiteDatabase.java:881)
at net.sqlcipher.database.SQLiteDatabase.openOrCreateDatabase(SQLiteDatabase.java:913)
at net.sqlcipher.database.SQLiteOpenHelper.getWritableDatabase(SQLiteOpenHelper.java:132)
at net.sqlcipher.database.SQLiteOpenHelper.getReadableDatabase(SQLiteOpenHelper.java:197)
at net.sqlcipher.database.SQLiteOpenHelper.getReadableDatabase(SQLiteOpenHelper.java:184)
at devreach.co.uk.devreach.DBModel.queryAllFromUser(DBModel.java:175)
at devreach.co.uk.devreach.DBModel.checkIfUserInDB(DBModel.java:262)
at devreach.co.uk.devreach.LoginActivity.onCreate(LoginActivity.java:62)
at android.app.Activity.performCreate(Activity.java:5958)
at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1129)
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2364)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2474)
at android.app.ActivityThread.access$800(ActivityThread.java:144)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1359)
at android.os.Handler.dispatchMessage(Handler.java:102)
at android.os.Looper.loop(Looper.java:155)
at android.app.ActivityThread.main(ActivityThread.java:5696)
at java.lang.reflect.Method.invoke(Native Method)
at java.lang.reflect.Method.invoke(Method.java:372)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1028)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:823)
07-25 13:45:43.643 10654-10654/? E/SQLiteOpenHelper﹕ Couldn't open devreach.db for writing (will try read-only):
net.sqlcipher.database.SQLiteException: file is encrypted or is not a database
at net.sqlcipher.database.SQLiteDatabase.native_setLocale(Native Method)
at net.sqlcipher.database.SQLiteDatabase.setLocale(SQLiteDatabase.java:2096)
at net.sqlcipher.database.SQLiteDatabase.<init>(SQLiteDatabase.java:1962)
at net.sqlcipher.database.SQLiteDatabase.openDatabase(SQLiteDatabase.java:881)
at net.sqlcipher.database.SQLiteDatabase.openOrCreateDatabase(SQLiteDatabase.java:913)
at net.sqlcipher.database.SQLiteOpenHelper.getWritableDatabase(SQLiteOpenHelper.java:132)
at net.sqlcipher.database.SQLiteOpenHelper.getReadableDatabase(SQLiteOpenHelper.java:197)
at net.sqlcipher.database.SQLiteOpenHelper.getReadableDatabase(SQLiteOpenHelper.java:184)
at devreach.co.uk.devreach.DBModel.queryAllFromUser(DBModel.java:175)
at devreach.co.uk.devreach.DBModel.checkIfUserInDB(DBModel.java:262)
at devreach.co.uk.devreach.LoginActivity.onCreate(LoginActivity.java:62)
at android.app.Activity.performCreate(Activity.java:5958)
at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1129)
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2364)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2474)
at android.app.ActivityThread.access$800(ActivityThread.java:144)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1359)
at android.os.Handler.dispatchMessage(Handler.java:102)
at android.os.Looper.loop(Looper.java:155)
at android.app.ActivityThread.main(ActivityThread.java:5696)
at java.lang.reflect.Method.invoke(Native Method)
at java.lang.reflect.Method.invoke(Method.java:372)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1028)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:823)
07-25 13:45:43.983 10654-10654/? E/Database﹕ CREATE TABLE android_metadata failed
07-25 13:45:43.983 10654-10654/? E/Database﹕ Failed to setLocale() when constructing, closing the database
net.sqlcipher.database.SQLiteException: file is encrypted or is not a database
at net.sqlcipher.database.SQLiteDatabase.native_setLocale(Native Method)
at net.sqlcipher.database.SQLiteDatabase.setLocale(SQLiteDatabase.java:2096)
at net.sqlcipher.database.SQLiteDatabase.<init>(SQLiteDatabase.java:1962)
at net.sqlcipher.database.SQLiteDatabase.openDatabase(SQLiteDatabase.java:881)
at net.sqlcipher.database.SQLiteDatabase.openDatabase(SQLiteDatabase.java:940)
at net.sqlcipher.database.SQLiteOpenHelper.getReadableDatabase(SQLiteOpenHelper.java:219)
at net.sqlcipher.database.SQLiteOpenHelper.getReadableDatabase(SQLiteOpenHelper.java:184)
at devreach.co.uk.devreach.DBModel.queryAllFromUser(DBModel.java:175)
at devreach.co.uk.devreach.DBModel.checkIfUserInDB(DBModel.java:262)
at devreach.co.uk.devreach.LoginActivity.onCreate(LoginActivity.java:62)
at android.app.Activity.performCreate(Activity.java:5958)
at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1129)
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2364)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2474)
at android.app.ActivityThread.access$800(ActivityThread.java:144)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1359)
at android.os.Handler.dispatchMessage(Handler.java:102)
at android.os.Looper.loop(Looper.java:155)
at android.app.ActivityThread.main(ActivityThread.java:5696)
at java.lang.reflect.Method.invoke(Native Method)
at java.lang.reflect.Method.invoke(Method.java:372)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1028)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:823)
07-25 13:45:43.983 10654-10654/? E/AndroidRuntime﹕ FATAL EXCEPTION: main
Process: devreach.co.uk.devreach, PID: 10654
java.lang.RuntimeException: Unable to start activity ComponentInfo{devreach.co.uk.devreach/devreach.co.uk.devreach.LoginActivity}: net.sqlcipher.database.SQLiteException: file is encrypted or is not a database
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2411)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2474)
at android.app.ActivityThread.access$800(ActivityThread.java:144)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1359)
at android.os.Handler.dispatchMessage(Handler.java:102)
at android.os.Looper.loop(Looper.java:155)
at android.app.ActivityThread.main(ActivityThread.java:5696)
at java.lang.reflect.Method.invoke(Native Method)
at java.lang.reflect.Method.invoke(Method.java:372)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1028)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:823)
Caused by: net.sqlcipher.database.SQLiteException: file is encrypted or is not a database
at net.sqlcipher.database.SQLiteDatabase.native_setLocale(Native Method)
at net.sqlcipher.database.SQLiteDatabase.setLocale(SQLiteDatabase.java:2096)
at net.sqlcipher.database.SQLiteDatabase.<init>(SQLiteDatabase.java:1962)
at net.sqlcipher.database.SQLiteDatabase.openDatabase(SQLiteDatabase.java:881)
at net.sqlcipher.database.SQLiteDatabase.openDatabase(SQLiteDatabase.java:940)
at net.sqlcipher.database.SQLiteOpenHelper.getReadableDatabase(SQLiteOpenHelper.java:219)
at net.sqlcipher.database.SQLiteOpenHelper.getReadableDatabase(SQLiteOpenHelper.java:184)
at devreach.co.uk.devreach.DBModel.queryAllFromUser(DBModel.java:175)
at devreach.co.uk.devreach.DBModel.checkIfUserInDB(DBModel.java:262)
at devreach.co.uk.devreach.LoginActivity.onCreate(LoginActivity.java:62)
at android.app.Activity.performCreate(Activity.java:5958)
at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1129)
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2364)
            at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2474)
            at android.app.ActivityThread.access$800(ActivityThread.java:144)
            at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1359)
            at android.os.Handler.dispatchMessage(Handler.java:102)
            at android.os.Looper.loop(Looper.java:155)
            at android.app.ActivityThread.main(ActivityThread.java:5696)
            at java.lang.reflect.Method.invoke(Native Method)
            at java.lang.reflect.Method.invoke(Method.java:372)
            at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1028)
            at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:823)

登录 Activity :

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_login);

appObj = (AppObj)getApplication();
editTextFirstName = (EditText)findViewById(R.id.edittextfirstname);
editTextPassword = (EditText)findViewById(R.id.editTextpassword);

String firstName = appObj.dbModel.checkIfUserInDB();

if(! firstName.equalsIgnoreCase("NO_USER")){

editTextFirstName.setText(firstName);
}

数据库模型:

    import net.sqlcipher.Cursor;
import net.sqlcipher.database.SQLiteDatabase;
import net.sqlcipher.database.SQLiteOpenHelper;
import android.content.ContentValues;
import android.content.Context;
import android.provider.BaseColumns;
import android.util.Log;
import android.widget.Toast;



public class DBModel {



private static final String TAG = DBModel.class.getSimpleName();


// table user column names
public static final String C_USER_ID_INDEX = BaseColumns._ID;
public static final String C_USER_ID = "userid";
public static final String C_USER_COMP_ID = "usercompid";
public static final String C_USER_FIRSTNAME = "userfirstname";
public static final String C_USER_LASTNAME = "userlastname";
public static final String C_USER_PASSWORD = "userpassword";
public static final String C_USER_DATE_TIME = "userdatetime";




// table company column names
public static final String C_COMPANY_ID_INDEX = BaseColumns._ID;
public static final String C_COMPANY_ID = "companyid";
public static final String C_COMPANY_NAME = "companyname";
public static final String C_COMPANY_URL = "companyurl";
public static final String C_COMPANY_GUID = "companyguid";







Context context;
DBHelper dbhelper;
AppObj appObj;



public DBModel(Context context) {

this.context = context;
dbhelper = new DBHelper();
appObj = (AppObj) context.getApplicationContext();


}




/**
* inner class to create/open/upgrade database
*
* @author matt
*
*/
private class DBHelper extends SQLiteOpenHelper {

// database name and version number
public static final String DB_NAME = "devreach.db";
public static final int DB_VERSION = 1;

// table names

public static final String TABLEUSER = "user";
public static final String TABLECOMPANY = "company";



public DBHelper() {
super(context, DB_NAME, null, DB_VERSION);
}

@Override
public void onCreate(SQLiteDatabase db) {

Log.e(TAG, "SQLiteOpenHelper oncreate ");





String sqlToCreateUserTable = String
.format("create table %s ( %s INTEGER primary key, %s TEXT, %s TEXT, %s TEXT, %s TEXT, %s TEXT, %s TEXT)",
TABLEUSER, C_USER_ID_INDEX, C_USER_ID, C_USER_COMP_ID,
C_USER_FIRSTNAME, C_USER_LASTNAME, C_USER_PASSWORD,
C_USER_DATE_TIME);

db.execSQL(sqlToCreateUserTable);
Log.e(TAG, "oncreate " + sqlToCreateUserTable);




String sqlToCreateCompanyTable = String
.format("create table %s ( %s INTEGER primary key, %s TEXT, %s TEXT, %s TEXT, %s TEXT)",
TABLECOMPANY, C_COMPANY_ID_INDEX, C_COMPANY_ID, C_COMPANY_NAME,
C_COMPANY_URL, C_COMPANY_GUID);

db.execSQL(sqlToCreateCompanyTable);
Log.e(TAG, "oncreate " + sqlToCreateCompanyTable);






}

@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {




}//end of onUpgrade

}//end of DBHelper

public void close() {

dbhelper.close();
}









public void deleteTableUser() {
// open database
SQLiteDatabase db = dbhelper.getWritableDatabase(AppObj.getSecretKey().toString());

// delete contents of table
db.delete(DBHelper.TABLEUSER, null, null);


}

public void insertIntoUser(ContentValues cv) {

SQLiteDatabase db = dbhelper.getWritableDatabase(AppObj.getSecretKey().toString());

db.insertWithOnConflict(DBHelper.TABLEUSER, null, cv, SQLiteDatabase.CONFLICT_REPLACE);

}



public Cursor queryAllFromUser() {

// open database
SQLiteDatabase db = dbhelper.getReadableDatabase(AppObj.getSecretKey().toString());

return db.query(DBHelper.TABLEUSER, null, null, null, null, null, null);

}



public void deleteTableCompany() {
// open database
SQLiteDatabase db = dbhelper.getWritableDatabase(AppObj.getSecretKey().toString());

// delete contents of table
db.delete(DBHelper.TABLECOMPANY, null, null);


}


public void insertIntoCompany(ContentValues cv) {

SQLiteDatabase db = dbhelper.getWritableDatabase(AppObj.getSecretKey().toString());

db.insertWithOnConflict(DBHelper.TABLECOMPANY, null, cv, SQLiteDatabase.CONFLICT_REPLACE);

}



public Cursor queryAllFromCompany() {

// open database
SQLiteDatabase db = dbhelper.getReadableDatabase(AppObj.getSecretKey().toString());

return db.query(DBHelper.TABLECOMPANY, null, null, null, null, null, null);

}


public String getCompanyGuid(){

String guid = null;
Cursor c = null;
SQLiteDatabase db = dbhelper.getReadableDatabase(AppObj.getSecretKey().toString());

c = db.query(DBHelper.TABLECOMPANY, null, null, null, null, null, null);

if(c != null){
if(c.moveToLast()){

guid = c.getString(c.getColumnIndex(DBModel.C_COMPANY_GUID));
}
}

try{
c.close();
}catch(Exception e){}

return guid;
}

public String getCompanyID(){

String id = null;
Cursor c = null;
SQLiteDatabase db = dbhelper.getReadableDatabase(AppObj.getSecretKey().toString());

c = db.query(DBHelper.TABLECOMPANY, null, null, null, null, null, null);

if(c != null){
if(c.moveToLast()){

id = c.getString(c.getColumnIndex(DBModel.C_COMPANY_ID));
}
}

try{
c.close();
}catch(Exception e){}

return id;
}


public String checkIfUserInDB() {

String firstName = null;
Cursor c = queryAllFromUser();

if(c != null && c.getCount() > 0){
if(c.moveToLast()){

Log.e(TAG,"c != null and > 0");
firstName = c.getString(c.getColumnIndex(DBModel.C_USER_FIRSTNAME));

}

}else{
Log.e(TAG,"c == null");
firstName = "NO_USER";

}

try{
c.close();
}catch(Exception e){}

Log.e(TAG,"firstName = " + firstName);
return firstName;
}








}//end of DBModel

[编辑2]

   @Override
public void onCreate() {
super.onCreate();

secretKey = null;
Log.e(TAG, "Build.SERIAL = " + Build.SERIAL);

SecureRandom secureRandom = new SecureRandom();
byte[] salt = secureRandom.generateSeed(256);


try {
secretKey = generateKey(Build.SERIAL.toCharArray(), salt);
Log.e(TAG, "key-Base64 before in appObj = "+new String(Base64.encode(RROnCallApplication.getSecretKey().getEncoded(),0)));
} catch (NoSuchAlgorithmException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (InvalidKeySpecException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}

Log.e(TAG, "secretKey = " + secretKey);

SQLiteDatabase.loadLibs(this);

dbModel = new DBModel(this);
webService = new WebService(this);
alertCount = 0;

// Cursor checkCarerTable = dbModel.queryAllFromCarer();
//
// if(checkCarerTable.getCount() == 0){
//
// //runGetCarersService();
// //runGetClientsService();
//
//
// }else{
//
// Log.e(TAG, "carer and client table is populated with some data");
// }



}

private static SecretKey generateKey(char[] passphraseOrPin, byte[] salt) throws NoSuchAlgorithmException, InvalidKeySpecException {
// Number of PBKDF2 hardening rounds to use. Larger values increase
// computation time. You should select a value that causes computation
// to take >100ms.
final int iterations = 1000;

// Generate a 256-bit key
final int outputKeyLength = 256;

SecretKeyFactory secretKeyFactory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA1");
KeySpec keySpec = new PBEKeySpec(passphraseOrPin, salt, iterations, outputKeyLength);
SecretKey secretKey = secretKeyFactory.generateSecret(keySpec);

return secretKey;
}

最佳答案

盐必须与要散列以创建 key 的变量相同。

变量可能会保持不变,相同的用户/用户密码,但是您的代码正在重新生成随机盐。

如果您使用 key 加密数据库,则 key 必须相同,因此盐也必须相同。

希望对您有所帮助!

关于android - 重新打开 sqlcipher DB 时创建表 android_metadata 失败,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31519553/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com