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
1 package com.hb.mobilesafe.activities; 2 3 import java.util.ArrayList; 4 import java.util.List; 5 6 import android.app.Activity; 7 import android.content.pm.ApplicationInfo; 8 import android.content.pm.PackageManager; 9 import android.os.Bundle; 10 import android.view.View; 11 import android.view.View.OnClickListener; 12 import android.view.ViewGroup; 13 import android.view.Window; 14 import android.widget.BaseAdapter; 15 import android.widget.Button; 16 import android.widget.ImageView; 17 import android.widget.ListView; 18 import android.widget.TextView; 19 20 import com.hb.demo_mobilesafe.R; 21 import com.hb.mobilesafe.bean.ApplockInfo; 22 import com.hb.mobilesafe.dbdao.AppLockDao; 23 24 public class SoftLockActivity extends Activity implements OnClickListener { 25 private PackageManager pm; 26 27 private Button bt_unlock; 28 private Button bt_lock; 29 private TextView tv_unlocksoft; 30 private TextView tv_locksoft; 31 private ListView lv_unlocksoft; 32 private ListView lv_locksoft; 33 34 private MylocksoftAdapter unlockadapter; 35 private MylocksoftAdapter lockadapter; 36 37 private boolean flags=false; 38 private List<ApplockInfo> unlockList; 39 private List<ApplockInfo> lockList; 40 41 private AppLockDao dao; 42 43 @Override 44 protected void onCreate(Bundle savedInstanceState) { 45 // TODO Auto-generated method stub 46 super.onCreate(savedInstanceState); 47 requestWindowFeature(Window.FEATURE_NO_TITLE); 48 setContentView(R.layout.activity_softlock); 49 initView(); 50 } 51 /** 52 * 找Id 53 */ 54 private void initView() { 55 bt_unlock=(Button) findViewById(R.id.bt_unlock); 56 bt_lock=(Button) findViewById(R.id.bt_lock); 57 tv_unlocksoft=(TextView) findViewById(R.id.tv_unlocksoft); 58 tv_locksoft=(TextView) findViewById(R.id.tv_locksoft); 59 lv_unlocksoft=(ListView) findViewById(R.id.lv_unlocksoft); 60 lv_locksoft=(ListView) findViewById(R.id.lv_locksoft); 61 bt_unlock.setOnClickListener(this); 62 bt_lock.setOnClickListener(this); 63 getAllAppInfo(); 64 InitUI(); 65 66 } 67 /** 68 * 初始化界面 69 */ 70 private void InitUI() { 71 tv_locksoft.setVisibility(View.INVISIBLE); 72 lv_locksoft.setVisibility(View.INVISIBLE); 73 74 } 75 /** 76 * 获取手机上的APP 77 */ 78 public void getAllAppInfo(){ 79 pm = getPackageManager(); 80 dao = new AppLockDao(this); 81 List<String> all = dao.findAll(); 82 System.out.println("all :"+all); 83 List<ApplicationInfo> appInfo = pm.getInstalledApplications(0); 84 unlockList = new ArrayList<ApplockInfo>(); 85 lockList = new ArrayList<ApplockInfo>(); 86 for (ApplicationInfo mInfo : appInfo) { 87 ApplockInfo lockInfo = new ApplockInfo(); 88 lockInfo.setIcon(mInfo.loadIcon(pm)); 89 lockInfo.setAppName(mInfo.loadLabel(pm).toString()); 90 lockInfo.setAppPackageName(mInfo.packageName); 91 //判断是加锁还是未加锁 92 if(all.contains(mInfo.packageName)){ 93 lockList.add(lockInfo); 94 }else{ 95 unlockList.add(lockInfo); 96 } 97 if(!flags){ 98 unlockadapter=new MylocksoftAdapter(); 99 lv_unlocksoft.setAdapter(unlockadapter); 100 }else{ 101 lockadapter = new MylocksoftAdapter(); 102 lv_locksoft.setAdapter(lockadapter); 103 104 } 105 } 106 } 107 class MylocksoftAdapter extends BaseAdapter{ 108 109 private ApplockInfo info; 110 111 @Override 112 public int getCount() { 113 if(!flags){ 114 tv_unlocksoft.setText("未加锁程序"+unlockList.size()+"个"); 115 return unlockList.size(); 116 }else{ 117 tv_locksoft.setText("已加锁程序"+lockList.size()+"个"); 118 return lockList.size(); 119 120 } 121 } 122 @Override 123 public View getView(final int position, View convertView, ViewGroup parent) { 124 ViewHolder holder=null; 125 if(convertView != null){ 126 holder = (ViewHolder) convertView.getTag(); 127 }else{ 128 holder=new ViewHolder(); 129 convertView=View.inflate(SoftLockActivity.this, R.layout.unlock_item, null); 130 holder.iv_appicon =(ImageView) convertView.findViewById(R.id.iv_appicon); 131 holder.tv_appname= (TextView) convertView.findViewById(R.id.tv_appname); 132 holder.iv_status=(ImageView) convertView.findViewById(R.id.iv_status); 133 convertView.setTag(holder); 134 } 135 final ApplockInfo info = (ApplockInfo) getItem(position); 136 holder.iv_appicon.setImageDrawable(info.getIcon()); 137 holder.tv_appname.setText(info.getAppName()); 138 if(!flags){ 139 holder.iv_status.setBackgroundResource(R.drawable.btn_lock_selector); 140 }else{ 141 holder.iv_status.setBackgroundResource(R.drawable.btn_unlock_selector); 142 143 } 144 145 holder.iv_status.setOnClickListener(new OnClickListener() { 146 147 @Override 148 public void onClick(View v) { 149 if(flags){ 150 /** 151 * 已加锁 152 */ 153 new Thread(){ 154 public void run() { 155 dao.delete(lockList.get(position).getAppPackageName()); 156 unlockList.add(info); 157 runOnUiThread(new Runnable() { 158 public void run() { 159 lockList.remove(info); 160 tv_locksoft.setText("已加锁程序"+lockList.size()+"个"); 161 lockadapter.notifyDataSetChanged(); 162 } 163 }); 164 165 }; 166 }.start(); 167 }else{ 168 /** 169 * 未加锁 170 */ 171 new Thread(){ 172 public void run() { 173 dao.add(unlockList.get(position).getAppPackageName()); 174 lockList.add(info); 175 runOnUiThread(new Runnable() { 176 public void run() { 177 unlockList.remove(info); 178 tv_unlocksoft.setText("未加锁程序"+unlockList.size()+"个"); 179 unlockadapter.notifyDataSetChanged(); 180 } 181 }); 182 183 }; 184 }.start(); 185 186 } 187 } 188 }); 189 190 return convertView; 191 } 192 @Override 193 public Object getItem(int position) { 194 if(!flags){ 195 info = unlockList.get(position); 196 }else{ 197 info = lockList.get(position); 198 } 199 return info; 200 } 201 202 @Override 203 public long getItemId(int position) { 204 // TODO Auto-generated method stub 205 return 0; 206 } 207 208 209 210 } 211 static class ViewHolder{ 212 ImageView iv_appicon; 213 TextView tv_appname; 214 ImageView iv_status; 215 } 216 /** 217 * 已加锁与未加锁的点击事件 218 * 219 */ 220 @Override 221 public void onClick(View v) { 222 switch (v.getId()) { 223 case R.id.bt_unlock: 224 flags=false; 225 tv_locksoft.setVisibility(View.INVISIBLE); 226 lv_locksoft.setVisibility(View.INVISIBLE); 227 tv_unlocksoft.setVisibility(View.VISIBLE); 228 lv_unlocksoft.setVisibility(View.VISIBLE); 229 unlockadapter=new MylocksoftAdapter(); 230 lv_unlocksoft.setAdapter(unlockadapter); 231 break; 232 233 case R.id.bt_lock: 234 flags=true; 235 tv_unlocksoft.setVisibility(View.INVISIBLE); 236 lv_unlocksoft.setVisibility(View.INVISIBLE); 237 tv_locksoft.setVisibility(View.VISIBLE); 238 lv_locksoft.setVisibility(View.VISIBLE); 239 lockadapter=new MylocksoftAdapter(); 240 lv_locksoft.setAdapter(lockadapter); 241 break; 242 } 243 } 244 245 }
xml:
1 <?xml version="1.0" encoding="utf-8"?> 2 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" 3 android:layout_width="match_parent" 4 android:layout_height="match_parent" 5 android:orientation="vertical" > 6 7 <RelativeLayout 8 android:layout_width="match_parent" 9 android:layout_height="wrap_content" 10 android:background="#A1FF80" > 11 12 <TextView 13 android:id="@+id/tv_title" 14 android:layout_width="match_parent" 15 android:layout_height="46dp" 16 android:layout_marginLeft="5dip" 17 android:gravity="center_vertical" 18 android:text="程序锁" 19 android:textSize="20sp" /> 20 21 <LinearLayout 22 android:layout_width="wrap_content" 23 android:layout_height="wrap_content" 24 android:layout_centerInParent="true" 25 android:orientation="horizontal" > 26 27 <Button 28 android:id="@+id/bt_unlock" 29 android:layout_width="wrap_content" 30 android:layout_height="30dip" 31 android:background="#5300FF" 32 android:text="未加锁" 33 android:textColor="#ffffff" /> 34 <TextView 35 android:layout_width="1dip" 36 android:layout_height="30dip" 37 android:background="#ffffff" 38 /> 39 40 <Button 41 android:id="@+id/bt_lock" 42 android:layout_width="wrap_content" 43 android:layout_height="30dip" 44 android:background="#5f00F0" 45 android:text="已加锁" 46 android:textColor="#ffffff" /> 47 </LinearLayout> 48 </RelativeLayout> 49 50 <RelativeLayout 51 android:layout_width="match_parent" 52 android:layout_height="match_parent" > 53 54 <TextView 55 android:id="@+id/tv_locksoft" 56 android:layout_width="match_parent" 57 android:layout_height="wrap_content" 58 android:text="未加锁程序:12个" /> 59 60 <TextView 61 android:id="@+id/tv_unlocksoft" 62 android:layout_width="match_parent" 63 android:layout_height="wrap_content" 64 android:text="已加锁程序:5个" /> 65 66 <ListView 67 android:id="@+id/lv_locksoft" 68 android:layout_width="match_parent" 69 android:layout_height="match_parent" 70 android:layout_below="@id/tv_locksoft" /> 71 72 <ListView 73 android:id="@+id/lv_unlocksoft" 74 android:layout_width="match_parent" 75 android:layout_height="match_parent" 76 android:layout_below="@id/tv_unlocksoft" /> 77 </RelativeLayout> 78 79 </LinearLayout>
到这里整个项目已接近尾声,但这里也有许多代码没有贴出来如果感兴趣的可以看看笔者的源码:http://pan.baidu.com/s/1i59msz7