功能 | 实现思路 | 注意事项 |
看门狗 应用程序的监听测试 用户正在使用的程序 是否被加锁 要求密码解锁
| 1.创建Service 2.使用Thread+ActivityManager 3.TaskStack 管理Actvity的集合 4.Sqlite+Dao:判断程序是否被加锁 5.Activity创建密码输入界面 6.sendBroadcast发送给后台 7.注册BroadcastReciever Intent
| 1.一遍 x1 2.二遍 综合点多 a.归属地显示 b.通讯卫士 c.看门狗 (国庆) 优化: 1.内存>io 要求同步 ContentObserver内容观察者 数据库专用的监测数据变化持技术 2.电量:BoradcastReceve监听SCREEN_OFF SCAENN_ON BUG: 1.launchMode创建一个新栈显示在被程序之上singleInstacne 2.返回路径 隐式意图的调用 action category data
|
手机杀毒 查找 有恶意的程序 删除 | 1.Activity创建查杀界面 布局 2.RoateAnimation startAnimation 3.Thread_handler更新AsyncTask 4.LayerList:以叠加方式管理素材的对象 修改progressBar外观 5.PackageManager获取所有apk( ApkUtils) 6.文件md5值 7.导入病毒库 8.调用sqlite 查找desc 9.做好逻辑提示 10.LinearLayout addView
| 实现多个行有两种方式 ListView+List Linearlayout addView |
1. 昨日复习
功能/知识点 | 概念 含义 思路 | 注意事项 |
Apppwidget 生命周期 | 创建开始 销毁结束,有序的方法 on | 优化timer+servcie |
网易 多种格式appwidget | 配置多个reciever 公式 70xn -30 |
|
短信的备份与还原 帮助用户找回短信 | 1.获取短信集合 2.生成xml XmlSerilizer序列化器 3.PullParser 解析标签 | Uri: 访问地址 ContentResolver:内容解析者 ContentProvider:内容提供者 Cursor:游标 多条数据记录的集合 |
监听器: 获取参数 | 入门 :控件+监听器 创建监听器:1.代码抽取 2.接口: 3.内部对监听器进行传值 | 1.interface 2.On...Listener 3.on.. 4.setOn..Listener |
AsyncTask | Thread+Handler 比方:洗衣服 任务开始:onPreexecute();初始化 任务中:doInbackground();耗时代码 不能更新ui publishProgress提交参数给界面 onProgressUpdate:更新界面 任务后:onPostExecute();显示数据 | 一定要调用execute(); Thread_start(); |
程序锁: 1.小孩子 2.隐私 | 1.名单 2.后台监控程序:看门
FragmentAcvity:Fragment的集合 Fragmetnmanager:管理者打开事务 FragmentTransaction:事务 begine commit | Fragment:类似Activity 比Activity更灵活 a.继承 Fragmnet b.重写 oncreateView c.显示 <fragment 当作控件 d.代码: 事务当作集合
已经安装应用程序集合获取 PackasgeManager TranslateAnimation移动动画 加锁:表中添加记录 解锁: 表中删除记录 |
1.1. 短信加密码
项目中:支付软件
RSA DES AES
U2FsdGVkX1+CqoYP1mOINn7xMqGxtLfrkCaeJyO0lZ4=
U2FsdGVkX19UfInFcEOeo/fx+vKkx2VxsxqhtKzE/gU=
https://github.com/gfx/Android-EncryptUtils
1.2. 看门狗
后台的监控程序:监控当前屏幕显示的是哪个应用程序
如果程序 是已加锁,要求用户密码解锁程序 。
反之,直接放行。
快播:上几个小时 什么时间比较活跃===》老是睡觉
① 创建Service a.继承 b.重写 c. 配置 d.启动
② 编写监测Activity工具
Stack | 集合 先进后出 吃了吐出 |
TaskStack | 管理Activity的Stack 打开一个 Acvivty添加到栈顶 关闭一个activity 将栈顶弹出
|
用户看到一个应用程序 | 包含 activity的任务栈 |
③ 查询数据库
④ 已加锁 弹出密码输入界面Activity a.继承 b.重写 c.配置 d.启动
⑤ 通知看门狗放行 a.密码验证 b.通知看门狗
密码解锁
@OnClick(R.id.unlock)
public void unlock(View view) {
String inputString = et_password.getText().toString();
// 可以参考手机防盗 注册 登录
if ("123".equals(inputString)) {
// 发送广播
Intent intent = new Intent();
intent.putExtra("packagename", packagename);
intent.setAction("itheima.action.Intent.LET_GO");
sendBroadcast(intent);
finish();
} else {
Toast.makeText(getBaseContext(), "密码不对!", 0).show();
}
}
看门狗接收解锁广播
private String letgoPackageName = "";
private BroadcastReceiver receiver = new BroadcastReceiver() {
public void onReceive(android.content.Context context, Intent intent) {
Log.i("wzx", "接收到解锁放行广播 ....." + intent.getAction());
letgoPackageName = intent.getStringExtra("packagename");
};
};
@Override
public void onDestroy() {
super.onDestroy();
isWorking = false;
Log.i("wzx", "WatchDogService----销毁");
unregisterReceiver(receiver);
}
1.3. 优化
① 减少电量: gps 线程1000 SCREEN_OFF SCREEN_ON
用户锁屏 不看应用程序
使用看门狗停止
用户解锁屏幕 打开看门
② 减少io次数:提高访问速度 必须保持 数据库与集合的同步
内存》磁盘 文件或者数据库》网络 (不稳定)
查询所有的加锁程序 放到List
//boolean isLock = dao.hasLock(userApp);//io
boolean isLock = lockAppPackageNames.contains(userApp);//内存
root@vbox86p:/data/data/com.itheima.mobilesafe/databases # ls
ls
address.db
applock.db
applock.db-journal
blacknumbers.db
blacknumbers.db-journal
root@vbox86p:/data/data/com.itheima.mobilesafe/databases # sqlite3 applock.db 打开数据库
sqlite3 applock.db
SQLite version 3.7.11 2012-03-20 11:35:50
Enter ".help" for instructions
Enter SQL statements terminated with a ";"
sqlite> .tables 查看所有表
.tables
android_metadata lockapps
sqlite> select * from lockapps; 执行sql
//------------数据库信号
private ContentObserver observer=new ContentObserver(new Handler()) {
//接收到数据库的修改信号 2.2. 2.3 3.0
//二选 一调用。
public void onChange(boolean selfChange) {
keepSameAsDb();
}
private void keepSameAsDb() {
Log.i("wzx", "接收到修信号");
lockAppPackageNames.clear();
List<String> temp=dao.findAll();
lockAppPackageNames.addAll(temp);
};
//4.0 4.1..
public void onChange(boolean selfChange, android.net.Uri uri) {
keepSameAsDb();
};
};
@Override
public void onDestroy() {
super.onDestroy();
isWorking = false;
Log.i("wzx", "WatchDogService----销毁");
unregisterReceiver(receiver);
getContentResolver().unregisterContentObserver(observer);
}
private List<String> lockAppPackageNames=new ArrayList<String>();
@Override
public void onCreate() {
super.onCreate();
Uri uri=Uri.parse("content://"+AppLockDao.class.getName());
//content://com.itheima.change
//content://com.itheima.change/1 子路径
//getContentResolver().registerContentObserver(uri, 是否对子路径有效, observer);
1.4. 修改BUG
BUG1:解锁后界面不对
<!-- 密码输入界面 -->
<activity android:name="com.itheima.mobilesafe.act.PasswordEnterActivity"
android:launchMode="singleInstance" />
launchMode:启动模式,就是 Activity响应startActivity的方式
standard 默认 | 一个命令一个实例 |
singleTop | ”检测栈顶“ 1.如果不是自己 创建一个实例 2.如果自己在栈顶 不创建实例 |
singleTask | 检测在栈中 不在 创建 在 是栈顶 不创建实例 不是栈顶 弹出自己以上的所有页面 ”霸道“ 例:主页 |
singleInstance | 会创建新的栈 添加页面 输入密码界面 |
BUG2:返回 需要回到桌面
@Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
// TODO Auto-generated method stub
if(keyCode==KeyEvent.KEYCODE_BACK)
{
// <action android:name="android.intent.action.MAIN" />
// <category android:name="android.intent.category.HOME" />
// <category android:name="android.intent.category.DEFAULT" />
// <category android:name="android.intent.category.MONKEY"/>
Intent intent=new Intent();
intent.setAction("android.intent.action.MAIN");
intent.addCategory("android.intent.category.HOME");
intent.addCategory("android.intent.category.DEFAULT");
intent.addCategory("android.intent.category.MONKEY");
startActivity(intent);
return true;
}
return super.onKeyDown(keyCode, event);
}
2. 手机杀毒
DNA:
需求:查找手机中的病毒(有破坏性的程序,盗取信息的程序),进行删除。
2.4w
① 创建Activity a. 继承 b.重写 c.配置 d.启动 布局 ”不要嵌套太多“
② 旋转动画
private void startAnimation() {
// 动画
RotateAnimation anim = new RotateAnimation//
(0, 360, // 角度
RotateAnimation.RELATIVE_TO_SELF, 0.5f,// 宽
RotateAnimation.RELATIVE_TO_SELF, 0.5f);// 高
anim.setDuration(700);// 时长
anim.setRepeatCount(Integer.MAX_VALUE);
act_img.startAnimation(anim);
}
③ ProgressBar自定义外观
selector | 选择器 针对界面的美化 管理素材的对象,根据状态显示 |
layer-list | 图层列表 管理素材的对象,根据叠加顺序显示图片 |
a. 准备图片
b. 创建android xml文件
c. 使用item配置
d. 设置给Progressbar
<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android" >
<!-- a.准备图片 -->
<!-- b.创建android xml文件 -->
<!-- c.使用item配置 -->
<item
android:id="@android:id/background"
android:drawable="@drawable/security_progress_bg">
</item>
<item
android:id="@android:id/progress"
android:drawable="@drawable/security_progress">
</item>
<!-- d.设置给Progressbar -->
</layer-list>
<ProgressBar
android:id="@+id/progress"
style="?android:attr/progressBarStyleHorizontal"
android:progressDrawable="@drawable/progressbar_layerlist" />
④ Activity受屏幕旋转的影响 onCreate
1.竖屏 横屏
<!-- 杀毒 -->
<activity android:name="com.itheima.mobilesafe.act.KillVirusActivity"
android:screenOrientation="portrait" />
<!-- portrait只能竖屏 -->
<!-- landscape只能横屏 -->
<!-- 密码输入界面 -->
2.配置configChanges
<!-- 杀毒 -->
<activity android:name="com.itheima.mobilesafe.act.KillVirusActivity"
android:configChanges="keyboard|keyboardHidden|orientation|screenSize"
/>
⑤ 获取所有apk 的 md5值
MessageDigest | 生成摘要工具 |
|
|
/**
* 获取md5从文件
* @param filePath
* @return
* @throws NoSuchAlgorithmException
* @throws FileNotFoundException
* @throws IOException
*/
public static String getMd5FromFile(String filePath) throws Exception {
// 针对每部分的byte[]
MessageDigest md = MessageDigest.getInstance("MD5");
FileInputStream input = new FileInputStream(new File(filePath));
byte[] buffer = new byte[1024 * 10];
int len = 0;
while ((len = input.read(buffer)) != -1) {
md.update(buffer, 0, len);
}
input.close();
// 合成md5
byte[] bytes = md.digest();// 16汇总 md5 128 bit 1byte=8bit 16byte
// byte-->0x
// 32位
StringBuffer sb = new StringBuffer();
for (byte temp : bytes) {
String hex = Integer.toHexString(temp & 0xff);// 不一定是1byte 变两位
if (hex.length() == 1) {
sb.append("0").append(hex);// 为了达到32 必段填充0
} else {
sb.append(hex);
}
}
String md5 = sb.toString().toLowerCase();
return md5;
}
⑥ 外部数据库(病毒库)
public class VirusDao {
private Context context;
public VirusDao(Context context) {
super();
this.context = context;
}
private String virusDb = Environment.getExternalStorageDirectory().getAbsolutePath() + "/";
/**
* 初始化病毒库
*/
public void initDb() {
try {
InputStream input = context.getAssets().open("antivirus.db");
FileUtils.copyFile(input, virusDb, "antivirus.db");
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
/**
* 判断是否是病毒
* @param md5
* @return
*/
public String findDesc(String md5) {
String desc = null;
// 病毒
String sql = "select desc from datable where md5=?;";
// SQLiteDatabase db=SQLiteDatabase.openDatabase(外部数据库路径 , 游标工厂, 打开方式 只读
// 读写);
SQLiteDatabase db = SQLiteDatabase.openDatabase(virusDb + "/antivirus.db", null, SQLiteDatabase.OPEN_READWRITE);
Cursor cursor = db.rawQuery(sql, new String[] { md5 });
if (cursor.moveToNext())// 游标的默认不在第一行
{
desc = cursor.getString(cursor.getColumnIndex("desc"));
}
cursor.close();
db.close();
return desc;
}
}
⑦ 只要存在 就是病毒
QQ与360 360报qq是病毒
// 每个apkmd5摘要
for (ApkInfo info : apklist) {
try {
String md5 = Md5Utils.getMd5FromFile(info.path);
// Log.i("wzx", "应用程序:"+info.appName+" md5:"+md5);
String desc = dao.findDesc(md5);// 查询病毒库
ScanItemResult item=new ScanItemResult();
item.appName=info.appName;
if (desc == null) {
item.desc="正常";
item.isVirus=false;
Log.i("wzx", info.appName + ":正常" + "-" + md5);
} else {
Log.i("wzx", info.appName + ":" + desc + "-" + md5);
item.isVirus=true;
item.desc=desc;
}
++currProgress;//更新进度条
Message msg1=handler.obtainMessage();
msg1.what=1;
msg1.obj=item;
handler.sendMessage(msg1);
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
⑧ 卸载