Android项目实战_手机安全卫士程序锁
###1.两个页面切换的实现
1. 可以使用Fragment,调用FragmentTransaction的hide和show方法
2. 可以使用两个布局,设置visibility的VISIABLE和INVISIABLE
3. 可以使用一套布局,切换不同的显示数据
###2.已加锁、未加锁界面数据的获取思路
1. 获取所有的应用
2. 这些应用只可能是未加锁或者已加锁
3. 根据数据库中存储的已加锁的情况,将所有数据分别装到已加锁和未加锁两个集合中
###3.动画播放需要注意什么
1. 动画的播放是非阻塞式的,相当于开启了一个子线程定期的刷新UI
2. 如果想在动画播完之后执行一些操作,需要设置监听器
ta.setAnimationListener(new AnimationListener() {
@Override
public void onAnimationStart(Animation animation) {
//动画开始播放了。。。
}
@Override
public void onAnimationRepeat(Animation animation) {
//动画重复播放了。
}
@Override
public void onAnimationEnd(Animation animation) {
//动画播放完毕了。
//从当前页面把应用程序条目给移除
unlockPackinfos.remove(position);
unlockItemsAdapter.notifyDataSetChanged();
//把数据加入到已加锁的列表里面
lockedPackinfos.add(packInfo);
lockedItemsAdapter.notifyDataSetChanged();
}
});
###4.程序锁的工作原理
1. 开启一个服务一直去监听最新开启的应用
2. 判断新开启的应用是否是已加锁的应用
3. 如果是已加锁应用,弹出输入密码对话框
4. 获取正在运行的应用,需要权限<uses-permission android:name="android.permission.GET_TASKS"/>
//获取到当前手机的任务栈
List<RunningTaskInfo> infos = am.getRunningTasks(1000);
//获取任务栈最上面的Activity
String packname = infos.get(0).topActivity.getPackageName();
System.out.println("正在运行:"+packname);
###5.非Activity里启动Activity有什么要注意的
需要设置flag————Intent.FLAG_ACTIVITY_NEW_TASK
Intent intent = new Intent(WatchDogService.this,EnterPasswordActivity.class);
intent.putExtra("packname", packname);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(intent);
###6.如何监听返回键,打开桌面
@Override
public void onBackPressed() {
// <action android:name="android.intent.action.MAIN" />
// <category android:name="android.intent.category.HOME" />
// <category android:name="android.intent.category.DEFAULT" />
Intent intent = new Intent();
intent.setAction("android.intent.action.MAIN");
intent.addCategory("android.intent.category.HOME");
intent.addCategory("android.intent.category.DEFAULT");
startActivity(intent);
}
###7.Activity的启动模式
(1)standard:每次激活Activity时(startActivity),都创建Activity实例,并放入任务栈;

(2)singleTop:如果某个Activity自己激活自己,即任务栈栈顶就是该Activity,则不需要创建,其余情况都要创建Activity实例;

(3)singleTask:如果要激活的那个Activity在任务栈中存在该实例,则不需要创建,只需要把此Activity放入栈顶,并把该Activity以上的Activity实例都pop;

(4)singleInstance:会单独创建一个Activity栈;

