[mobilesafe] 06_手机杀毒-病毒查杀-病毒扫描

Android 4.0

手机杀毒-病毒查杀-

技术点:1、PackageManager.GET_UNINSTALLED_PACKAGES,获取那些已经卸载掉的应用,但数据文件没有删除
2、获取应用的签名,要加上flag,否则包管理者是不会获取的
packageInfo.signatures[0]  这是google为了扩展,而定义的返回一个数组,现在只用到第一个
步骤:
1、获取手机上所有的应用(包括已经卸载的,但没删除数据的)
2、然后获取其签名,转换成MD5值
3、将这个MD5值和病毒数据库中进行比较,如果存在,那么认为是病毒
4、拷贝病毒数据库antivirus.db到应用目录中
5、然后细节处理
核心代码:
package cn.zengfansheng.mobilesafe;
 
import java.util.List;
 
import android.app.Activity;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.graphics.Color;
import android.os.AsyncTask;
import android.os.Bundle;
import android.view.ViewGroup.LayoutParams;
import android.view.animation.AnimationUtils;
import android.view.animation.RotateAnimation;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.ProgressBar;
import android.widget.TextView;
import cn.zengfansheng.mobilesafe.db.dao.AntiVirusDao;
import cn.zengfansheng.mobilesafe.utils.DensityUtil;
import cn.zengfansheng.mobilesafe.utils.MD5Utils;
 
/**
* 26、病毒查杀AntiVirusActivity
* @author hacket
*/

public class AntiVirusActivity extends Activity {
 
    private ImageView iv_scan_malware;// 病毒扫描雷达
 
    private ProgressBar pb_scan_progress;// 扫描进度条
 
    private TextView tv_scan_status;// 扫描状态对应的文本
 
    private LinearLayout ll_scan_content;// 扫描过程中存放的扫描到的应用名
 
    private PackageManager packageManager;// 包管理者
 
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        this.setContentView(R.layout.activity_anti_virus);
 
        iv_scan_malware = (ImageView) this.findViewById(R.id.iv_scan_malware);
 
        pb_scan_progress = (ProgressBar) this.findViewById(R.id.pb_scan_progress);
        tv_scan_status = (TextView) this.findViewById(R.id.tv_scan_status);
        ll_scan_content = (LinearLayout) this.findViewById(R.id.ll_scan_content);
 
        // 病毒扫描过程中的转动动画
        // multiThreadUpdateUI();
 
