病毒库直接使用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; } }
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度的旋转。