43、手机杀毒--代码实现

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


你可能感兴趣的:(43、手机杀毒--代码实现)