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实例,并放入任务栈;
![](http://i.imgur.com/64EfO0V.png)
(2)singleTop:如果某个Activity自己激活自己,即任务栈栈顶就是该Activity,则不需要创建,其余情况都要创建Activity实例;
![](http://i.imgur.com/7iYx5y8.png)
(3)singleTask:如果要激活的那个Activity在任务栈中存在该实例,则不需要创建,只需要把此Activity放入栈顶,并把该Activity以上的Activity实例都pop;
![](http://i.imgur.com/lHBkS2d.png)
(4)singleInstance:会单独创建一个Activity栈;
![](http://i.imgur.com/adhFrrx.png)
###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中的坐标系![](http:/ ...
- Android项目实战_手机安全卫士系统加速
## 1.本地数据库自动更新的工作机制1. 开启一个服务,定时访问服务器2. 进行版本对比,如果最新版本比较高,获取需要更新的内容3. 将新内容插入到本地数据库中 ## 2.如何处理横竖屏切换1. 指 ...
- Android项目实战_手机安全卫士软件管家
###1.应用程序信息的flags 1. int flags = packageInfo.applicationInfo.flags2. 0000 0000 0000 0000 0000 0000 0 ...
- Android项目实战_手机安全卫士拦截骚扰
###1.骚扰拦截需求分析1.界面1.1 黑名单列表界面1.2 添加黑名单界面2.功能2.1 黑名单的添加.删除2.2 拦截电话2.3 拦截短信 ###2.黑名单数据库的创建1.分析需要的字段id 主 ...
- Android项目实战_手机安全卫士流量统计
## 1.抽屉控件SlidingDrawer:一定要配置android:handle(把手)和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- ...
随机推荐
- 《Spring in action》之Spring之旅
Spring框架作用是简化java开发的复杂性.下面是spring in action 对spring初步介绍. 一.主要有4种关键策略: 1. 基于POJO的轻量级和最小侵入性编程 . 2. 通过依 ...
- Ubuntu下使用Sysvinit实现自定义服务(简单研究)
通过上一篇文章http://www.cnblogs.com/EasonJim/p/7168216.html可以大概了解到Sysvinit的历史. 其实在自定义服务上,使用Sysvinit是最简单的,本 ...
- 淘宝手机rem的如何使用
1.主要介绍几个移动端常用的单位rem.vw.vh,配合传统的px.百分比.<viewport>标签,兼容适配移动端的各种分辨率的手机端. rm : 这个单位是以父元素为标准来进行计算 , ...
- something interesting when read docs
When you kill a session with "ALTER SYSTEM KILL SESSION '' ". If the session is performin ...
- unary operator expected
在centos系统从root用户切换到oracle用的时候,总是提示 : -bash- : :[: unary operator expected 能切换成功,就是总提示上面这个, 后来找到原因,在安 ...
- 犀牛Phinoceros 如何切换中文语言
Tools-Options-Rhino Options-Appearance,然后改成中文
- 一个unity3d lightmap问题
上周美术同学在使用unity3d制作lightmap的过程中,发现部分被lightmap影响的模型在移动端上效果与pc端不一致.当时我大概看了下,分析后,得到一个结论是“在移动端上lightmap的h ...
- nginx + mysql + php-fpm 环境
安装 Nginx 想在 CentOS 系统上安装 Nginx ,你得先去加入一个资源库.像这样: vim /etc/yum.repos.d/nginx.repo 使用 vim 命令去打开 /etc/y ...
- ios method swizzling
阅读器 iOS开发iOS 本文由TracyYih[博客]翻译自NSHipster的文章Method Swizzling. 在上周associated objects一文中,我们开始探索Ob ...
- openstack instance bootmgr is missing 问题 修复