###1.两个页面切换的实现
1. 可以使用Fragment,调用FragmentTransaction的hide和show方法2. 可以使用两个布局,设置visibility的VISIABLE和INVISIABLE3. 可以使用一套布局,切换不同的显示数据###2.已加锁、未加锁界面数据的获取思路
1. 获取所有的应用2. 这些应用只可能是未加锁或者已加锁3. 根据数据库中存储的已加锁的情况,将所有数据分别装到已加锁和未加锁两个集合中###3.动画播放需要注意什么
1. 动画的播放是非阻塞式的,相当于开启了一个子线程定期的刷新UI2. 如果想在动画播完之后执行一些操作,需要设置监听器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_TASKIntent 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_OFF1 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 ListunlockList; 39 private List 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 all = dao.findAll(); 82 System.out.println("all :"+all); 83 List appInfo = pm.getInstalledApplications(0); 84 unlockList = new ArrayList (); 85 lockList = new ArrayList (); 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 @Override112 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 @Override123 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 @Override148 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 @Override193 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 @Override203 public long getItemId(int position) {204 // TODO Auto-generated method stub205 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 @Override221 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:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
![](https://images.cnblogs.com/OutliningIndicators/ExpandedBlockStart.gif)
1 26 7 48 49 5011 12 20 21 26 27 34 39 40 47 53 54 59 60 65 66 71 72 77 78 79
到这里整个项目已接近尾声,但这里也有许多代码没有贴出来如果感兴趣的可以看看笔者的源码:http://pan.baidu.com/s/1i59msz7