###8.程序锁的优化
1. 将while循环里每次都创建的变量放到循环外面,只创建一次
//修改前
while(flag){
List<RunningTaskInfo> infos = am.getRunningTasks(1000);
String packname = infos.get(0).topActivity.getPackageName();
//修改后
List<RunningTaskInfo> infos;
String packname;
while(flag){
infos = am.getRunningTasks(1000);
packname = infos.get(0).topActivity.getPackageName();
2. 获取正在运行的应用时,只需要获取到第一个就可以了,将集合大小设置为1
//修改前
infos = am.getRunningTasks(1000);
//修改后
infos = am.getRunningTasks(1);
3. 每次都查询数据库比较耗时,将数据库的内容都查询出来,放到一个集合里,以后查询的时候就去查询内存中的集合数据
//修改前
if(dao.find(packname)){//每次都查询数据库
//修改后
1.在ApplockDao中添加一个查询所有已加锁应用的方法
public List<String> findAll() {
List<String> lockedPacknames = new ArrayList<String>();
SQLiteDatabase db = helper.getReadableDatabase();
Cursor cursor = db.rawQuery("select packname from lockinfo", null);
while (cursor.moveToNext()) {
lockedPacknames.add(cursor.getString(0));
}
cursor.close();
db.close();
return lockedPacknames;
}
2.声明一个成员变量,onCreate方法中将所有数据查询出来
private List<String> lockedPacknames;
@Override
public void onCreate() {
...
...
//获取的是数据库锁定的全部的包名
lockedPacknames = dao.findAll();
...
...
}
3.查询的时候直接去查询内存中的数据
if(lockedPacknames.contains(packname)){//查询内存
###9. 如何利用内容观察者同步数据库变化
1. 在AppLockDao中的add和delete方法中,加入修改数据库的通知
//添加或删除一条记录
Uri uri = Uri.parse("content://com.hb.mobilesafe.applockdb");
context.getContentResolver().notifyChange(uri, null);
2. 在WatchDogService中注册内容观察者
//注册内容观察者观察数据库内容的变化
Uri uri = Uri.parse("content://com.hb.mobilesafe.applockdb");
observer = new MyObserver(new Handler());
getContentResolver().registerContentObserver(uri, true, observer);
//内容观察者
private class MyObserver extends ContentObserver{
public MyObserver(Handler handler) {
super(handler);
}
//内容观察者观察到数据变化调用的方法
@Override
public void onChange(boolean selfChange) {
Log.i(TAG,"看门狗里面的内容观察者观察到了数据库变化。。。。");
lockedPacknames = dao.findAll();
super.onChange(selfChange);
}
}
上面的方式在观察到数据库的变化时,又重新查询了所有的数据,还是不够优化,实际上我们在add或者delete时只是对一条数据进行了操作,可以利用uri将add或者delete的数据通知出来
1. 在AppLockDao中的add和delete方法中,加入修改数据库的通知,通知时带出操作和所操作的包名
//添加数据
Uri uri = Uri.parse("content://com.hb.mobilesafe.applockdb?add="+packname);
context.getContentResolver().notifyChange(uri, null);
//删除数据
Uri uri = Uri.parse("content://com.hb.mobilesafe.applockdb?delete="+packname);
context.getContentResolver().notifyChange(uri, null);
2. 在WatchDogService中注册内容观察者,根据不同的uri,做出不同的操作
private class MyObserver extends ContentObserver{
public MyObserver(Handler handler) {
super(handler);
}
@Override
public void onChange(boolean selfChange, Uri uri) {
// TODO Auto-generated method stub
String query = uri.getQuery();
Log.i(TAG, "query--->"+query);
Set<String> names = uri.getQueryParameterNames();
for(String name : names){
Log.i(TAG, "name--->"+name);
List<String> parameters = uri.getQueryParameters(name);
for(String parameter : parameters){
Log.i(TAG, "parameter--->"+parameter);
}
}
super.onChange(selfChange);
}
}
//对应的log
query--->add=com.android.calculator2
name--->add
parameter--->com.android.calculator2
###10. 接收屏幕锁屏和亮起的广播
Intent.ACTION_SCREEN_ON
Intent.ACTION_SCREEN_OFF
package com.hb.mobilesafe.activities; import java.util.ArrayList;
import java.util.List; import android.app.Activity;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
import android.os.Bundle;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
import android.view.Window;
import android.widget.BaseAdapter;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.ListView;
import android.widget.TextView; import com.hb.demo_mobilesafe.R;
import com.hb.mobilesafe.bean.ApplockInfo;
import com.hb.mobilesafe.dbdao.AppLockDao; public class SoftLockActivity extends Activity implements OnClickListener {
private PackageManager pm; private Button bt_unlock;
private Button bt_lock;
private TextView tv_unlocksoft;
private TextView tv_locksoft;
private ListView lv_unlocksoft;
private ListView lv_locksoft; private MylocksoftAdapter unlockadapter;
private MylocksoftAdapter lockadapter; private boolean flags=false;
private List<ApplockInfo> unlockList;
private List<ApplockInfo> lockList; private AppLockDao dao; @Override
protected void onCreate(Bundle savedInstanceState) {
// TODO Auto-generated method stub
super.onCreate(savedInstanceState);
requestWindowFeature(Window.FEATURE_NO_TITLE);
setContentView(R.layout.activity_softlock);
initView();
}
/**
* 找Id
*/
private void initView() {
bt_unlock=(Button) findViewById(R.id.bt_unlock);
bt_lock=(Button) findViewById(R.id.bt_lock);
tv_unlocksoft=(TextView) findViewById(R.id.tv_unlocksoft);
tv_locksoft=(TextView) findViewById(R.id.tv_locksoft);
lv_unlocksoft=(ListView) findViewById(R.id.lv_unlocksoft);
lv_locksoft=(ListView) findViewById(R.id.lv_locksoft);
bt_unlock.setOnClickListener(this);
bt_lock.setOnClickListener(this);
getAllAppInfo();
InitUI(); }
/**
* 初始化界面
*/
private void InitUI() {
tv_locksoft.setVisibility(View.INVISIBLE);
lv_locksoft.setVisibility(View.INVISIBLE); }
/**
* 获取手机上的APP
*/
public void getAllAppInfo(){
pm = getPackageManager();
dao = new AppLockDao(this);
List<String> all = dao.findAll();
System.out.println("all :"+all);
List<ApplicationInfo> appInfo = pm.getInstalledApplications(0);
unlockList = new ArrayList<ApplockInfo>();
lockList = new ArrayList<ApplockInfo>();
for (ApplicationInfo mInfo : appInfo) {
ApplockInfo lockInfo = new ApplockInfo();
lockInfo.setIcon(mInfo.loadIcon(pm));
lockInfo.setAppName(mInfo.loadLabel(pm).toString());
lockInfo.setAppPackageName(mInfo.packageName);
//判断是加锁还是未加锁
if(all.contains(mInfo.packageName)){
lockList.add(lockInfo);
}else{
unlockList.add(lockInfo);
}
if(!flags){
unlockadapter=new MylocksoftAdapter();
lv_unlocksoft.setAdapter(unlockadapter);
}else{
lockadapter = new MylocksoftAdapter();
lv_locksoft.setAdapter(lockadapter); }
}
}
class MylocksoftAdapter extends BaseAdapter{ private ApplockInfo info; @Override
public int getCount() {
if(!flags){
tv_unlocksoft.setText("未加锁程序"+unlockList.size()+"个");
return unlockList.size();
}else{
tv_locksoft.setText("已加锁程序"+lockList.size()+"个");
return lockList.size(); }
}
@Override
public View getView(final int position, View convertView, ViewGroup parent) {
ViewHolder holder=null;
if(convertView != null){
holder = (ViewHolder) convertView.getTag();
}else{
holder=new ViewHolder();
convertView=View.inflate(SoftLockActivity.this, R.layout.unlock_item, null);
holder.iv_appicon =(ImageView) convertView.findViewById(R.id.iv_appicon);
holder.tv_appname= (TextView) convertView.findViewById(R.id.tv_appname);
holder.iv_status=(ImageView) convertView.findViewById(R.id.iv_status);
convertView.setTag(holder);
}
final ApplockInfo info = (ApplockInfo) getItem(position);
holder.iv_appicon.setImageDrawable(info.getIcon());
holder.tv_appname.setText(info.getAppName());
if(!flags){
holder.iv_status.setBackgroundResource(R.drawable.btn_lock_selector);
}else{
holder.iv_status.setBackgroundResource(R.drawable.btn_unlock_selector); } holder.iv_status.setOnClickListener(new OnClickListener() { @Override
public void onClick(View v) {
if(flags){
/**
* 已加锁
*/
new Thread(){
public void run() {
dao.delete(lockList.get(position).getAppPackageName());
unlockList.add(info);
runOnUiThread(new Runnable() {
public void run() {
lockList.remove(info);
tv_locksoft.setText("已加锁程序"+lockList.size()+"个");
lockadapter.notifyDataSetChanged();
}
}); };
}.start();
}else{
/**
* 未加锁
*/
new Thread(){
public void run() {
dao.add(unlockList.get(position).getAppPackageName());
lockList.add(info);
runOnUiThread(new Runnable() {
public void run() {
unlockList.remove(info);
tv_unlocksoft.setText("未加锁程序"+unlockList.size()+"个");
unlockadapter.notifyDataSetChanged();
}
}); };
}.start(); }
}
}); return convertView;
}
@Override
public Object getItem(int position) {
if(!flags){
info = unlockList.get(position);
}else{
info = lockList.get(position);
}
return info;
} @Override
public long getItemId(int position) {
// TODO Auto-generated method stub
return 0;
} }
static class ViewHolder{
ImageView iv_appicon;
TextView tv_appname;
ImageView iv_status;
}
/**
* 已加锁与未加锁的点击事件
*
*/
@Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.bt_unlock:
flags=false;
tv_locksoft.setVisibility(View.INVISIBLE);
lv_locksoft.setVisibility(View.INVISIBLE);
tv_unlocksoft.setVisibility(View.VISIBLE);
lv_unlocksoft.setVisibility(View.VISIBLE);
unlockadapter=new MylocksoftAdapter();
lv_unlocksoft.setAdapter(unlockadapter);
break; case R.id.bt_lock:
flags=true;
tv_unlocksoft.setVisibility(View.INVISIBLE);
lv_unlocksoft.setVisibility(View.INVISIBLE);
tv_locksoft.setVisibility(View.VISIBLE);
lv_locksoft.setVisibility(View.VISIBLE);
lockadapter=new MylocksoftAdapter();
lv_locksoft.setAdapter(lockadapter);
break;
}
} }
xml:
<?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" > <RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#A1FF80" > <TextView
android:id="@+id/tv_title"
android:layout_width="match_parent"
android:layout_height="46dp"
android:layout_marginLeft="5dip"
android:gravity="center_vertical"
android:text="程序锁"
android:textSize="20sp" /> <LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:orientation="horizontal" > <Button
android:id="@+id/bt_unlock"
android:layout_width="wrap_content"
android:layout_height="30dip"
android:background="#5300FF"
android:text="未加锁"
android:textColor="#ffffff" />
<TextView
android:layout_width="1dip"
android:layout_height="30dip"
android:background="#ffffff"
/> <Button
android:id="@+id/bt_lock"
android:layout_width="wrap_content"
android:layout_height="30dip"
android:background="#5f00F0"
android:text="已加锁"
android:textColor="#ffffff" />
</LinearLayout>
</RelativeLayout> <RelativeLayout
android:layout_width="match_parent"
android:layout_height="match_parent" > <TextView
android:id="@+id/tv_locksoft"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="未加锁程序:12个" /> <TextView
android:id="@+id/tv_unlocksoft"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="已加锁程序:5个" /> <ListView
android:id="@+id/lv_locksoft"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_below="@id/tv_locksoft" /> <ListView
android:id="@+id/lv_unlocksoft"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_below="@id/tv_unlocksoft" />
</RelativeLayout> </LinearLayout>
到这里整个项目已接近尾声,但这里也有许多代码没有贴出来如果感兴趣的可以看看笔者的源码:http://pan.baidu.com/s/1i59msz7
Android项目实战_手机安全卫士程序锁的更多相关文章
- Android项目实战_手机安全卫士home界面
# 安全卫士主页面# ###1.GridView控件 1.与ListView的使用方式差不多,也要使用数据适配器,通过设置android:numColumns控制显示几列 2.通过指定android: ...
- Android项目实战_手机安全卫士splash界面
- 根据代码的类型组织包结构 1. 界面 com.hb.mobilesafe.activities 2. 服务 com.hb.mobilesafe.services 3. 业务逻辑 com.hb.mo ...
- Android项目实战_手机安全卫士手机防盗界面
#安全卫士手机防盗# ###1.Activity的任务栈 1.类似一个木桶,每层只能放一个木块,我们放入木块和取出木块的时候只能从最上面开始操作 ###2.Android中的坐标系和android:content(内容),并在子View中添加把手和内容的布局```java <Sli ...
- Android项目实战_手机安全卫士进程管理
###1.设备进程信息获取获取设备运行进程 ActivityManager am = (ActivityManager) context.getSystemService(Context.ACTIVI ...
- Android项目实战--手机卫士开发系列教程
<ignore_js_op> banner131010.jpg (71.4 KB, 下载次数: 0) 下载附件 保存到相册 2 分钟前 上传 Android项目实战--手机卫士01- ...
随机推荐
- HDU 1325 拓扑排序
根据题目所给的3个不符合情况的条件,一个个判断图是否符合这3个条件即可 1.不能出现内部环,拓扑排序判断 2.不能有超过1个点的入度为0,因为只有一个树根 3.每个点最多一个入度 这里要注意的一点是这 ...
- [luoguP3690] 【模板】Link Cut Tree
传送门 处理路径 xor 和的时候可以维护子树 xor 和,先提取出路径,再把一个点 splay 到最上方,直接取子树 xor 和即可. 更新一个点权时可以先提取出根到这个点的路径,把这个点 spla ...
- RxJava如何结合观察者与链式处理
RxJava如何结合观察者与链式处理 Author: Dorae Date: 2018年12月3日17:10:31 转载请注明出处 一.概述 首先问自己几个问题,如果非常清楚这几个问题的目的与答案,那 ...
- Ubuntu 16.04安装Kdbg替代Insight实现汇编的调试
Insight已经不能使用APT进行安装,且如果使用源码安装时需要修改.所以只能放弃,转投使用Kdbg. 安装: sudo apt-get install kdbg 使用: nasm -f elf64 ...
- 【CV论文阅读】Faster R-CNN: Towards Real-Time Object Detection with Region Proposal Networks
由RCNN到FAST RCNN一个很重要的进步是实现了多任务的训练,但是仍然使用Selective Search算法来获得ROI,而FASTER RCNN就是把获得ROI的步骤使用一个深度网络RPN来 ...
- Linux中W与Who命令的使用
踢掉一个从某个终端连上的用户pkill -kill -t pts/0 ---------------------------------------------------------------- ...
- CoreData使用方法三: NSPredicate在CoreData中的使用
NSPredicate在CoreData中经常使用作查询使用,相当于sql语句中的where查询子句. 最经常使用的方法为: NSPredicate *ca = [NSPredicate predic ...
- wpf slider进度条的样式模板,带有进度颜色显示
效果图: 仅仅需在前台加上这段代码就可以: <UserControl.Resources> <!--笔刷--> <LinearGradientBrush x:Key=&q ...
- jqury+css实现可弹出伸缩层
1.使用可弹出伸缩窗调整了之前的页面布局,使用这样的布局使整个界面看起来更加清爽也更简洁 watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQv/font/5a6L ...
- about service in android
注意:标红处! A Service is an application component representing either an application's desire to perform ...