利用SQLChiper对Android SQLite数据库加密
生活随笔
收集整理的這篇文章主要介紹了
利用SQLChiper对Android SQLite数据库加密
小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.
利用SQLChiper對Android SQLite數(shù)據庫加密
前言: 上篇文章講了Android studio+SQLCipher加密SQLite數(shù)據庫的幾個坑,跳過這幾個坑,那么SQLCipher的前提就處理完成,本片文章接著講如何使用SQLCiper加密數(shù)據庫。
一、與SQLite的使用相似先繼承SQLiteOpenHelper,實現(xiàn)其中的OnCreate和onUpgrade兩個抽象方法,同時必須super其中至少一個構造函數(shù)。代碼如下:
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;//數(shù)據庫名字public static String DB_PWD;//數(shù)據庫密碼public static int DB_VERSION; // 數(shù)據庫版本//private String createTableSQL="";//創(chuàng)建數(shù)據庫表的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);}@Overridepublic void onCreate(SQLiteDatabase sqLiteDatabase) {//createTable(sqLiteDatabase);}@Overridepublic void onUpgrade(SQLiteDatabase sqLiteDatabase, int i, int i1) {onCreate(sqLiteDatabase);} }注意,參照多篇文章,他們都是在OnCreate實現(xiàn)中創(chuàng)建數(shù)據表,但是,我覺得這種方法創(chuàng)建表有時候不太靈驗,而且不利于多張表的創(chuàng)建。因此,我并未在OnCreate實現(xiàn)中創(chuàng)建表,我把創(chuàng)建表的方法單獨拿出去,何時需要創(chuàng)建表,何時創(chuàng)建,這樣會比較靈活。
二、創(chuàng)建數(shù)據庫管理類,用來管理數(shù)據庫表的創(chuàng)建,以及表數(shù)據的增刪改查,代碼如下:
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";// 靜態(tài)引用private volatile static DBCipherManager mInstance;//volatile關鍵字會保證修改的值會立即被更新到主存,當有其他線程需要讀取時,它會去內存中讀取新值(參考https://www.cnblogs.com/dolphin0520/p/3920373.html)。// DatabaseHelperprivate 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;}/*** 插入數(shù)據* @param tableName 待插入數(shù)據表的表名* @param contentValues 要修改或者插入的鍵值對(表中字段名,對應值)eg:ContentValues values=new ContentValues();* values.put("fieldname","fieldValue");*/public void insertData(String tableName,ContentValues contentValues) {//獲取寫數(shù)據庫SQLiteDatabase db = dbHelper.getWritableDatabase(DBCipherHelper.DB_PWD);// insert 操作db.insert(tableName, null, contentValues);//關閉數(shù)據庫db.close();}/*** 未開啟事務批量插入* @param tableName 待插入數(shù)據表的表名* @param contentValuesList 要修改或者插入的鍵值對列表*/public void insertDatasByNomarl(String tableName, List<ContentValues> contentValuesList){//獲取寫數(shù)據庫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");}//關閉數(shù)據庫db.close();}/*** 開啟事務批量插入* @param tableName 待插入數(shù)據表的表名* @param contentValuesList 要修改或者插入的鍵值對列表*/public void insertDatasByTransaction(String tableName, List<ContentValues> contentValuesList){//獲取寫數(shù)據庫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(); //處理完成//關閉數(shù)據庫db.close();}}/*** 刪除數(shù)據* @param tableName 待刪除數(shù)據表的表名* @param whereClause 刪除數(shù)據條件語句 eg: StringBuffer whereBuffer = new StringBuffer();* whereBuffer.append(DBCipherHelper.FIELD_NAME).append(" = ").append("'").append(name).append("'");*/public void deleteData(String tableName,StringBuffer whereClause) {//獲取寫數(shù)據庫SQLiteDatabase db = dbHelper.getWritableDatabase(DBCipherHelper.DB_PWD);// delete 操作db.delete(tableName, whereClause.toString(), null);//關閉數(shù)據庫db.close();}/*** 刪除所有數(shù)據* @param tableName 待刪除數(shù)據表的表名*/public void deleteDataAll(String tableName){String sql="delete from "+ tableName;//可以在不刪除表的情況下刪除所有的行execSQL(sql);}/*** 更新數(shù)據* @param tableName 待更新數(shù)據表的表名* @param whereClause 更新數(shù)據條件語句* @param newValue 更新數(shù)據的新值*/public void updateData(String tableName,StringBuffer whereClause,ContentValues newValue) {//獲取寫數(shù)據庫SQLiteDatabase db = dbHelper.getWritableDatabase(DBCipherHelper.DB_PWD);// update 操作db.update(tableName, newValue, whereClause.toString(), null);//關閉數(shù)據庫db.close();}/*** 指定條件查詢數(shù)據* @param tableName 待查詢數(shù)據表的表名* @param whereClause 查詢條件(if whereClause=null,則為查詢所有數(shù)據 )* @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="";//獲取可讀數(shù)據庫SQLiteDatabase db = dbHelper.getReadableDatabase(DBCipherHelper.DB_PWD);//查詢數(shù)據庫Cursor cursor;try {if (whereClause==null)cursor = db.query(tableName, queryColumns,null, null, null, null, null);elsecursor = 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());}//關閉數(shù)據庫db.close();return queryResultList;}/*** 執(zhí)行sql語句*/public void execSQL(String sql){//獲取寫數(shù)據庫SQLiteDatabase db = dbHelper.getWritableDatabase(DBCipherHelper.DB_PWD);//直接執(zhí)行sql語句db.execSQL(sql);//或者//關閉數(shù)據庫db.close();} }三、對上面管理類的使用方法,示例代碼如下:
//建立Sqlite數(shù)據庫所需 DBCipherHelper.DB_NAME="testDB"; DBCipherHelper.DB_PWD="shy"; DBCipherHelper.DB_VERSION=1;//創(chuàng)建表所需 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數(shù)據庫中創(chuàng)建表SQL語句(該表用于存儲該類中信息)//1、建庫和建表try {DBCipherManager.getInstance(context).execSQL(createTableSQL);//建庫和建表} catch (Exception e) {e.printStackTrace();} //2、插入數(shù)據 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);//插入數(shù)據//3、查詢數(shù)據 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"});//查詢數(shù)據?
總結
以上是生活随笔為你收集整理的利用SQLChiper对Android SQLite数据库加密的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 详解计算机内部存储数据的形式 二进制数
- 下一篇: 超全的Android组件及UI框架