无法打开使用SQLCipher Android创建的数据库文件

时间:2019-08-16 12:10:37

标签: sqlcipher-android

我正在尝试使用SQLCipher为SQLite数据库启用加密。下面是我的DBHelper和MainActivity代码。有了这个功能,就可以创建数据库,并且应用程序在模拟器中也可以正常工作。但是,当我导出db文件并尝试在SQLite的DB浏览器下运行时,出现一条错误消息**无法打开文件原因:文件不是数据库文件**。有人可以帮我吗?在此先感谢。

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

1 个答案:

答案 0 :(得分:0)

您正在使用哪个版本的SQLCipher?这可以通过使用PRAGMA cipher_version

来确定

您正在使用哪个版本的DBite for SQLite?您将要使用最新版本:https://github.com/sqlitebrowser/sqlitebrowser/releases/tag/v3.11.2,该版本支持同时打开两个SQLCipher 3 + 4数据库。

确定了要使用的SQLCipher版本之后,并确保使用了正确的DB Browser for SQLite版本,请从提示中选择正确的对应SQLCipher版本默认加密设置: SQLCipher_Version_Default_Encryption_Settings