Android 系统的Sqlite数据库是一个轻量级且没有加密功能的数据库,但有时候我们的数据库保存了一些重要的信息,不想让别人知道,就需要对数据库加密。但大多数的加密都需要收费的,而Sqlcipher是免费的。下面我们用sqlcipher来加密数据库。
一、配置工程
注意assets下的文件
二、加载so
我们在Application加载so,别忘记将Application配置到Manifest文件中
package com.huang.sqlcipher;
//注意导包
import net.sqlcipher.database.SQLiteDatabase;
import android.app.Application;
public class MyApplication extends Application {
@Override
public void onCreate() {
// TODO Auto-generated method stub
super.onCreate();
//加载so
SQLiteDatabase.loadLibs(MyApplication.this);
}
}
三、加密
注:输入的密码在第一次生效,后期无法修改,当密码为空时,相当于没有加密的数据库
1.我们可以用
SQLiteDatabase.openOrCreateDatabase(file, password, factory)
来获取SQLiteDatabase进行操作
2.也可以对/data/data下数据库进行加密
SqlDbHelper类
package com.huang.sqlcipher;
import android.content.Context;
import net.sqlcipher.database.SQLiteDatabase;
import net.sqlcipher.database.SQLiteDatabase.CursorFactory;
import net.sqlcipher.database.SQLiteOpenHelper;
public class SqlDbHelper extends SQLiteOpenHelper {
public static final String CREATE_TABLE = "create table person (name text, age integer)";
public SqlDbHelper(Context context, String name, CursorFactory factory,
int version) {
super(context, name, factory, version);
}
@Override
public void onCreate(SQLiteDatabase db) {
//创建表格
db.execSQL(CREATE_TABLE);
}
@Override
public void onUpgrade(SQLiteDatabase arg0, int arg1, int arg2) {
// TODO Auto-generated method stub
}
/**
* @param args
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
}
}
调用获取SQLiteDatabase
SqlDbHelper dbHelper = new SqlDbHelper(this, "test.db", null, 1);
//输入密码加密
db = dbHelper.getWritableDatabase("123456");
测试代码:
package com.huang.sqlcipher;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import net.sqlcipher.Cursor;
import net.sqlcipher.database.SQLiteDatabase;
import android.app.Activity;
import android.content.ContentValues;
import android.os.Bundle;
import android.os.Environment;
import android.util.Log;
import android.view.View;
import android.view.View.OnClickListener;
public class MainActivity extends Activity implements OnClickListener{
private SQLiteDatabase db;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
SqlDbHelper dbHelper = new SqlDbHelper(this, "test.db", null, 1);
//这里的123456是给数据库加密的密码,密码在第一次生效,后期无法修改,当密码为空时,相当于没有加密的数据库
db = dbHelper.getWritableDatabase("123456");
//插入数据
findViewById(R.id.add_data).setOnClickListener(this);
//查询数据
findViewById(R.id.query_data).setOnClickListener(this);
//手机没有root,拷贝数据库到sd卡,看是否加密成功
findViewById(R.id.copy_db).setOnClickListener(this);
}
@Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.add_data:
ContentValues values = new ContentValues();
values.put("name", "小红");
values.put("age", 123);
db.insert("person", null, values);
break;
case R.id.query_data:
Cursor cursor = db.query("person", null, null, null, null, null, null);
if (cursor != null) {
while (cursor.moveToNext()) {
String name = cursor.getString(cursor.getColumnIndex("name"));
int age = cursor.getInt(cursor.getColumnIndex("age"));
Log.d("TAG", "name is " + name);
Log.d("TAG", "age is " + age);
}
}
cursor.close();
break;
case R.id.copy_db:
//找到文件的路径 /data/data/包名/databases/数据库名称
File dbFile = new File(Environment.getDataDirectory().getAbsolutePath()+"/data/"+getPackageName()+"/databases/test.db");
FileInputStream fis = null;
FileOutputStream fos = null;
try {
//文件复制到sd卡中
fis = new FileInputStream(dbFile);
fos = new FileOutputStream(Environment.getExternalStorageDirectory().getAbsolutePath()+"/copy.db");
int len = 0;
byte[] buffer = new byte[2048];
while(-1!=(len=fis.read(buffer))){
fos.write(buffer, 0, len);
}
fos.flush();
} catch (Exception e) {
e.printStackTrace();
}finally{
//关闭数据流
try{
if(fos!=null)fos.close();
if (fis!=null)fis.close();
}catch(IOException e){
e.printStackTrace();
}
}
break;
}
}
}
测试结果:
将db文件拷贝出来并用SQLiteExpertPers打开会出错:
sqlcipher可能存在版本不兼容问题,用最新的jar与so打不以前加密的db文件情况。