Use SQLChiper to encrypt Android SQLite database

Using SQLChiper to encrypt Android SQLite database
Preface: The last article talked about several pits of Android studio+SQLCipher encrypting SQLite database. If you skip these pits, then the premise of SQLCipher is processed. This article continues on how to use SQLCiper encryption database.

1. Similar to the use of SQLite, first inherit SQLiteOpenHelper, implement the two abstract methods of OnCreate and onUpgrade, and must super at least one of the constructors. code show as below:

package com.tuoqun.Tool;

import android.content.Context;
import android.util.Log;

import net.sqlcipher.database.SQLiteDatabase;
import net.sqlcipher.database.SQLiteOpenHelper;

public class DBCipherHelper extends SQLiteOpenHelper {

    private static final String TAG = "DatabaseHelper";

    public static String DB_NAME;//数据库名字
    public static String DB_PWD;//数据库密码
    public static int DB_VERSION;   // 数据库版本
    //private String createTableSQL="";//创建数据库表的SQL语句(eg: "CREATE TABLE TABLE_NAME(FIELD_ID integer primary key autoincrement , FIELD_NAME text not null);")

    public DBCipherHelper(Context context, String name, SQLiteDatabase.CursorFactory factory, int version) {
        super(context, name, factory, version);
        //不可忽略的,进行so库加载;这个千万别忘记调用!!!!
        SQLiteDatabase.loadLibs(context);
        Log.e(TAG, "CreateDB:---------------"+name+"---------------Success");
    }

    public DBCipherHelper(Context context) {
        this(context, DB_NAME, null, DB_VERSION);
    }

    @Override
    public void onCreate(SQLiteDatabase sqLiteDatabase) {
        //createTable(sqLiteDatabase);
    }
    @Override
    public void onUpgrade(SQLiteDatabase sqLiteDatabase, int i, int i1) {
        onCreate(sqLiteDatabase);
    }
}

Note that referring to many articles, they all create data tables in the OnCreate implementation. However, I think this method of creating tables is sometimes not very effective and is not conducive to the creation of multiple tables. Therefore, I did not create a table in the OnCreate implementation. I took out the method of creating a table separately. When I need to create a table and when to create it, it will be more flexible.

2. Create a database management class to manage the creation of database tables and the addition, deletion, and modification of table data. The code is as follows:

package com.tuoqun.Tool;

import android.content.ContentValues;
import android.content.Context;
import android.util.Log;

import net.sqlcipher.Cursor;
import net.sqlcipher.SQLException;
import net.sqlcipher.database.SQLiteDatabase;

import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;

public class DBCipherManager {
    private static final String TAG = "DatabaseManager";
    // 静态引用
    private volatile static DBCipherManager mInstance;//volatile关键字会保证修改的值会立即被更新到主存,当有其他线程需要读取时,它会去内存中读取新值(参考https://www.cnblogs.com/dolphin0520/p/3920373.html)。
    // DatabaseHelper
    private DBCipherHelper dbHelper;

    private DBCipherManager(Context context) {
        dbHelper = new DBCipherHelper(context);
    }

    /**
     * 获取单例引用
     *
     * @param context
     * @return
     */
    public static DBCipherManager getInstance(Context context) {
        DBCipherManager inst = mInstance;
        //Java 中的双重检查(Double-Check)
        if (inst == null) {
            synchronized (DBCipherManager.class) {
                inst = mInstance;
                if (inst == null) {
                    inst = new DBCipherManager(context);
                    mInstance = inst;
                }
            }
        }
        return inst;
    }

    /**
     * 插入数据
     * @param tableName 待插入数据表的表名
     * @param contentValues 要修改或者插入的键值对(表中字段名,对应值)eg:ContentValues values=new ContentValues();
     *                                                                   values.put("fieldname","fieldValue");
     */
    public void insertData(String tableName,ContentValues contentValues) {
        //获取写数据库
        SQLiteDatabase db = dbHelper.getWritableDatabase(DBCipherHelper.DB_PWD);
        // insert 操作
        db.insert(tableName, null, contentValues);
        //关闭数据库
        db.close();
    }

    /**
     * 未开启事务批量插入
     * @param tableName 待插入数据表的表名
     * @param contentValuesList 要修改或者插入的键值对列表
     */
    public void insertDatasByNomarl(String tableName, List<ContentValues> contentValuesList){
        //获取写数据库
        SQLiteDatabase db = dbHelper.getWritableDatabase(DBCipherHelper.DB_PWD);
        for(int i =0;i<contentValuesList.size();i++ ){
            // insert 操作
            db.insert(tableName, null, contentValuesList.get(i));
            Log.e(TAG, "insertDatasByNomarl");
        }
        //关闭数据库
        db.close();
    }

    /**
     * 开启事务批量插入
     * @param tableName 待插入数据表的表名
     * @param contentValuesList 要修改或者插入的键值对列表
     */
    public void insertDatasByTransaction(String tableName, List<ContentValues> contentValuesList){
        //获取写数据库
        SQLiteDatabase db = dbHelper.getWritableDatabase(DBCipherHelper.DB_PWD);
        db.beginTransaction();  //手动设置开始事务
        try{
            //批量处理操作
            for(int i =0;i<contentValuesList.size();i++ ){
                // insert 操作
                db.insert(tableName, null, contentValuesList.get(i));
                Log.e(TAG, "insertDatasByTransaction");
            }
            db.setTransactionSuccessful(); //设置事务处理成功,不设置会自动回滚不提交
        }catch(Exception e){

        }finally{
            db.endTransaction(); //处理完成
            //关闭数据库
            db.close();
        }
    }

