仿QQ黑屏,锁屏,程序切换之后的手势密码锁定,加强版
来源:互联网 发布:中保险网络大学ii 编辑:程序博客网 时间:2024/06/06 04:00
这是一篇我个人在EOE发的帖子《仿QQ黑屏,锁屏,程序切换之后的手势密码锁定,》,由于eoe的blog系统实在是无言以对,我就把eoe上面的帖子以及blog是都转到csdn上来,原帖地址:http://www.eoeandroid.com/thread-313331-1-1.html
加强版:原来是不管你怎么操作,都是5分钟锁定一次,但是客户要求,只要不触碰的时候再5分钟锁定一次,看过第一版的同学,直接拉到帖子最后看,加强版的实现吧,没看过的,建议从头看
----------------------------------------------------------------第一版,我是华丽分割线---------------------------------------------------------------------------
需求:项目里要用类似的如题的功能,然后在那基础上加一个5分钟锁定一次
先说下我原来的思路,
黑屏和锁屏,5分钟的切换都好说,黑屏和锁定有广播通知,5分钟自己开线程操作;但是android有长按home(menu)或者home之后再切换回来的功能,这个就要利用activity的生命周期,我开始的思路是错的,没有利用好生命周期,最后反编译qq的apk看代码才看出来的;原思路核心代码如下:
黑屏和锁屏,代码是网上搜索的,也贴出来,看下:
/**
* screen状态广播接收者
*/
private class ScreenBroadcastReceiver extends BroadcastReceiver {
private String action = null;
@Override
public void onReceive(Context context, Intent intent) {
action = intent.getAction();
if (Intent.ACTION_SCREEN_ON.equals(action)) {
mScreenStateListener.onScreenStateChange(true);
} else if (Intent.ACTION_SCREEN_OFF.equals(action)) {
mScreenStateListener.onScreenStateChange(false);
}
}
}
/**
* 请求screen状态更新
*/
public void requestScreenStateUpdate(ScreenStateListener listener) {
mScreenStateListener = listener;
startScreenBroadcastReceiver();
firstGetScreenState();
}
/**
* 第一次请求screen状态
*/
private void firstGetScreenState() {
PowerManager manager = (PowerManager) mContext
.getSystemService(Activity.POWER_SERVICE);
if (isScreenOn(manager)) {
if (mScreenStateListener != null) {
mScreenStateListener.onScreenStateChange(true);
}
} else {
if (mScreenStateListener != null) {
mScreenStateListener.onScreenStateChange(false);
}
}
}
/**
* 停止screen状态更新
*/
public void stopScreenStateUpdate() {
mContext.unregisterReceiver(mScreenReceiver);
}
/**
* 启动screen状态广播接收器
*/
private void startScreenBroadcastReceiver() {
IntentFilter filter = new IntentFilter();
filter.addAction(Intent.ACTION_SCREEN_ON);
filter.addAction(Intent.ACTION_SCREEN_OFF);
mContext.registerReceiver(mScreenReceiver, filter);
}
/**
* screen是否打开状态
*
* @param pm
* @return
*/
private static boolean isScreenOn(PowerManager pm) {
boolean screenState;
try {
screenState = (Boolean) mReflectScreenState.invoke(pm);
} catch (Exception e) {
screenState = false;
}
return screenState;
}
5分钟一次:
private static Timer timer ;
private static TimerTask timerTask;
private static boolean isRunning;
/**
* 5分钟一次弹出
*
* @param
* @return void
* @throws
*/
public void startVerify(){
if(timer == null){
timer = new Timer();
}
if(timerTask == null){
timerTask = new TimerTask() {
@Override
public void run() {
// 使用handler去通知主线程判断是否开启锁定界面
mHandler.sendEmptyMessage(0);
}
};
}
if(!isRunning){
timer.schedule(timerTask, 60*1000, 60*1000);
isRunning = true;
}
}
private Handler mHandler = new Handler(){
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
verify();
LogUtil.i("GestureActivity.IS_SHOW-->"+GestureActivity.IS_SHOW);
}
};
/** * 开启检测界面 * * @param * @return void * @throws */
public void verify(boolean isPause) {
boolean isTopRunning = isRunningForeground(getApplicationContext());
if(isPause){ if(!isTopRunning){
// 判断检测界面是否已经运行
if(!GestureActivity.IS_SHOW)
{ Intent intent = new Intent(); intent.setClass(getApplicationContext(), GestureActivity.class); intent.putExtra(GestureActivity.INTENT_MODE, GestureActivity.GESTURE_MODE_VERIFY); intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); startActivity(intent); } } }else{ // 判断是否在前台运行 if(isTopRunning){ // 判断检测界面是否已经运行 if(!GestureActivity.IS_SHOW){ Intent intent = new Intent(); intent.setClass(getApplicationContext(), GestureActivity.class); intent.putExtra(GestureActivity.INTENT_MODE, GestureActivity.GESTURE_MODE_VERIFY); intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); startActivity(intent); } } } }
错误的程序切换核心代码:思路1:onstop中
@Override
protected void onPause() {
super.onPause();
if(isVerify()){
mApplication.verify(true);
}
}
思路2:在onrestart中
@Override
protected void onRestart() {
super.onRestart();
if (isVerify()) {
mApplication.verify(true);
}
}
如上代码,按home健没问题,但是长按调出最近程序列表的时候就会有问题,会直接弹出来密码解锁界面
qq已经实现了,就去看看大牛们是怎么做的,晚上回去反编译qq的apk,反编译出来的资源如下
大企业,代码写的一般都会非常规范,一般略懂鸟语的一些常用的东西就能看的明白:
1、首先要看manifest中的activity,首先要定位到解锁界面是那个类
2、因为qq所以界面都会响应这操作,所以这个判断肯定是在一个基类里,可以找到一个baseactivity里面有这个判断的方法,而且必须是在生命周期中,用jd-jui来定位一下代码看看base中有这样的代码,如图
如图确实是有一个方法是开启锁定界面,然后看了下生命周期,有调用到该方法的地方,那么下一步就是把新建一个工程,吧qq的src放进去(主要为了使用eclipse的search功能,也可以用sourceinsight)
3、来分析base的onstart,onresume,onstop(onstart,onresume的操作是一致的)
分析看图中
在这三个生命周期中用到了一个重要的类GesturePWDUtils,一会分析这个类
多余代码我都删掉了,代码中的注释是我加的,纯属个人YY,如果有差错,也请高抬贵手
public class GesturePWDUtils{ // 应该是判断当前app是否在最前端 public static boolean getAppForground(Context paramContext) { boolean bool = getAppSharedPreferences(paramContext). getBoolean("gesturepassword_appforground", false); if (QLog.isColorLevel()) { String str = "getAppForground.uin=,isAppFroground=" + bool; QLog.d("Q.gesturelock.util", 2, str); } return bool; } // 应该是判断当前账号的是否设置了 手势密码锁定 public static boolean getJumpLock(Context paramContext, String paramString) { boolean bool = true; SharedPreferences localSharedPreferences = getSharedPreferences(paramContext); String str1 = "gesturepassword_gesture_mode" + paramString; int i = localSharedPreferences.getInt(str1, 21); if (i == 21) { String str2 = "gesturepassword_gesture_state" + paramString; if (localSharedPreferences.getInt(str2, 0) != 2) break label146; } while (true) { if (QLog.isColorLevel()) { String str3 = "getJumpLock.uin=" + paramString + ",isjumplock=" + bool; QLog.d("Q.gesturelock.util", 2, str3); } return bool; if ((i == 20) && (localSharedPreferences. getBoolean("gesturepassword_locking", false))) continue; label146: bool = false; } } // 判断当前app是否在最前端,可以看代码,qq把一些activity过滤掉了, public static boolean isAppOnForeground(Context paramContext) { ActivityManager localActivityManager = (ActivityManager)paramContext.getApplicationContext().getSystemService("activity"); String str1 = paramContext.getApplicationContext().getPackageName(); Object localObject = localActivityManager.getRunningAppProcesses(); int i; if (localObject == null) i = 0; while (true) { return i; Iterator localIterator = ((List)localObject).iterator(); while (true) if (localIterator.hasNext()) { localObject = (ActivityManager.RunningAppProcessInfo)localIterator.next(); if (((ActivityManager.RunningAppProcessInfo)localObject).importance != 100) continue; if (!((ActivityManager.RunningAppProcessInfo)localObject).processName.equals(str1)) { String str2 = ((ActivityManager.RunningAppProcessInfo)localObject).processName; String str3 = str1 + ":qzone"; if (!str2.equals(str3)) { String str4 = ((ActivityManager.RunningAppProcessInfo)localObject).processName; String str5 = str1 + ":picture"; if (!str4.equals(str5)) { String str6 = ((ActivityManager.RunningAppProcessInfo)localObject).processName; String str7 = str1 + ":web"; if (!str6.equals(str7)) { String str8 = ((ActivityManager.RunningAppProcessInfo)localObject).processName; String str9 = str1 + ":video"; if (!str8.equals(str9)) { String str10 = ((ActivityManager.RunningAppProcessInfo)localObject).processName; String str11 = str1 + ":zebra"; if (!str10.equals(str11)) { String str12 = ((ActivityManager.RunningAppProcessInfo)localObject).processName; String str13 = str1 + ":qqreader"; if (!str12.equals(str13)) continue; } } } } } } i = 1; break; } i = 0; } } // 重点,保存当前app是否在最前端的状态 public static void setAppForground(Context paramContext, boolean paramBoolean) { if (QLog.isColorLevel()) { String str = "setAppForground.uin=,isAppFroground=" + paramBoolean; QLog.d("Q.gesturelock.util", 2, str); } SharedPreferences.Editor localEditor1 = getAppSharedPreferences(paramContext).edit(); SharedPreferences.Editor localEditor2 = localEditor1.putBoolean("gesturepassword_appforground", paramBoolean); boolean bool = localEditor1.commit(); }}
ok,分析完了代码,知道了解决方法,来改造我自己的代码,主要是程序切换的代码(生命周期中),代码如下:SpOperationUtil是我对SharedPreferences的封装,大家看方法名就应该明白,getBooleanInfof的意识是获取boolean值,默认值为false
@Override protected void onStart() { super.onStart(); isForeGround = SpOperationUtil.getBooleanInfof(CTX, ISFOREGROUND_KEY); if(!isForeGround){ if (isVerify()) { mApplication.verify(); } } if(!isForeGround){ SpOperationUtil.saveBoolean(CTX, ISFOREGROUND_KEY, true); } } @Override protected void onResume() { super.onResume(); isForeGround = SpOperationUtil.getBooleanInfof(CTX, ISFOREGROUND_KEY); if(!isForeGround){ if (isVerify()) { mApplication.verify(); } } if(!isForeGround){ SpOperationUtil.saveBoolean(CTX, ISFOREGROUND_KEY, true); } } String ISFOREGROUND_KEY = "ISFOREGROUND_KEY"; boolean isForeGround = true; @Override protected void onStop() { super.onStop(); isForeGround = mApplication.isRunningForeground(CTX); if(!isForeGround){ SpOperationUtil.saveBoolean(CTX, ISFOREGROUND_KEY, isForeGround); } }
这样的话,功能就完成......代码分析先到这,中午整理下,写个demo,上传上来
----------------------------------------------------------------第一版,我是华丽分割线---------------------------------------------------------------------------
加强版:只有没操作之后,5分钟锁定一次,注意demo中为了方便测试设置的是30秒,下面是思路和解决方法:
1、监听每一个activity的触碰事件,获取最新一次的触碰时间,和上一次时间相比,如果没超过5分钟,就把监听先停掉然后再重新开启,代码如下:
base中拦截触碰时间
@Override public boolean dispatchTouchEvent(MotionEvent ev) { mApplication.setLastTouchTime(); return super.dispatchTouchEvent(ev); } MApplication 中// 上一次触碰时间 long lastTimeMillis = 0; /** * 设置上一次监听时间 * * @param * @return void * @throws */ public void setLastTouchTime(){ // 最新的触碰时间 long currentTimeMillis = System.currentTimeMillis(); if(lastTimeMillis == 0){ // 第一次触碰 lastTimeMillis = currentTimeMillis; // 开启监听 startVerify(); }else{ //时间差 long temp = currentTimeMillis - lastTimeMillis; // 如果时间差小于5分钟,就先停掉前一次的监听,再重新开启 if(temp < 1000 * 60 * 5){ stopVerify(); startVerify(); } // else 如果大于,那么上一次的监听在运行着,5分钟之后自然会锁定 } }
2、注意:MainActivity中
// 过滤掉本activity 这个界面不用监听
setVerify(false);
最后代码地址:http://download.csdn.net/detail/lsmfeixiang/7859569
- 仿QQ黑屏,锁屏,程序切换之后的手势密码锁定,加强版
- 仿QQ界面的切换
- 仿支付宝手势密码
- 黑屏手势的性能提升
- 仿QQ聊天程序
- 仿QQ聊天程序
- 高仿QQ首页消息和电话切换的实现
- 仿QQ的密码保存,点击按钮选择其他账号
- 使用FragmentTabHost实现仿QQ的切换,并在里面嵌套TabLayout+ViewPager的滑动切换
- 仿手机QQ聊天列表滑动菜单删除和手势滑动返回的两种方式
- qq密码记录程序
- QQ密码窃取程序
- 盗取QQ密码程序
- C# 仿QQ截图程序
- 微信小程序_仿QQ
- JAVA 仿QQ聊天程序
- 基于P2P及多播技术的仿QQ程序
- 仿QQ聊天窗口抖动的小程序及源程序
- UVA 10404 Bachet's Game
- 九度OJ 1069 查找学生信息 (模拟)
- Linux下DISPLAY环境变量的作用
- 第十八周OJ项目六用数字造数字二
- struts+hibernate权限管理系统
- 仿QQ黑屏,锁屏,程序切换之后的手势密码锁定,加强版
- hadoop对专利引用数据进行处理,输出被引用的专利
- 周鼎——《自白书》
- google chrome调试
- 1016. 部分A+B (15)
- 互联网思维,改变未来的武器
- HDU - 1166 - 敌兵布阵 (树状数组 or 线段树)
- 递增数组元素的折半查找
- POJ1659 Frogs' Neighborhood ACM解题报告(图论基础 邻接矩阵)