利用SQLChiper对Android SQLite数据库加密
前言: 上篇文章讲了Android studio+SQLCipher加密SQLite数据库的几个坑,跳过这几个坑,那么SQLCipher的前提就处理完成,本片文章接着讲如何使用SQLCiper加密数据库。
一、与SQLite的使用相似先继承SQLiteOpenHelper,实现其中的OnCreate和onUpgrade两个抽象方法,同时必须super其中至少一个构造函数。代码如下:
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); } }
注意,参照多篇文章,他们都是在OnCreate实现中创建数据表,但是,我觉得这种方法创建表有时候不太灵验,而且不利于多张表的创建。因此,我并未在OnCreate实现中创建表,我把创建表的方法单独拿出去,何时需要创建表,何时创建,这样会比较灵活。
二、创建数据库管理类,用来管理数据库表的创建,以及表数据的增删改查,代码如下:
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(); } }