    /**
     * 删除数据
     * @param tableName 待删除数据表的表名
     * @param whereClause 删除数据条件语句 eg: StringBuffer whereBuffer = new StringBuffer();
     * whereBuffer.append(DBCipherHelper.FIELD_NAME).append(" = ").append("'").append(name).append("'");
     */
    public void deleteData(String tableName,StringBuffer whereClause) {
        //获取写数据库
        SQLiteDatabase db = dbHelper.getWritableDatabase(DBCipherHelper.DB_PWD);
        // delete 操作
        db.delete(tableName, whereClause.toString(), null);
        //关闭数据库
        db.close();
    }

    /**
     * 删除所有数据
     * @param tableName 待删除数据表的表名
     */
    public void deleteDataAll(String tableName)
    {
        String sql="delete from "+ tableName;//可以在不删除表的情况下删除所有的行
        execSQL(sql);
    }

    /**
     * 更新数据
     * @param tableName 待更新数据表的表名
     * @param whereClause 更新数据条件语句
     * @param newValue 更新数据的新值
     */
    public void updateData(String tableName,StringBuffer whereClause,ContentValues newValue) {
        //获取写数据库
        SQLiteDatabase db = dbHelper.getWritableDatabase(DBCipherHelper.DB_PWD);
        // update 操作
        db.update(tableName, newValue, whereClause.toString(), null);
        //关闭数据库
        db.close();
    }

    /**
     * 指定条件查询数据
     * @param tableName 待查询数据表的表名
     * @param whereClause 查询条件(if whereClause=null,则为查询所有数据 )
     * @param queryColumns 查询列 eg: String[] queryColumns = {fieldName};
     * @return <列名,列值>
     */
    public List<Map<String,String>> queryDatas(String tableName,StringBuffer whereClause,String[] queryColumns){
        List<Map<String,String>> queryResultList=new ArrayList<>();
        Map<String,String> queryResult;
        String columName="";
        String  columValue="";
        //获取可读数据库
        SQLiteDatabase db = dbHelper.getReadableDatabase(DBCipherHelper.DB_PWD);
        //查询数据库
        Cursor cursor;
        try {
            if (whereClause==null)
                cursor = db.query(tableName, queryColumns,null, null, null, null, null);
            else
                cursor = db.query(tableName, queryColumns, whereClause.toString(), null, null, null, null);
            while (cursor.moveToNext()) {
                queryResult=new LinkedHashMap<>();
                int count = cursor.getColumnCount();
                for (int i=0;i<count;i++)
                {
                    columName = cursor.getColumnName(i);
                    columValue = cursor.getString(i);
                    queryResult.put(columName,columValue);
                }
                queryResultList.add(queryResult);
                //Log.e(TAG, "count = " + count + " columName = " + columName + "  name =  " +tname);
            }
            //关闭游标防止内存泄漏
            if (cursor != null) {
                cursor.close();
            }
        } catch (SQLException e) {
            Log.e(TAG, "queryDatas" + e.toString());
        }
        //关闭数据库
        db.close();
        return queryResultList;
    }
    /**
     * 执行sql语句
     */
    public void execSQL(String sql){
        //获取写数据库
        SQLiteDatabase db = dbHelper.getWritableDatabase(DBCipherHelper.DB_PWD);
        //直接执行sql语句
        db.execSQL(sql);//或者
        //关闭数据库
        db.close();
    }
}

3. For the usage of the above management class, the sample code is as follows:

//建立Sqlite数据库所需
DBCipherHelper.DB_NAME="testDB";
DBCipherHelper.DB_PWD="shy";
DBCipherHelper.DB_VERSION=1;

//创建表所需
String tableName="proofPhotoInfo";
String createTableSQL="CREATE TABLE "+tableName+"(ID integer primary key autoincrement,layerName text not null,picName text not null,azimuth text,pitch text,roll text,longitude text not null,latitude text not null);";//在SQLite数据库中创建表SQL语句(该表用于存储该类中信息)

//1、建库和建表
       try {
             DBCipherManager.getInstance(context).execSQL(createTableSQL);//建库和建表
       } catch (Exception e) {
             e.printStackTrace();
       }
//2、插入数据
ContentValues photoInfo=new ContentValues();
photoInfo.put("layerName",CameraClass.layerDirName);
photoInfo.put("picName",basicDOClass.getFileName(CameraClass.currenImgFilePath));
photoInfo.put("azimuth",SensorEx.azimuth+"");
photoInfo.put("pitch",SensorEx.pitch+"");
photoInfo.put("roll",SensorEx.roll+"");
photoInfo.put("longitude",SensorEx.longitude+"");
photoInfo.put("latitude",SensorEx.latitude+"");
DBCipherManager.getInstance(context).insertData(tableName,photoInfo);//插入数据

//3、查询数据
StringBuffer querySQLWhere=new StringBuffer();
String layerName=basicDOClass.getDirName(basicDOClass.getFilePath(photoPath));
String picName=basicDOClass.getFileName(photoPath);
querySQLWhere.append("layerName").append("=").append("'").append(layerName).append("'").append(" and ").append("picName").append("=").append("'").append(picName).append("'");     
queryPhotoInfoResult=DBCipherManager.getInstance(context).queryDatas(tableName,querySQLWhere,new String[]{"ID","layerName","picName","azimuth","pitch","roll","longitude","latitude"});//查询数据

 

Guess you like

Origin blog.csdn.net/feng8403000/article/details/114906257