无法打开使用 SQLCipher 创建的数据库文件 Android
Unable to open db file created using SQLCipher Android
我正在尝试使用 SQLCipher 为 SQLite 数据库启用加密。下面是我的 DBHelper 和 MainActivity 代码。有了这个我就可以创建数据库,应用程序在模拟器中也能正常工作。但是当我导出数据库文件并尝试在数据库浏览器下为 SQLite 运行 时,我收到一条错误消息,即 ** 无法打开文件原因:文件不是数据库文件 **。谁能帮我解决这个问题?提前致谢..
** DBHelper.java***
package com.example.androidsqlitesipher.Helper;
import android.content.ContentValues;
import android.content.Context;
import net.sqlcipher.Cursor;
import net.sqlcipher.database.SQLiteDatabase;
import net.sqlcipher.database.SQLiteOpenHelper;
import java.util.ArrayList;
import java.util.List;
public class DBHelper extends SQLiteOpenHelper {
private static DBHelper instance;
private static final int DATABASE_VERSION = 1;
private static final String DATABASE_NAME = "ContactsDemo.db";
public static final String TABLE_NAME = "Emails";
public static final String COLUMN_NAME = "Email";
public static final String PASS_PHRASE = "@123#";
private static String SQL_CREATE_TABLE = "CREATE TABLE " + TABLE_NAME + "("
+ COLUMN_NAME + " TEXT PRIMARY KEY)";
private static String SQL_DELETE_TABLE = "DROP TABLE IF EXITS " + TABLE_NAME;
public DBHelper(Context context) {
super(context, DATABASE_NAME, null, DATABASE_VERSION);
}
static public synchronized DBHelper getInstance(Context context){
if(instance == null)
instance = new DBHelper(context);
return instance;
}
@Override
public void onCreate(SQLiteDatabase sqLiteDatabase) {
sqLiteDatabase.execSQL(SQL_CREATE_TABLE);
}
@Override
public void onUpgrade(SQLiteDatabase sqLiteDatabase, int i, int i1) {
sqLiteDatabase.execSQL(SQL_DELETE_TABLE);
onCreate(sqLiteDatabase);
}
//CRUD
public void insertNewEmail(String email){
SQLiteDatabase db = instance.getWritableDatabase(PASS_PHRASE);
ContentValues cv = new ContentValues();
cv.put(COLUMN_NAME,email);
db.insert(TABLE_NAME,null,cv);
db.close();
}
public void updateEmail(String oldEmail, String newEmail){
SQLiteDatabase db = instance.getWritableDatabase(PASS_PHRASE);
ContentValues cv = new ContentValues();
cv.put(COLUMN_NAME,newEmail);
db.update(TABLE_NAME,cv,COLUMN_NAME+"='"+oldEmail+"'",null);
db.close();
}
public void deleteEmail(String email){
SQLiteDatabase db = instance.getWritableDatabase(PASS_PHRASE);
ContentValues cv = new ContentValues();
cv.put(COLUMN_NAME,email);
db.delete(TABLE_NAME,COLUMN_NAME+"='"+email+"'",null);
db.close();
}
public List<String> getAllEmails(){
SQLiteDatabase db = instance.getWritableDatabase(PASS_PHRASE);
Cursor cursor = db.rawQuery(String.format("Select * from %s;",TABLE_NAME),null);
List<String> emails = new ArrayList<>();
if(cursor.moveToFirst()){
while(!cursor.isAfterLast()){
String email = cursor.getString(cursor.getColumnIndex(COLUMN_NAME));
emails.add(email);
cursor.moveToNext();
}
}
cursor.close();
db.close();
return emails;
}
}
** MainActivity.java**
package com.example.androidsqlitesipher;
import androidx.appcompat.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.EditText;
import android.widget.ListView;
import com.example.androidsqlitesipher.Helper.DBHelper;
import net.sqlcipher.database.SQLiteDatabase;
public class MainActivity extends AppCompatActivity {
Button btnAdd, btnUpdate, btnDelete;
EditText edtEmail;
ListView lstEmails;
String saveEmail = ""; //save current email to update/delete
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
SQLiteDatabase.loadLibs(this);
lstEmails = (ListView)findViewById(R.id.lstEmails);
lstEmails.setOnItemClickListener(new AdapterView.OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> adapterView, View view, int i, long l) {
String item = (String)lstEmails.getItemAtPosition(i);
edtEmail.setText(item);
saveEmail = item;
}
});
edtEmail = (EditText) findViewById(R.id.edtEmail);
btnAdd = (Button)findViewById(R.id.btnAdd);
btnUpdate = (Button)findViewById(R.id.btnUpdate);
btnDelete = (Button)findViewById(R.id.btnDelete);
btnAdd.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
DBHelper.getInstance(MainActivity.this).insertNewEmail(edtEmail.getText().toString());
reloadEmails();
}
});
btnUpdate.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
DBHelper.getInstance(MainActivity.this).updateEmail(saveEmail,edtEmail.getText().toString());
reloadEmails();
}
});
btnDelete.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
DBHelper.getInstance(MainActivity.this).deleteEmail(edtEmail.getText().toString());
reloadEmails();
}
});
reloadEmails();
}
private void reloadEmails()
{
ArrayAdapter<String> adapter = new ArrayAdapter<String>(this,
android.R.layout.simple_list_item_1,
android.R.id.text1,
DBHelper.getInstance(this).getAllEmails());
lstEmails.setAdapter(adapter);
}
}
您使用的是什么版本的 SQLCipher?这可以通过使用 PRAGMA cipher_version
来确定
您使用的是什么版本的 SQLite 数据库浏览器?您需要使用最新版本:https://github.com/sqlitebrowser/sqlitebrowser/releases/tag/v3.11.2 支持同时打开 SQLCipher 3 + 4 数据库。
一旦您确定您使用的是哪个版本的 SQLCipher,并确保您使用的是正确版本的 SQLite DB Browser,select 从提示中选择正确的相应 SQLCipher 版本默认加密设置:
我正在尝试使用 SQLCipher 为 SQLite 数据库启用加密。下面是我的 DBHelper 和 MainActivity 代码。有了这个我就可以创建数据库,应用程序在模拟器中也能正常工作。但是当我导出数据库文件并尝试在数据库浏览器下为 SQLite 运行 时,我收到一条错误消息,即 ** 无法打开文件原因:文件不是数据库文件 **。谁能帮我解决这个问题?提前致谢..
** DBHelper.java***
package com.example.androidsqlitesipher.Helper;
import android.content.ContentValues;
import android.content.Context;
import net.sqlcipher.Cursor;
import net.sqlcipher.database.SQLiteDatabase;
import net.sqlcipher.database.SQLiteOpenHelper;
import java.util.ArrayList;
import java.util.List;
public class DBHelper extends SQLiteOpenHelper {
private static DBHelper instance;
private static final int DATABASE_VERSION = 1;
private static final String DATABASE_NAME = "ContactsDemo.db";
public static final String TABLE_NAME = "Emails";
public static final String COLUMN_NAME = "Email";
public static final String PASS_PHRASE = "@123#";
private static String SQL_CREATE_TABLE = "CREATE TABLE " + TABLE_NAME + "("
+ COLUMN_NAME + " TEXT PRIMARY KEY)";
private static String SQL_DELETE_TABLE = "DROP TABLE IF EXITS " + TABLE_NAME;
public DBHelper(Context context) {
super(context, DATABASE_NAME, null, DATABASE_VERSION);
}
static public synchronized DBHelper getInstance(Context context){
if(instance == null)
instance = new DBHelper(context);
return instance;
}
@Override
public void onCreate(SQLiteDatabase sqLiteDatabase) {
sqLiteDatabase.execSQL(SQL_CREATE_TABLE);
}
@Override
public void onUpgrade(SQLiteDatabase sqLiteDatabase, int i, int i1) {
sqLiteDatabase.execSQL(SQL_DELETE_TABLE);
onCreate(sqLiteDatabase);
}
//CRUD
public void insertNewEmail(String email){
SQLiteDatabase db = instance.getWritableDatabase(PASS_PHRASE);
ContentValues cv = new ContentValues();
cv.put(COLUMN_NAME,email);
db.insert(TABLE_NAME,null,cv);
db.close();
}
public void updateEmail(String oldEmail, String newEmail){
SQLiteDatabase db = instance.getWritableDatabase(PASS_PHRASE);
ContentValues cv = new ContentValues();
cv.put(COLUMN_NAME,newEmail);
db.update(TABLE_NAME,cv,COLUMN_NAME+"='"+oldEmail+"'",null);
db.close();
}
public void deleteEmail(String email){
SQLiteDatabase db = instance.getWritableDatabase(PASS_PHRASE);
ContentValues cv = new ContentValues();
cv.put(COLUMN_NAME,email);
db.delete(TABLE_NAME,COLUMN_NAME+"='"+email+"'",null);
db.close();
}
public List<String> getAllEmails(){
SQLiteDatabase db = instance.getWritableDatabase(PASS_PHRASE);
Cursor cursor = db.rawQuery(String.format("Select * from %s;",TABLE_NAME),null);
List<String> emails = new ArrayList<>();
if(cursor.moveToFirst()){
while(!cursor.isAfterLast()){
String email = cursor.getString(cursor.getColumnIndex(COLUMN_NAME));
emails.add(email);
cursor.moveToNext();
}
}
cursor.close();
db.close();
return emails;
}
}
** MainActivity.java**
package com.example.androidsqlitesipher;
import androidx.appcompat.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.EditText;
import android.widget.ListView;
import com.example.androidsqlitesipher.Helper.DBHelper;
import net.sqlcipher.database.SQLiteDatabase;
public class MainActivity extends AppCompatActivity {
Button btnAdd, btnUpdate, btnDelete;
EditText edtEmail;
ListView lstEmails;
String saveEmail = ""; //save current email to update/delete
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
SQLiteDatabase.loadLibs(this);
lstEmails = (ListView)findViewById(R.id.lstEmails);
lstEmails.setOnItemClickListener(new AdapterView.OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> adapterView, View view, int i, long l) {
String item = (String)lstEmails.getItemAtPosition(i);
edtEmail.setText(item);
saveEmail = item;
}
});
edtEmail = (EditText) findViewById(R.id.edtEmail);
btnAdd = (Button)findViewById(R.id.btnAdd);
btnUpdate = (Button)findViewById(R.id.btnUpdate);
btnDelete = (Button)findViewById(R.id.btnDelete);
btnAdd.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
DBHelper.getInstance(MainActivity.this).insertNewEmail(edtEmail.getText().toString());
reloadEmails();
}
});
btnUpdate.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
DBHelper.getInstance(MainActivity.this).updateEmail(saveEmail,edtEmail.getText().toString());
reloadEmails();
}
});
btnDelete.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
DBHelper.getInstance(MainActivity.this).deleteEmail(edtEmail.getText().toString());
reloadEmails();
}
});
reloadEmails();
}
private void reloadEmails()
{
ArrayAdapter<String> adapter = new ArrayAdapter<String>(this,
android.R.layout.simple_list_item_1,
android.R.id.text1,
DBHelper.getInstance(this).getAllEmails());
lstEmails.setAdapter(adapter);
}
}
您使用的是什么版本的 SQLCipher?这可以通过使用 PRAGMA cipher_version
来确定您使用的是什么版本的 SQLite 数据库浏览器?您需要使用最新版本:https://github.com/sqlitebrowser/sqlitebrowser/releases/tag/v3.11.2 支持同时打开 SQLCipher 3 + 4 数据库。
一旦您确定您使用的是哪个版本的 SQLCipher,并确保您使用的是正确版本的 SQLite DB Browser,select 从提示中选择正确的相应 SQLCipher 版本默认加密设置: