学习到的内容:
1)抽屉原理
2)手机杀毒的原理
3)杀毒UI界面实现【挺有意思的】
4)利用反射获取应用程序缓存和应用程序大小
5)清理缓存
整个项目源代码:http://download.csdn.net/detail/itjavawfc/8383617
部分UI界面如下:
系统中获取各个应用程序流量的API方法:
public class TrafficManagerActivity extends Activity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); //1.获取一个包管理器 PackageManager pm=getPackageManager(); //2.遍历手机系统 获取所有的应用程序UID List<ApplicationInfo> applicationInfos=pm.getInstalledApplications(0); for(ApplicationInfo applicationInfo:applicationInfos){ int uid=applicationInfo.uid; long tx=TrafficStats.getUidTxBytes(uid);//发送上传的流量 long rx=TrafficStats.getUidRxBytes(uid);//下载的流量Byte } TrafficStats.getMobileRxBytes(); //手机2g、3g网络下载流量综合 TrafficStats.getMobileTxBytes(); //手机2g、3g网络上传流量综合 TrafficStats.getTotalTxBytes(); //手机全部网络接口 包括wifi,3g、2g网络上传流量综合 TrafficStats.getTotalTxBytes(); //手机全部网络接口 包括wifi,3g、2g网络下载流量综 setContentView(R.layout.activity_traffic_manage); } }
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" > <SlidingDrawer android:orientation="horizontal" android:id="@+id/my_drawer" android:layout_width="fill_parent" android:layout_height="fill_parent" android:content="@+id/my_content" android:handle="@+id/my_handle" > <LinearLayout android:id="@id/my_handle" android:layout_width="wrap_content" android:orientation="vertical" android:layout_height="fill_parent" > <!-- 把手布局 --> <ImageView android:layout_width="wrap_content" android:layout_height="wrap_content" android:src="@drawable/lock" /> </LinearLayout> <!-- 内容布局 --> <LinearLayout android:background="#22000000" android:id="@id/my_content" android:layout_width="fill_parent" android:layout_height="fill_parent" android:gravity="center" > <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="我是抽屉里面的内容" /> </LinearLayout> </SlidingDrawer> </LinearLayout>
手机杀毒原理:
传统杀毒软件的工作原理:
扫描硬盘上的每个文件,分析这些文件特征码,
查看病毒文件的特征是否在病毒数据库存在。
校验文件的md5 sha1签名。
算法提权软件的关键信息。
遍历文件里面的字符串。http://
手机杀毒的步骤:1.获取每个程序的sha1或者md5码
2.看数据库、云服务存储服务病毒库中有没有该md5码
给一个文件名,获得md5码
<strong> * 获取文件SHA1的值</strong> * @param path 文件的全路径 */ private String getFileSHA(String path){ //获取一个文件的特征信息,签名信息 File file=new File(path); //md5 try { // 拿到一个sha1转换器(同样,这里可以换成MD5) MessageDigest digest=MessageDigest.getInstance("sha1"); FileInputStream fis=new FileInputStream(file); byte[] buffer=new byte[1024]; int len=-1; // read的过程中进行sha1处理,直到读完文件 while((len=fis.read(buffer))!=-1){ digest.update(buffer, 0, len); } byte[] result=digest.digest(); StringBuffer sb=new StringBuffer(); for(byte b:result){ //与运算 int number=b & 0xff; //加盐 String str=Integer.toHexString(number); if(str.length()==1){ sb.append("0"); } sb.append(str); } return sb.toString(); } catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); return ""; } }
扫描病毒的方法:这里面用到了内部类、Handler、Message【非常重要】、仿照源码的一个进度条
/* * 扫描病毒 */ private void scanVirus() { pm=getPackageManager(); tv_scan_status.setText("正在初始化杀毒引擎....."); new Thread(){ public void run(){ List<PackageInfo> infos=pm.getInstalledPackages(0); try { Thread.sleep(500); } catch (InterruptedException e1) { // TODO Auto-generated catch block e1.printStackTrace(); } progressBar1.setMax(infos.size()); int progress=0; for(PackageInfo info:infos){ //apk文件的完整的路径 String sourcedir=info.applicationInfo.sourceDir; //得到.apk文件的sha1签名 String sha1=getFileSHA(sourcedir); ScanInfo scaninfo=new ScanInfo(); scaninfo.name=info.applicationInfo.loadLabel(pm).toString(); scaninfo.packname=info.packageName; //查询md5信息,是否在病毒数据库里面存着 if(AntivirsuDao.isVirus(sha1)){ //发现病毒 scaninfo.isvirus=true; }else{ //扫描安全 scaninfo.isvirus=false; } Message msg=Message.obtain(); msg.obj=scaninfo; msg.what=SCANING; handler.sendMessage(msg); try { Thread.sleep(300); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } progress++; progressBar1.setProgress(progress); } Message msg=Message.obtain(); msg.what=FINISH; handler.sendMessage(msg); } }.start(); }
自定义ProgressBar的实现:style="@style/my_pb_style"
<style name="my_pb_style" parent="@android:style/Widget.ProgressBar.Horizontal"> <item name="android:progressDrawable">@drawable/progress_horizontal</item> </style>
<?xml version="1.0" encoding="utf-8"?> <layer-list xmlns:android="http://schemas.android.com/apk/res/android"> <item android:id="@android:id/background" android:drawable="@drawable/security_progress_bg"> </item> <item android:id="@android:id/secondaryProgress" android:drawable="@drawable/security_progress"> </item> <item android:id="@android:id/progress" android:drawable="@drawable/security_progress"> </item> </layer-list>
/** * 病毒数据库查询业务类 * @author Administrator * */ public class AntivirsuDao { /* * 查询一个md5是否在病毒数据库里面存在 */ public static boolean isVirus(String md5){ String path="/data/data/com.example.mobilesafe/files/antivirus.db"; boolean result = false; //打开病毒数据库文件 SQLiteDatabase db = SQLiteDatabase.openDatabase(path, null, SQLiteDatabase.OPEN_READONLY); Cursor cursor = db.rawQuery("select * from datable where md5=?", new String[]{md5}); if(cursor.moveToNext()){ result = true; } cursor.close(); db.close(); return result; } }
private Handler handler=new Handler(){ @Override public void handleMessage(Message msg) { //super.handleMessage(msg); switch(msg.what){ case SCANING: ScanInfo scanInfo=(ScanInfo) msg.obj; tv_scan_status.setText("正在扫描:"+scanInfo.name); TextView tv=new TextView(getApplicationContext()); if(scanInfo.isvirus){ tv.setTextColor(Color.RED); tv.setText("发现病毒:"+scanInfo.name); }else{ tv.setTextColor(Color.BLACK); tv.setText("扫描安全:"+scanInfo.name); } ll_container.addView(tv,0); //把一个控件上的动画清除掉 iv_scan.clearAnimation(); break; case FINISH: tv_scan_status.setText("扫描完毕"); break; } } };这个方法非常有意思: ll_container.addView(tv,0);
LinearLayout不断的加入:text,而且是一个接着一个加入
定义了一个动画:一直旋转,增强立体感。
RotateAnimation ra=new RotateAnimation(0, 360, Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF, 0.5f); ra.setDuration(1000); ra.setRepeatCount(Animation.INFINITE); iv_scan.startAnimation(ra); progressBar1=(ProgressBar) findViewById(R.id.progressBar1);
缓存清理:做了两方面内容,1扫描缓存区的所有内容 2.清除所有缓存【按照源码,一步一来写下来】
注意项:1.使用到了AIDL
2.获得缓存相关信息必须通过反射强制得到相关的方法后执行【回顾反射机制,反射执行原理】
3.内部类使用的局部变量必须声明为final型
4.单个程序的缓存是无法清除的,只有系统自己才有这个权限,就算加了权限仍然不可用:【实现清除缓存原理是:利用Android内存漏洞,设置其缓存已全部用完,系统就会执行清除所有缓存的操作】
<uses-permission android:name="android.permission.DELETE_CACHE_FILES"/>
代码如下:
public class CleanCacheActivity extends Activity { private ProgressBar pb; private TextView tv_scan_status; private PackageManager pm; private LinearLayout ll_container; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_clean_cache); pb=(ProgressBar) findViewById(R.id.pb); tv_scan_status=(TextView) findViewById(R.id.tv_scan_status); ll_container=(LinearLayout) findViewById(R.id.ll_container); scanCache(); } private void scanCache() { pm=getPackageManager(); new Thread(){ public void run(){ Method[] methods=PackageManager.class.getMethods(); Method getPackageSizeInfoMethod = null; for(Method method:methods){ if("getPackageSizeInfo".equals(method.getName())){ getPackageSizeInfoMethod=method; } } List<PackageInfo> packInfos=pm.getInstalledPackages(0); pb.setMax(packInfos.size()); int progress=0; for(PackageInfo packInfo:packInfos){ try { getPackageSizeInfoMethod.invoke(pm, packInfo.packageName,new MyDataObserver()); Thread.sleep(50); } catch (Exception e) { e.printStackTrace(); } progress++; pb.setProgress(progress); } runOnUiThread(new Runnable(){ @Override public void run() { tv_scan_status.setText("扫描完毕....."); } }); }; }.start(); } private class MyDataObserver extends IPackageStatsObserver.Stub{ @Override public void onGetStatsCompleted(PackageStats pStats, boolean succeeded) throws RemoteException { final long cache=pStats.cacheSize; final long code=pStats.codeSize; final long data=pStats.dataSize; final String packname=pStats.packageName; final ApplicationInfo appInfo; try { appInfo=pm.getApplicationInfo(packname, 0); runOnUiThread(new Runnable(){ public void run() { //SmartcardService tv_scan_status.setText("正在扫描:"+appInfo.loadLabel(pm)); if(appInfo.loadLabel(pm).equals("SmartcardService")){ tv_scan_status.setText("扫描完毕....."); } if(cache>0){ View view=View.inflate(getApplicationContext(),R.layout.list_item_cacheinfo,null); TextView tv_cache=(TextView) view.findViewById(R.id.tv_cache_size); tv_cache.setText("缓存大小:"+Formatter.formatFileSize(getApplicationContext(), cache)); TextView tv_name=(TextView) view.findViewById(R.id.tv_app_name); tv_name.setText(appInfo.loadLabel(pm)); //清理全部缓存 ImageView iv_delete=(ImageView) view.findViewById(R.id.iv_delete); iv_delete.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { try { //拿到方法的字节码 Method method=PackageManager.class.getMethod("deleteApplicationCacheFiles", String.class,IPackageDataObserver.class); method.invoke(pm, packname,new MypackDataObserver()); } catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); } } }); ll_container.addView(view,0); } } }); } catch (Exception e) { e.printStackTrace(); } } } private class MypackDataObserver extends IPackageDataObserver.Stub{ @Override public void onRemoveCompleted(String packageName, boolean succeeded) throws RemoteException { } } /* * 清理手机的全部缓存 * */ public void clearAll(View view){ Method[] methods = PackageManager.class.getMethods(); for(Method method:methods){ if("freeStorageAndNotify".equals(method.getName())){ try { method.invoke(pm, Integer.MAX_VALUE,new MypackDataObserver()); } catch (Exception e) { e.printStackTrace(); } return; } } } }