手机卫士day12
来源:互联网 发布:中科院自动化所 知乎 编辑:程序博客网 时间:2024/06/04 18:12
day12
- 看门狗 - 看门狗原理介绍 - 创建服务WatchDogService - 设置页面增加启动服务的开关 - 看门狗轮询检测任务栈 打印当前最顶上的activity /** * 看门狗服务 需要权限: android.permission.GET_TASKS * * @author Kevin * */ public class WathDogService extends Service { private boolean isRunning;// 表示线程是否正在运行 private ActivityManager mAM; @Override public IBinder onBind(Intent intent) { return null; } @Override public void onCreate() { super.onCreate(); mAM = (ActivityManager) getSystemService(ACTIVITY_SERVICE); isRunning = true; new Thread() { public void run() { while (isRunning) {// 看门狗每隔100毫秒巡逻一次 List<RunningTaskInfo> runningTasks = mAM.getRunningTasks(1);// 获取正在运行的任务栈 String packageName = runningTasks.get(0).topActivity .getPackageName();// 获取任务栈最上层activity的包名 System.out.println("top Activity=" + packageName); try { Thread.sleep(100); } catch (InterruptedException e) { e.printStackTrace(); } } }; }.start(); } @Override public void onDestroy() { super.onDestroy(); isRunning = false;// 结束线程 } }- 轮询获取最近的task, 如果发现是加锁的,跳EnterPwdActivity if (mDao.find(packageName)) {// 查看当前页面是否在加锁的数据库中 Intent intent = new Intent(WatchDogService.this, EnterPwdActivity.class); intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); intent.putExtra("packageName", packageName); startActivity(intent); } ----------------------------------- /** * 加锁输入密码页面 * * @author Kevin * */ public class EnterPwdActivity extends Activity { private TextView tvName; private ImageView ivIcon; private EditText etPwd; private Button btnOK; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_enter_pwd); tvName = (TextView) findViewById(R.id.tv_name); ivIcon = (ImageView) findViewById(R.id.iv_icon); etPwd = (EditText) findViewById(R.id.et_pwd); btnOK = (Button) findViewById(R.id.btn_ok); Intent intent = getIntent(); String packageName = intent.getStringExtra("packageName"); PackageManager pm = getPackageManager(); try { ApplicationInfo info = pm.getApplicationInfo(packageName, 0);// 根据包名获取应用信息 Drawable icon = info.loadIcon(pm);// 加载应用图标 ivIcon.setImageDrawable(icon); String name = info.loadLabel(pm).toString();// 加载应用名称 tvName.setText(name); } catch (NameNotFoundException e) { e.printStackTrace(); } btnOK.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { String pwd = etPwd.getText().toString().trim(); if (!TextUtils.isEmpty(pwd)) {// 密码校验 if (pwd.equals("123")) { finish(); } else { Toast.makeText(EnterPwdActivity.this, "密码错误", Toast.LENGTH_LONG).show(); } } else { Toast.makeText(EnterPwdActivity.this, "请输入密码", Toast.LENGTH_LONG).show(); } } }); } }- 重写返回事件,跳转到主页面 //查看系统Launcher源码,确定跳转逻辑 @Override public void onBackPressed() { // 跳转主页面 Intent intent = new Intent(); intent.setAction(Intent.ACTION_MAIN); intent.addCategory(Intent.CATEGORY_HOME); startActivity(intent); finish();//销毁当前页面 }- 发送广播,看门狗跳过检测 认证成功后,发送广播 EnterPwdActivity.java // 发送广播,通知看门狗不要再拦截当前应用 Intent intent = new Intent(); intent.setAction("com.itheima.mobilesafeteach.ACTION_STOP_PROTECT"); intent.putExtra("packageName", packageName); sendBroadcast(intent); ------------------------------------------- WatchDogService.java class InnerReceiver extends BroadcastReceiver { @Override public void onReceive(Context context, Intent intent) { // 看门狗得到了消息,临时的停止对某个应用程序的保护 mSkipPackageName = intent.getStringExtra("packageName"); } } if (packageName.equals(mSkipPackageName)) {// 用过已经认证通过了,需跳过验证 System.out.println("无需验证..."); continue; }- 相关优化 知识拓展:看门狗后台一直在运行,这样是比较耗电的。 我们要优化的的话怎么做呢? 在看门狗服务里,监听锁屏事件,如果锁屏了我就把看门狗停止(flag = false;);屏幕开启了,我就让看门狗开始工作启动服务并且flag = true;; 避免一次输入密码了不再输入;防止别人在我使用的时候,接着使用不用输入密码的情形; 也可以在锁屏的时候把mSkipPackageName赋值为空就行了。- 利用activity启动模式修复密码输入bug 1. 演示bug(进入手机卫士,按home退到后台,然后再打开加锁app,进入后发现跳转到手机卫士页面) 2. 画图分析,正常情况下的任务栈和bug时的任务栈图; 3. 解决问题;在功能清单文件EnterPwdActivity加上字段 <activity android:name="com.itheima.mobilesafe.EnterPwdActivity" android:launchMode="singleInstance"/> 4. 然后再画图分析正确的任务栈;- 隐藏最近打开的activity 长按小房子键:弹出历史记录页面,就会列出最近打开的Activity; 1. 演示由于最近打开的Activity导致的Bug; 2. 容易暴露用户的隐私 最近打开的Activity,是为了用户可以很快打开最近打开的应用而设计的;2.2、2.3普及后就把问题暴露出来了,很容易暴露用户的隐私。比如你玩一些日本开发的游戏:吹裙子、扒衣服这类游戏。你正在玩这些有些,这个时候,爸妈或者大学女辅导员过来了,赶紧按小房子,打开背单词的应用,这时大学女辅导员走过来说,干嘛呢,把手机交出来,长按一下小房子键,这个时候很尴尬的事情就产生了。 A:低版本是无法移除的。低版本记录最近8个;想要隐藏隐私,打开多个挤出去; B:4.0以后高版本就可以直接移除了。考虑用户呼声比较高。 3. 设置不在最近任务列表显示activity <activity android:excludeFromRecents="true" android:name="com.itheima.mobilesafe.EnterPwdActivity" android:launchMode="singleInstance" /> 4. 在装有腾讯管家的模拟器演示腾讯管理的程序锁功能;也没用现实最近的Activity,它也是这样做的。 知识拓展,以后开发带有隐私的软件,或者软件名称不好听的应用,就可以加载在最近打开列表不包括字段.- 腾讯管家和手机卫士同时加锁,谁更快? 腾讯管家会更快一些, 所以需要再进一步优化- 提高性能 - 缩短每次巡逻时间 //将100改为20 try { Thread.sleep(20); } catch (InterruptedException e) { e.printStackTrace(); } - 不频繁调用数据库 从数据库中读取所有已加锁应用列表,每次从集合中查询判断 mLockedPackages = mDao.getInstance(this).findAll();// 查询所有已加锁的应用列表 // if (mDao.find(packageName)) {// 查看当前页面是否在加锁的数据库中 if (mLockedPackages.contains(packageName)) {} - 重新和腾讯管家比拼速度 - 监听数据库变化, 更新集合 - 增加另外一款软件进入程序锁。打开看看,是无法打开输入密码页面的;解析原因; 这个时候就需要根据数据库的数据变化而改变集合的信息了,就用到了观察者; - 联想监听来电拦截时,监听通话日志变化的逻辑,解释原理 - 具体实现 AppLockDao.java // 数据库改变后发送通知 mContext.getContentResolver().notifyChange( Uri.parse("content://com.itheima.mobilesafe/applockdb"), null); ------------------------------------- WatchDogService.java // 监听程序锁数据库内容变化 mObserver = new MyContentObserver(new Handler()); getContentResolver().registerContentObserver( Uri.parse("content://com.itheima.mobilesafe/applockdb"), true, mObserver); getContentResolver().unregisterContentObserver(mObserver);// 注销观察者 class MyContentObserver extends ContentObserver { public MyContentObserver(Handler handler) { super(handler); } @Override public void onChange(boolean selfChange) { System.out.println("数据变化了..."); mLockedPackages = mDao.findAll();// 查询所有已加锁的应用列表 } }
- 手机杀毒
- 什么是病毒?
计算机病毒是一个程序,一段可执行码。就像生物病毒一样,具有自我繁殖、互相传染以及激活再生等生物病毒特征。计算机病毒有独特的复制能力,它们能够快速蔓延,又常常难以根除。它们能把自身附着在各种类型的文件上,当文件被复制或从一个用户传送到另一个用户时,它们就随同文件一起蔓延开来。- 计算机第一个病毒 诞生于麻省理工大学- 蠕虫病毒 熊猫烧香,蠕虫病毒的一种,感染电脑上的很多文件;exe文件被感染,html文件被感染。 主要目的:证明技术有多牛。写这种病毒的人越来越少了- 木马 盗窃信息,盗号、窃取隐私、偷钱,玩了一个游戏,买了很多装备,监听你的键盘输入,下次进入的话,装备全部没了。 主要目目的:挣钱,产生利益;- 灰鸽子 主要特征,控制别人电脑,为我所有。比如挖金矿游戏挣钱的,控制几十万台机器为你干活。 总会比银河处理器快的多。 特点是:不知情情况下安装下的。- 所有的病毒,都是执行后才有危害,如果病毒下载了,没有安装运行,是没有危害的。 - 杀毒原理介绍 定位出特殊的程序,把程序的文件给删除。 王江民, 江民杀毒软件 Kv300 Kv300 干掉300个病毒 开发kv300后很多人用盗版的。 江民炸弹- 病毒怎么找到?-收集病毒的样本 电信 网络运营商主节点 部署服务器集群(蜜罐) 一组没有防火墙 没有安全软件 没有补丁的服务器, 主动联网,下载一些软件运行。这样情况下,特别容易中病毒。 工作原理相当于:苍蝇纸- 360互联网云安全计划 所有的用户都是你的蜜罐; 收集的数据量就大大提高了; 国内安全厂商,有些没有职业道德。 收集一些个人隐私,或者商业机密的文件也收集过去 3Q大战- 传统杀毒软件的缺陷 目前卡巴斯基病毒库已经有了2千多万病毒 传统杀毒软件的缺陷: 病毒数据库越来越大; 只能查杀已知的病毒,不能查杀未知病毒; 360免杀 写了一个木马,在加一个壳,加壳后360就识别不了了- 主动防御 检查软件 1.检查开机启动项 2.检查注册表; 3.检查进程列表 病毒特征: 1、开启启动 2、隐藏自身 3、监视键盘 4、联网发邮件 启发式扫描-扫描单个文件 拷贝文件到虚拟机-相当于精简版的系统, 运行后检测是否具备病毒特点- 杀毒引擎 优化后的数据库查询算法,优先扫描当下最常见的病毒, 速度快- Android上的杀毒软件 大多数停留在基于数据库方式杀毒 LBE主动防御方式杀毒。敏感权限扫描,敏感操作提示,和小米深度合作 金山手机卫士病毒库
手机杀毒模块开发
- 创建AntiVirusActivity
布局文件开发
<LinearLayoutandroid:layout_width="match_parent"android:layout_height="wrap_content"android:orientation="horizontal"android:padding="10dp" ><FrameLayout android:layout_width="80dp" android:layout_height="80dp" > <ImageView android:id="@+id/imageView1" android:layout_width="match_parent" android:layout_height="match_parent" android:src="@drawable/ic_scanner_malware" /> <ImageView android:id="@+id/iv_scanning" android:layout_width="match_parent" android:layout_height="match_parent" android:src="@drawable/act_scanning_03" /></FrameLayout><LinearLayout android:layout_width="match_parent" android:layout_height="match_parent" android:gravity="center" android:orientation="vertical" > <TextView android:id="@+id/tv_scan_status" android:layout_width="wrap_content" android:layout_height="wrap_content" android:singleLine="true" android:text="正在初始化8核杀毒引擎" android:textColor="#000" android:textSize="18sp" /> <ProgressBar android:id="@+id/progressBar1" style="?android:attr/progressBarStyleHorizontal" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginLeft="10dp" android:layout_marginRight="10dp" /></LinearLayout>
扫描动画
RotateAnimation anim = new RotateAnimation(0, 360, Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF, 0.5f);anim.setDuration(1000);//间隔时间anim.setRepeatCount(Animation.INFINITE);//无限循环anim.setInterpolator(new LinearInterpolator());//匀速循环,不停顿ivScanning.startAnimation(anim);
自定义进度条样式
1. 查看android系统对Progressbar样式的定义开发环境\platforms\android-16\data\res\values\styles.xml,搜索Widget.Holo.ProgressBar.Horizontal->progress_horizontal_holo_light2. 拷贝xml文件,修改成自己的图片<layer-list xmlns:android="http://schemas.android.com/apk/res/android" > <item android:id="@android:id/background" android:drawable="@drawable/security_progress_bg"/> <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>3. 将xml文件设置给Progressbar<ProgressBar android:id="@+id/progressBar1" style="?android:attr/progressBarStyleHorizontal" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginLeft="10dp" android:layout_marginRight="10dp" android:progress="50" android:layout_marginTop="5dp" android:progressDrawable="@drawable/custom_progress" />4. 进度更新 // 更新进度条 new Thread() { public void run() { pbProgress.setMax(100); for (int i = 0; i <= 100; i++) { pbProgress.setProgress(i); try { Thread.sleep(30); } catch (InterruptedException e) { e.printStackTrace(); } } }; }.start();
获取系统安装包的MD5
PackageManager pm = getPackageManager();// 获取所有已安装/未安装的包的安装包信息// GET_UNINSTALLED_PACKAGES代表已删除,但还有安装目录的List<PackageInfo> packages = pm .getInstalledPackages(PackageManager.GET_UNINSTALLED_PACKAGES);for (PackageInfo packageInfo : packages) { //apk安装路径 String apkPath = packageInfo.applicationInfo.sourceDir; //计算apk的md5 String md5 = MD5Utils.getFileMd5(apkPath);}-------------------------------------------------/** * 获取某个文件的md5 * @param path * @return */public static String getFileMd5(String path) { try { MessageDigest digest = MessageDigest.getInstance("MD5"); FileInputStream in = new FileInputStream(path); int len = 0; byte[] buffer = new byte[1024]; while ((len = in.read(buffer)) != -1) { digest.update(buffer, 0, len); } byte[] result = digest.digest(); StringBuffer sb = new StringBuffer(); for (byte b : result) { int i = b & 0xff;// 将字节转为整数 String hexString = Integer.toHexString(i);// 将整数转为16进制 if (hexString.length() == 1) { hexString = "0" + hexString;// 如果长度等于1, 加0补位 } sb.append(hexString); } System.out.println(sb.toString());// 打印得到的md5 return sb.toString(); } catch (Exception e) { e.printStackTrace(); } return "";}
扫描病毒数据库
AntiVirusDao.java/** * 病毒数据库的封装 * * @author Kevin * */public class AntiVirusDao { public static final String PATH = "data/data/com.itheima.mobilesafeteach/files/antivirus.db"; /** * 根据签名的md5判断是否是病毒 * * @param md5 * @return 返回病毒描述,如果不是病毒,返回null */ public static String isVirus(String md5) { SQLiteDatabase db = SQLiteDatabase.openDatabase(PATH, null, SQLiteDatabase.OPEN_READONLY); Cursor cursor = db.rawQuery("select desc from datable where md5=? ", new String[] { md5 }); String desc = null; if (cursor.moveToFirst()) { desc = cursor.getString(0); } cursor.close(); db.close(); return desc; }}
扫描安装包并更新进度条
int progress = 0;Random random = new Random();for (PackageInfo packageInfo : packages) { String name = packageInfo.applicationInfo.loadLabel(pm) .toString(); String apkPath = packageInfo.applicationInfo.sourceDir; String md5 = MD5Utils.getFileMd5(apkPath); String desc = AntiVirusDao.isVirus(md5); if (desc != null) { // 是病毒 System.out.println("是病毒...."); } else { // 不是病毒 System.out.println("不是病毒...."); } progress++; pbProgress.setProgress(progress); try { Thread.sleep(50 + random.nextInt(50));//随机休眠一段时间 } catch (InterruptedException e) { e.printStackTrace(); }}
扫描过程中,更新扫描状态文字
- 扫描前,强制休眠2秒,展示"正在初始化8核杀毒引擎"- 使用handler发送消息,更新TextView为:正在扫描:应用名称- 扫描结束后, 发送消息,更新TextView为:扫描完毕- 扫描结束后,关闭扫描的动画
扫描过程中,更新扫描文件列表
- 布局文件中添加空的LinearLayout(竖直方向),动态给线性布局添加TextView- 使用ScrollView包裹线性布局,保证可以上下滑动 <ScrollView android:layout_width="match_parent" android:layout_height="match_parent" > <LinearLayout android:id="@+id/ll_scanning" android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="vertical" > </LinearLayout> </ScrollView>- 如果发现是病毒, TextView需要展示为红色, 为了区分是不是病毒,可以把扫描的文件封装成一个对象ScanInfo class ScanInfo { public String packageName; public String desc; public String name; public boolean isVirus; } private Handler mHandler = new Handler() { public void handleMessage(android.os.Message msg) { switch (msg.what) { case SCANNING: ScanInfo info = (ScanInfo) msg.obj; tvScanStatus.setText("正在扫描:" + info.name); TextView tvScan = new TextView(AntiVirusActivity.this); if (info.isVirus) { tvScan.setText("发现病毒:" + info.name); tvScan.setTextColor(Color.RED); } else { tvScan.setText("扫描安全:" + info.name); } llScanning.addView(tvScan); break; case SCANNING_FINISHED: tvScanStatus.setText("扫描完毕"); ivScanning.clearAnimation();// 清除扫描的动画 break; default: break; } }; };
制作病毒
制作两个apk文件,并将这两个apk文件的md5加入到病毒数据库中,这样的话就可以测试扫出病毒的情况了注意: 将原来的antivirus.db替换为新的文件后,一定要把app的数据清除后再运行,重新进行拷贝数据库的操作, 否则app仍找的是data/data目录下的旧版数据库!
创建病毒集合
发现病毒后,提示用户删除病毒
if (mVirusList.isEmpty()) { Toast.makeText(getApplicationContext(), "你的手机很安全了,继续加油哦!", Toast.LENGTH_SHORT).show();} else { showAlertDialog();}----------------------------/** * 发现病毒后,弹出警告弹窗 */protected void showAlertDialog() { AlertDialog.Builder builder = new AlertDialog.Builder(this); builder.setTitle("警告!"); builder.setMessage("发现" + mVirusList.size() + "个病毒, 非常危险,赶紧清理!"); builder.setPositiveButton("立即清理", new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { for (ScanInfo info : mVirusList) { // 卸载apk Intent intent = new Intent(Intent.ACTION_DELETE); intent.setData(Uri.parse("package:" + info.packageName)); startActivity(intent); } } }); builder.setNegativeButton("下次再说", null); AlertDialog dialog = builder.create(); dialog.setCanceledOnTouchOutside(false);// 点击弹窗外面,弹窗不消失 dialog.show();}
处理横竖屏切换
fn+ctrl+f11 切换模拟器横竖屏后, Activity的onCreate方法会从新走一次, 可以通过清单文件配置,Activity强制显示竖屏<activity android:name=".activity.AntiVirusActivity" android:screenOrientation="portrait" />或者, 可以显示横屏, 通过此配置可以不重新创建Activity<activity android:name=".activity.AntiVirusActivity" android:configChanges="orientation|screenSize|keyboardHidden" />
0 0
- 手机卫士day12
- 手机卫士
- android项目-手机卫士
- Android实战--手机卫士
- 手机卫士 第三天
- 手机卫士 第十天
- Android手机卫士
- 手机卫士 自定义土司
- 手机卫士-01
- 手机卫士-02
- 手机卫士-03
- 手机卫士-04
- 手机卫士-05
- 手机卫士-06
- 手机卫士-07
- 手机卫士-08
- 手机卫士-09
- 手机卫士-10
- c-function
- 手机卫士day11
- 卷积神经网络入门学
- Python学习记录02 列表添加和删除元素
- 开源的监控系统
- 手机卫士day12
- Column name pattern can not be NULL or empty
- MySQL 的原生 JSON 操作
- Android Things SDK用法之UART篇
- 虚拟机安装spark配置推荐
- 内存优化
- 初学ES6(一) let和const
- TextView 最多显示2行,每行最多8个字,多余的显示....
- mysql ERROR 2027 (HY000): Malformed packet