病毒库直接使用assets目录下的antivirus.db文件,查询该数据库的类AntiVirusDao:
package com.example.mobilesafe.db;
import android.content.Context;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
/**
* Created by sing on 14-1-26.
* desc:
*/
public class AntiVirusDao {
private static final String TAG = "AntiVirusDao";
private Context context;
public AntiVirusDao(Context context) {
this.context = context;
}
/**
* 获取病毒的信息 如果没有获取到返回空
* @param md5
* @return
*/
public String getVirusInfo(String md5){
//默认情况下,没有获取到病毒信息
String result = null;
//病毒数据库的路径
String path = "/data/data/com.example.mobilesafe/files/antivirus.db";
//打开数据库
SQLiteDatabase db = SQLiteDatabase.openDatabase(path, null, SQLiteDatabase.OPEN_READONLY);
if(db.isOpen()){
//执行查询操作,返回一个结果集
Cursor cursor = db.rawQuery("select desc from datable where md5=?", new String[]{md5});
if(cursor.moveToFirst()){
result = cursor.getString(0);
}
//必须关闭系统的游标,如果没有关闭,即使关闭了数据库,也容易报出内存泄漏的异常信息
cursor.close();
db.close();
}
return result;
}
}
其中Md5Encoder:
package com.example.utils;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
/**
* Created by sing on 14-1-26.
* desc:
*/
public class Md5Encoder {
private static final String TAG = "Md5Encoder";
public static String encode(String password) {
try {
//获取到数字消息的摘要器
MessageDigest digest = MessageDigest.getInstance("MD5");
//执行加密操作
byte[] result = digest.digest(password.getBytes());
StringBuilder sb = new StringBuilder();
//将每个byte字节的数据转换成16进制的数据
for (int i = 0; i < result.length; i++) {
int number = result[i] & 0xff;//加盐
String str = Integer.toHexString(number);//将十进制的number转换成十六进制数据
if (str.length() == 1) {//判断加密后的字符的长度,如果长度为1,则在该字符前面补0
sb.append("0");
sb.append(str);
} else {
sb.append(str);
}
}
return sb.toString();//将加密后的字符转成字符串返回
} catch (NoSuchAlgorithmException e) {//加密器没有被找到,该异常不可能发生。因为我们填入的“MD5”是正确的
e.printStackTrace();
//CNA'T REACH;
return "";
}
}
}
需要事先将antivirus.db文件从assets目录复制到程序目录下,在SplashActivity的创建更新线程后添加:
//拷贝病毒库的数据库文件
new Thread() {
public void run() {
File file = new File(getFilesDir(), "antivirus.db");
if (file.exists() && file.length() > 0) {//数据库文件已经拷贝成功
} else {
AssetUtil.copy1(getApplicationContext(), "antivirus.db", file.getAbsolutePath(), null);
}
};
}.start();
其中AssetUtil.copy1:
/**
* 从资产目录拷贝文件
*
* @param context
* @param filename
* 资产目录的文件的名称
* @param destfilename
* 目标文件的路径
* @return
*/
public static File copy1(Context context, String filename, String destfilename, ProgressDialog pd) {
try {
InputStream in = context.getAssets().open(filename);
int max = in.available();
if (pd != null) {
pd.setMax(max);
}
File file = new File(destfilename);
OutputStream out = new FileOutputStream(file);
byte[] byt = new byte[1024];
int len = 0;
int total = 0;
while ((len = in.read(byt)) != -1) {
out.write(byt, 0, len);
total += len;
if (pd != null) {
pd.setProgress(total);
}
}
out.flush();
out.close();
in.close();
return file;
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
AntiVirusActivity代码:
package com.example.mobilesafe;
import android.app.Activity;
import android.content.Intent;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.net.Uri;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.view.View;
import android.view.animation.Animation;
import android.view.animation.RotateAnimation;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.ProgressBar;
import android.widget.TextView;
import android.widget.Toast;
import com.example.mobilesafe.db.AntiVirusDao;
import com.example.utils.Md5Encoder;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
/**
* Created by sing on 14-1-26.
* desc:
*/
public class AntiVirusActivity extends Activity {
protected static final int SCAN_NOT_VIRUS = 90;
protected static final int FIND_VIRUS = 91;
protected static final int SCAN_FINISH = 92;
// 查杀病毒时,雷达上的扫描指针
private ImageView iv_scan;
// 应用程序包管理器
private PackageManager pm;
// 操作数据库的对象
private AntiVirusDao dao;
// 扫描进度条
private ProgressBar progressBar1;
// 显示发现的病毒数目
private TextView tv_scan_status;
// 显示扫描的程序信息
private LinearLayout ll_scan_status;
// 用于添加扫描到的病毒信息
private List<PackageInfo> virusPackInfos;
// 旋转动画
RotateAnimation ra;
// 存放病毒的集合
private Map<String, String> virusMap;
// 用于与子线程通信,更新主线程(UI线程)
private Handler handler = new Handler() {
public void handleMessage(android.os.Message msg) {
PackageInfo info = (PackageInfo) msg.obj;
switch (msg.what) {
case SCAN_NOT_VIRUS:// 未发现病毒
TextView tv = new TextView(getApplicationContext());
tv.setText("扫描" + info.applicationInfo.loadLabel(pm) + " 安全");
ll_scan_status.addView(tv, 0);// 添加到ll_scan_info控件的最上面
break;
case FIND_VIRUS:// 发现病毒
// 将病毒添加到集合中
virusPackInfos.add(info);
break;
case SCAN_FINISH:// 扫描完成
// 停止动画的播放
iv_scan.clearAnimation();
// 判断病毒集合的大小
if (virusPackInfos.size() == 0) {
Toast.makeText(getApplicationContext(), "扫描完毕,你的手机很安全", 0).show();
}
break;
}
};
};
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.antivirus_layout);
pm = getPackageManager();
dao = new AntiVirusDao(this);
virusPackInfos = new ArrayList<PackageInfo>();
super.onCreate(savedInstanceState);
tv_scan_status = (TextView) findViewById(R.id.tv_scan_status2);
iv_scan = (ImageView) findViewById(R.id.iv_scan);
// 设置一个旋转的动画
ra = new RotateAnimation(0, 360, Animation.RELATIVE_TO_SELF, 1.0f, Animation.RELATIVE_TO_SELF, 1.0f);
ra.setDuration(1000);
// 设置旋转的重复次数(一直旋转)
ra.setRepeatCount(Animation.INFINITE);
// 设置旋转的模式(旋转一个回合后,重新旋转)
ra.setRepeatMode(Animation.RESTART);
ll_scan_status = (LinearLayout) findViewById(R.id.ll_scan_status);
progressBar1 = (ProgressBar) findViewById(R.id.progressBar1);
}
public void kill(View v) {
// 重置动画
ra.reset();
// 启动动画
iv_scan.startAnimation(ra);
// 开启一条子线程,遍历手机中各个应用的签名信息
new Thread() {
public void run() {
// PackageManager.GET_SIGNATURES应用程序的签名信息
List<PackageInfo> packinfos = pm.getInstalledPackages(PackageManager.GET_SIGNATURES);
progressBar1.setMax(packinfos.size());
// 计数当前已经遍历了多少条应用程序,以显示查杀的进度
int count = 0;
// 遍历出各个应用程序对应的签名信息
for (PackageInfo info : packinfos) {
// 将应用程序的签名信息转成MD5值,用于与病毒数据库比对
String md5 = Md5Encoder.encode(info.signatures[0]
.toCharsString());
// 在病毒数据库中查找该MD5值,来判断该应用程序是否数据病毒
String result = dao.getVirusInfo(md5);
// 如果查找的结果为null,则表示当前遍历的应用不是病毒
if (result == null) {
Message msg = Message.obtain();
msg.what = SCAN_NOT_VIRUS;
msg.obj = info;
handler.sendMessage(msg);
} else {//当前遍历到的应用属于病毒
Message msg = Message.obtain();
msg.what = FIND_VIRUS;
msg.obj = info;
handler.sendMessage(msg);
}
count++;
try {
Thread.sleep(20);
} catch (InterruptedException e) {
e.printStackTrace();
}
progressBar1.setProgress(count);
}
// 遍历结束
Message msg = Message.obtain();
msg.what = SCAN_FINISH;
handler.sendMessage(msg);
};
}.start();
}
// "一键清理"按钮
public void clean(View v) {
// 判断病毒集合的大小
if (virusPackInfos.size() > 0) {
for (PackageInfo pinfo : virusPackInfos) {
// 卸载应用程序
String packname = pinfo.packageName;
Intent intent = new Intent();
intent.setAction(Intent.ACTION_DEFAULT);
intent.setData(Uri.parse("package:" + packname));
startActivity(intent);
}
}else{
return;
}
}
}
这里的扫描动画有个技巧,一共有两个imageview,一个在底层是一个完整的图片,一个在顶层是一个半透明的小方块,运行时让其以右下角进行360度的旋转。