        // 1、使用代码定义动画,播放动画
        /*RotateAnimation ra = new RotateAnimation(0, 360,Animation.RELATIVE_TO_PARENT, 0.5f,Animation.RELATIVE_TO_PARENT, 0.5f);
        ra.setDuration(2000);
        ra.setRepeatCount(Animation.INFINITE);
        ra.setInterpolator(new LinearInterpolator());// 匀速旋转
        iv_scan_malware.startAnimation(ra);*/

 
        // 2、使用xml文件方式定义的动画
        RotateAnimation ra = (RotateAnimation) AnimationUtils.loadAnimation(this, R.anim.anti_virus_walware);
        iv_scan_malware.startAnimation(ra);
 
 
        // 3、异步任务
        new AsyncTask<Void, Object, Void>(){
 
            int total = 0;// 扫描进度条值的变化
 
            // 开始扫描前,主线程
            @Override
            protected void onPreExecute() {
                super.onPreExecute();
                tv_scan_status.setText("初始化全新的杀毒引擎");
                try {
                    Thread.sleep(2000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
 
            // 扫描过程中,ui的更新,主线程
            @Override
            protected void onProgressUpdate(Object... values) {
                super.onProgressUpdate(values);
                AntivirusAppInfo appInfo = (AntivirusAppInfo) values[0];
 
                tv_scan_status.setText("正在扫描:" + appInfo.appName);
 
                if (appInfo.isVirusApp) {
                    TextView tv = new TextView(getApplicationContext());
 
                    LayoutParams params = new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
                    tv.setLayoutParams(params);
                    int px5 = DensityUtil.dip2px(getApplicationContext(), 5);
                    int px10 = DensityUtil.dip2px(getApplicationContext(), 10);
                    tv.layout(px10, px5, px10, px5);
                    tv.setTextColor(Color.RED);
                    tv.setText("正在扫描:" + appInfo.appName + ":" + "发现病毒");
                    ll_scan_content.addView(tv, 0);// 每次都加到最前面
                } else {
                    TextView tv = new TextView(getApplicationContext());
 
                    tv.setTextColor(Color.GREEN);
                    LayoutParams params = new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
                    tv.setLayoutParams(params);
                    int px5 = DensityUtil.dip2px(getApplicationContext(), 5);
                    int px10 = DensityUtil.dip2px(getApplicationContext(), 10);
                    tv.layout(px10, px5, px10, px5);
 
                    tv.setText("正在扫描:" + appInfo.appName + ":" + "扫描安全");
 
                    ll_scan_content.addView(tv, 0);// 每次都加到最前面
                }
                total++;
                pb_scan_progress.setProgress(total);
            }
 
            // 后台扫描,查找数据库
            @Override
            protected Void doInBackground(Void... params) {
 
                packageManager = getPackageManager();
 
                int flags = PackageManager.GET_UNINSTALLED_PACKAGES|PackageManager.GET_SIGNATURES;//获取所有的应用(已删除应用但数据没有删除)和应用的签名
                // If flag GET_UNINSTALLED_PACKAGES is set, a list of all applications including those deleted with DONT_DELETE_DATA (partially installed apps with data directory) will be returned.
 
                List<PackageInfo> listPackageInfos = packageManager.getInstalledPackages(flags);
                pb_scan_progress.setMax(listPackageInfos.size());
                for (PackageInfo packageInfo : listPackageInfos) {
 
                    // 获取签名
                    String signature = packageInfo.signatures[0].toString().trim();
                    String signatureMD5 = MD5Utils.encode(signature);//
                    System.out.println("【"+packageInfo.packageName+"---"+signatureMD5+"】");
 
                    boolean isVirus = AntiVirusDao.isVirusByMD5(getApplicationContext(), signatureMD5);
 
                    AntivirusAppInfo appInfo = new AntivirusAppInfo();
                    appInfo.appName = packageInfo.applicationInfo.loadLabel(packageManager).toString();
                    if (isVirus) {// 是病毒
                        appInfo.isVirusApp = true;
                    } else {// 不是病毒
                        appInfo.isVirusApp = false;
                    }
 
                    // 通知进度更新,用的是publishProgress(),而不是onProgressUpdate()
                    // onProgressUpdate(appInfo);
                    publishProgress(appInfo);
 
                    try {
                        Thread.sleep(30);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
                return null;
            }
 
            // 扫描完成后,主线程
            @Override
            protected void onPostExecute(Void result) {
                super.onPostExecute(result);
                tv_scan_status.setText("扫描完成");
                iv_scan_malware.clearAnimation();
            }
 
        }.execute();
 
        /*测试ProgressBar的
         * new Thread() {
            public void run() {
                pb_scan_progress.setMax(100);
                for (int i = 1; i <= 100; i++) {
                    pb_scan_progress.setProgress(i);
                    try {
                        Thread.sleep(30);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }
        }.start();*/

    }
 
    private class AntivirusAppInfo {
        private boolean isVirusApp;// 是否是病毒应用
        private String appName;// 应用名
    }
    /**
     * 1、多个子线程更新扫描病毒雷达,防止动画播放时,速度不一致。
     */

    /*public void multiThreadUpdateUI() {
        boolean flag = true;// true 表示前面180°在播放动画
        Lock lock = new ReentrantLock();
        Condition conditionA = lock.newCondition();
        Condition conditionB = lock.newCondition();
        // A
        new Thread() {
            public void run() {
                while (true) {
                    try {
                        lock.lock();
                        if (!flag) {// flag为false才等待
                            System.out.println("A等待~~~");
                            conditionA.await();// 等待conditionB
                        } else {
                            System.out.println("A更新UI");
                            RotateAnimation ra1 = new RotateAnimation(0, 90,
                                    Animation.RELATIVE_TO_SELF, 0.5f,
                                    Animation.RELATIVE_TO_SELF, 0.5f);
                            ra1.setDuration(1500);// 动画播放时间,一定要设置,否则播放不了
                            ra1.setRepeatCount(Animation.INFINITE);// 永远播放下去,-1
                            iv_scan_malware.startAnimation(ra1);
                            // 参数1:从哪个角度开始 ,参数2:到哪个角度为止, 参数3:x轴相对于谁
                            // ,参数4:动画播放起始坐标x
                            // ,参数5:y轴相对于谁, 参数6:动画播放起始坐标y
 
                            flag = false;
                            conditionB.signal();// 唤醒B线程
                            System.out.println("唤醒B~~~");
                            Thread.sleep(1500);
                        }
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    } finally {
                        lock.unlock();
                    }
                }
            }
        }.start();
 
        // B
        new Thread() {
            public void run() {
                while (true) {
                    try {
                        lock.lock();
                        if (flag) {// flag = true , 等待A
                            System.out.println("B等待~~~");
                            conditionB.await();// 等待A线程
                        } else {
                            System.out.println("B更新UI");
                            RotateAnimation ra2 = new RotateAnimation(90, 180,
                                    Animation.RELATIVE_TO_SELF, 0.5f,
                                    Animation.RELATIVE_TO_SELF, 0.5f);
                            ra2.setDuration(1500);// 动画播放时间,一定要设置,否则播放不了
                            ra2.setRepeatCount(Animation.INFINITE);// 永远播放下去,-1
                            iv_scan_malware.startAnimation(ra2);
 
                            flag = true;
                            conditionA.signal();// 唤醒A
                            System.out.println("唤醒A");
                            Thread.sleep(1500);
                        }
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    } finally {
                        lock.unlock();
                    }
                }
            }
        }.start();
    }*/

}
结果:
问题:游标没有关闭,导致的问题,数据查询很多的时候会出现
11-22 17:17:43.833: E/AndroidRuntime(16476): Caused by: java.lang.IllegalStateException: Process 16476 exceeded cursor quota 100, will kill it
解决:数据库查询完毕,一定要将游标给关闭
if (cursor != null) {
   cursor.close();
}