安卓仿钉钉密码安全锁实现

 

            




第一步:自定义数字键盘

package cc.vv.btong.module_mine.view;

import android.content.Context;
import android.graphics.Color;
import android.graphics.drawable.ColorDrawable;
import android.os.Handler;
import android.os.Message;
import android.text.TextUtils;
import android.util.AttributeSet;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.BaseAdapter;
import android.widget.GridView;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.TextView;

import cc.vv.btong.module_mine.R;


public class MyPasswordView extends LinearLayout {

Context context;
LinearLayout showNumberLayout;
private ImageView[] imgs = new ImageView[4];
GridView dcMyGameMyGridView;
LayoutInflater mInflater;
private String password = "";
OnPasswordInputCompleteListener onPasswordInputCompleteListener;
String showButtonText;

PhoneNumberAdapter phoneNumberAdapter = new PhoneNumberAdapter();


public MyPasswordView(Context context) {
super(context);
this.context = context;
initView();
}

public MyPasswordView(Context context, AttributeSet attrs) {
super(context, attrs);
this.context = context;
initView();
}

public void setOnPasswordInputCompleteListener(OnPasswordInputCompleteListener onPasswordInputCompleteListener) {
this.onPasswordInputCompleteListener = onPasswordInputCompleteListener;
}

private void initView() {
this.mInflater = LayoutInflater.from(context);
LayoutInflater.from(context).inflate(R.layout.common_password_view,
this);
showNumberLayout = (LinearLayout) findViewById(R.id.llayout);
for (int i = 0; i < 4; i++) {
imgs[i] = (ImageView) showNumberLayout.getChildAt(i);
imgs[i].setEnabled(true);
imgs[i].setTag(i);
}
setHideImageView();
dcMyGameMyGridView = (GridView) findViewById(R.id.phone_number);
dcMyGameMyGridView.setAdapter(phoneNumberAdapter);
dcMyGameMyGridView.setSelector(new ColorDrawable(
Color.TRANSPARENT));
dcMyGameMyGridView.setOnItemClickListener(new PhoneNumberItemClickListener());
}

/**
* @param count
*/
public void setShowImageViewCount(int count) {
for (int i = 0; i < count; i++) {
imgs[i].setEnabled(false);
}
}

/**
*/
public void setHideImageView() {
int length = getPassword().length();
for (int i = 0; i < length; i++) {
imgs[i].setEnabled(false);
}
for (int i = 0; i < 4 - length; i++) {
imgs[3 - i].setEnabled(true);
}
}


private class PhoneNumberAdapter extends BaseAdapter {

@Override
public int getCount() {
return 12;
}

@Override
public Object getItem(int arg0) {
return arg0;
}

@Override
public long getItemId(int arg0) {
return arg0;
}

@Override
public View getView(int position, View contentView, ViewGroup arg2) {

if (position < 9) {
contentView = mInflater.inflate(R.layout.phone_number_layout,
null);
TextView imageView = (TextView) contentView
.findViewById(R.id.phone_number_view);
imageView.setText(position + 1 + "");

} else if (position == 9) {
contentView = mInflater.inflate(R.layout.phone_number_empty_layout, null);
} else if (position == 10) {
contentView = mInflater.inflate(R.layout.phone_number_layout,
null);
TextView imageView = (TextView) contentView
.findViewById(R.id.phone_number_view);
imageView.setText("0");
} else if (position == 11) {
contentView = mInflater.inflate(R.layout.phone_number_delete_layout,
null);
}
return contentView;
}

}

private class PhoneNumberItemClickListener implements OnItemClickListener {

@Override
public void onItemClick(AdapterView<?> arg0, View arg1, int position,
long arg3) {
if (position < 9) {
//添加数字
changePasswrod((position + 1) + "");
} else if (position == 10) {
//添加数字
changePasswrod(0 + "");
} else if (position == 11) {
//删除一位
deletePassword();
}
}

}

/**
* @param number
*/
private void changePasswrod(String number) {
String passwordString = getPassword();
if (TextUtils.isEmpty(passwordString) || passwordString.length() < 4) {
setPassword(passwordString + number);
setHideImageView();

if (passwordString.length() == 3) {

//回调密码输入完成
onPasswordInputCompleteListener.OnComPlete(password);
new Thread(new Runnable() {
@Override
public void run() {
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
handler.sendEmptyMessage(0);
}
}).start();
}
}
}

private Handler handler = new Handler() {
@Override
public void handleMessage(Message msg) {
cleanAllPassword();
}
};

/**
* 删除输入的
*/
private void deletePassword() {
String passwordString = getPassword();
if (!TextUtils.isEmpty(passwordString) || passwordString.length() > 0) {
setPassword(passwordString.substring(0, passwordString.length() - 1));
setHideImageView();
}
}

public String getPassword() {
return password;
}

public void setPassword(String password) {
this.password = password;
}

public static interface OnPasswordInputCompleteListener {
void OnComPlete(String password);
}


public void cleanAllPassword() {
setPassword("");
setHideImageView();
}

}
布局文件:
<?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">

<LinearLayout
android:id="@+id/llayout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center"
android:orientation="horizontal">

<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:clickable="true"
android:padding="6dp"
android:src="@drawable/page_indicator_bg" />

<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:clickable="true"
android:padding="6dp"
android:src="@drawable/page_indicator_bg" />

<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:clickable="true"
android:padding="6dp"


android:src="@drawable/page_indicator_bg" />

<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:clickable="true"
android:padding="6dp"
android:src="@drawable/page_indicator_bg" />
</LinearLayout>

<GridView
android:id="@+id/phone_number"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginTop="20dp"
android:divider="@null"
android:drawSelectorOnTop="false"
android:gravity="center"
android:horizontalSpacing="@dimen/dp_30"
android:listSelector="@null"
android:numColumns="3"
android:paddingLeft="@dimen/dp_55"
android:paddingRight="@dimen/dp_55"
android:stretchMode="columnWidth"
android:verticalSpacing="30dp" />

</LinearLayout>

锁屏界面:(这里有好多我项目里的逻辑,忽略)
package cc.vv.btong.module_mine.ui.activity;

import android.app.Dialog;
import android.content.Intent;
import android.os.Bundle;
import android.support.annotation.Nullable;
import android.view.Gravity;
import android.view.KeyEvent;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.TextView;

import com.tencent.common.MD5;

import java.util.LinkedHashMap;

import cc.vv.btong.module_mine.R;
import cc.vv.btong.module_mine.api.BtongApi;
import cc.vv.btong.module_mine.bean.response.SetSecretPasswordResponseObj;
import cc.vv.btong.module_mine.view.MyPasswordView;
import cc.vv.btongbaselibrary.app.activity.BTongBaseActivity;
import cc.vv.btongbaselibrary.app.activity.BTongNewBaseActivity;
import cc.vv.btongbaselibrary.bean.PublicViewHolder;
import cc.vv.btongbaselibrary.manager.UserManager;
import cc.vv.btongbaselibrary.router.RouterActivityIntentResourceKey;
import cc.vv.btongbaselibrary.router.RouterTransferCenterUtil;
import cc.vv.btongbaselibrary.ui.view.BaseTopBarView;
import cc.vv.btongbaselibrary.util.AppManager;
import cc.vv.btongbaselibrary.util.LKToastUtil;
import cc.vv.btongbaselibrary.vFinal.BTParamKey;
import cc.vv.lkbasecomponent.http.LKHttp;
import cc.vv.lkbasecomponent.util.LKDialogUtil;
import cc.vv.lkbasecomponent.util.LKStringUtil;
import cc.vv.lklibrary.anno.annotation.LayoutInject;
import cc.vv.lklibrary.anno.annotation.ViewInject;

import static cc.vv.btongbaselibrary.vFinal.BTParamKey.INTENT_CLASS_PATH_MESSAGE;
import static cc.vv.btongbaselibrary.vFinal.BTParamKey.SECRET_CHAT;


/**
* creat on 2018/4/3
*
* @author Lei D
* 安全密码设置页面
*/
public class LockScreenActivity extends BTongNewBaseActivity {

private ViewHolder viewHolder;

/**
* 输入错误计数器
*/
private int errorPasswordCount = 5;
/**
* 安全密码锁页面请求码
*/
public static final int GOTO_LOCK_REQUEST_CODE = 2001;
/**
* 输入密码的值
*/
private String psw = "";
/**
* 是否开启安全密码
*/
private int safeCodeLockState;
private static final int SECRET_CHAT_VALUE = 11;

private int secretChatValue;
private String classPath;
private Bundle bundle;

@Override
protected int initLayoutRes() {
return R.layout.activity_lock_screen;
}

@Override
protected PublicViewHolder initViewHolderObject() {
return viewHolder = new ViewHolder();
}

@Override
protected void baseOnClick(int viewId) {

}

@Override
protected void initView(@Nullable Bundle bundle) {
super.initView(bundle);
viewHolder.btbv_aasa_top_bar.setWhetherShowDividerView(false);
viewHolder.tv_info.setText(R.string.str_input_password);
}

@Override
protected void initData(@Nullable Bundle data) {
super.initData(data);

safeCodeLockState = UserManager.getmSafeCodeLockOpen();
try {
if (data != null) {
secretChatValue = data.getInt(SECRET_CHAT);
classPath = data.getString(INTENT_CLASS_PATH_MESSAGE);
bundle = data.getBundle(BTParamKey.INTENT_CLASS_BUNDLE);
viewHolder.btbv_aasa_top_bar.setVisibility(View.VISIBLE);
viewHolder.tv_forget_pwd.setText(R.string.str_manager_safe_code);
}
} catch (Exception e) {
e.printStackTrace();
}
}

@Override
protected void initAction(@Nullable Bundle data) {
super.initAction(data);

viewHolder.btbv_aasa_top_bar.setEventInterface(new BaseTopBarView.EventInterface() {
@Override
public void leftOnClick() {
if (secretChatValue == SECRET_CHAT_VALUE) {
finish();
}
}

@Override
public void leftCloseClick() {

}

@Override
public void rightOnClick() {

}
});

viewHolder.ls_passwordView.setOnPasswordInputCompleteListener(new MyPasswordView.OnPasswordInputCompleteListener() {
@Override
public void OnComPlete(String pwd) {

String password = MD5.MD5Encode(pwd);
//校验安全密码
//拿到本地存储的
String safeCode = UserManager.getSafeCode();
if (LKStringUtil.equals(safeCode, password)) {
if (secretChatValue == SECRET_CHAT_VALUE) {
Intent routerIntent = RouterTransferCenterUtil.getInstance().getRouterIntent(LockScreenActivity.this, classPath);
if (bundle != null) {
routerIntent.putExtras(bundle);
}
RouterTransferCenterUtil.getInstance().routerStartActivity(LockScreenActivity.this, routerIntent);
finish();
} else {
setResult(RESULT_OK);
finish();
}
} else {
//旧密码输入错误,1.输入错误时提示”密码不正确,4次重试后将重新登录“;”密码不正确,3次重试后将重新登录“;”密码不正确,2次重试后将重新登录“;
//密码不正确,1次重试后将重新登录“;4次输入错误后弹出提示框”超过错误次数限制,需重新登录“点击重新登录按钮,进入登录页面
errorPasswordCount--;
if (errorPasswordCount == 0) {
//需重新登录,进入登录页面
showReloginDialog(password);
} else {
//提示”密码不正确,..次重试后将重新登录
String msg = getResources().getString(R.string.str_secret_protect_password_fail);
String result = String.format(msg, errorPasswordCount + "");
LKToastUtil.showToastShort(result);
}
}
}
});


viewHolder.tv_forget_pwd.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {

if (secretChatValue == SECRET_CHAT_VALUE) {
RouterTransferCenterUtil.getInstance().routerStartActivity(LockScreenActivity.this, SafePasswordLockActivity.class);
} else {

//重新登录,同时关闭锁屏保护
View view = LayoutInflater.from(LockScreenActivity.this).inflate(R.layout.lock_screen_relogin_dialog, null);
final Dialog dialog = LKDialogUtil.getDialog(view, 0, 0, Gravity.CENTER, false);
dialog.show();
TextView tv_cancel = view.findViewById(R.id.tv_cancel);
TextView tv_goOn = view.findViewById(R.id.tv_goOn);
tv_cancel.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
dialog.cancel();
}
});
tv_goOn.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
//跳转登录页面
//关闭密码锁
UserManager.setSafeCodeLockOpen(0);
closeSafeCode();
Intent intentPrivate = RouterTransferCenterUtil.getInstance().getRouterIntent(LockScreenActivity.this, RouterActivityIntentResourceKey.KEY_BT_LOGIN_LOGIN_ACTIVITY);
intentPrivate.putExtra(BTParamKey.CLOSE_CODE, true);
RouterTransferCenterUtil.getInstance().routerStartActivity(LockScreenActivity.this, intentPrivate);
dialog.cancel();
}
});
}
}
});

}

private void closeSafeCode() {
LinkedHashMap<String, Object> linkedHashMap = new LinkedHashMap<>(2);
linkedHashMap.put("item", "SAFE_CODE");
linkedHashMap.put("safeCode", UserManager.getSafeCode());
LKHttp.post(BtongApi.CLOSE_SECRET_PASSWORD, linkedHashMap, SetSecretPasswordResponseObj.class, new BtCallBack<SetSecretPasswordResponseObj>(LockScreenActivity.this) {

@Override
protected void onComplete(String url, String resultText, SetSecretPasswordResponseObj obj) {
super.onComplete(url, resultText, obj);
//关闭
UserManager.setSafeCodeLockOpen(0);
UserManager.setScreenLockState(0);
UserManager.setSecurityChatProtected(false);
UserManager.setSafeCode("");
// setResult(RESULT_OK);
// finish();
}

@Override
protected boolean onGetBadCode(String url, SetSecretPasswordResponseObj obj, int code) {
UserManager.setSafeCodeLockOpen(1);
LKToastUtil.showToastShort(obj.statusMessage);
return super.onGetBadCode(url, obj, code);
}
}, true);
}


private void showReloginDialog(final String password) {
View view = LayoutInflater.from(this).inflate(R.layout.password_error_dialog, null);
final Dialog dialog = LKDialogUtil.getDialog(view, 0, 0, Gravity.CENTER, false);
TextView errorMsg = view.findViewById(R.id.tv_comment);
errorMsg.setText(getString(R.string.str_change_safe_lock_psw_relogin_info));
TextView tv_goOn = view.findViewById(R.id.tv_goOn);
tv_goOn.setText(getString(R.string.str_relogin_info));
dialog.show();
tv_goOn.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
dialog.cancel();
// 退出登录
UserManager.setSafeCodeLockOpen(0);
closeSafeCode();
AppManager.getInstance().loginOut(LockScreenActivity.this);
//TODO 跳转到登录页面 closeSafeCode yes
Intent routerIntent = RouterTransferCenterUtil.getInstance().getRouterIntent(LockScreenActivity.this, RouterActivityIntentResourceKey.KEY_BT_LOGIN_LOGIN_ACTIVITY);
routerIntent.putExtra(BTParamKey.CLOSE_CODE, true);
RouterTransferCenterUtil.getInstance().routerStartActivity(LockScreenActivity.this, routerIntent);
}
});
}

@Override
public void onBackPressed() {
Intent intent = new Intent();
intent.setAction("android.intent.action.MAIN");
intent.addCategory("android.intent.category.HOME");
startActivity(intent);
super.onBackPressed();
}

@Override
public boolean onKeyDown(int keyCode, KeyEvent event) {

if (keyCode == KeyEvent.KEYCODE_BACK) {
Intent intent = new Intent();
intent.setAction("android.intent.action.MAIN");
intent.addCategory("android.intent.category.HOME");
startActivity(intent);
return true;
}
return super.onKeyDown(keyCode, event);
}

class ViewHolder extends PublicViewHolder {
/**
* 标题栏
*/
BaseTopBarView btbv_aasa_top_bar;
/**
* 提示textview
*/
TextView tv_info;
/**
* 忘记密码
*/
TextView tv_forget_pwd;

MyPasswordView ls_passwordView;
}
}


布局:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#99FFFFFF"
android:gravity="center">

<cc.vv.btongbaselibrary.ui.view.BaseTopBarView
android:id="@+id/btbv_aasa_top_bar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:visibility="invisible" />


<!-- 提示信息 -->
<TextView
android:id="@+id/tv_info"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="@+id/btbv_aasa_top_bar"
android:layout_marginTop="@dimen/dp_25"
android:gravity="center_horizontal"
android:text="@string/str_secret_protect_password_info"
android:textColor="@color/color_4390E1"
android:textSize="@dimen/sp_16" />

<cc.vv.btong.module_mine.view.MyPasswordView
android:id="@+id/ls_passwordView"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_below="@+id/tv_info"
android:layout_marginTop="@dimen/dp_24" />

<!-- 底部布局 -->
<RelativeLayout
android:id="@+id/rl_bottom"
android:layout_width="fill_parent"
android:layout_height="40dp"
android:layout_alignParentBottom="true"
android:layout_marginBottom="40dp"
android:paddingLeft="30dp"
android:paddingRight="30dp">
<!-- 重输按钮 -->
<TextView
android:id="@+id/tv_forget_pwd"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:onClick="doClick"
android:text="@string/str_forget_secret_protect_password_info"
android:textColor="#0f93df"
android:textSize="@dimen/dp_14" />

</RelativeLayout>

</RelativeLayout>

在application中判断程序是否切入后台
private void setSecurityCodeLock() {
AppFrontBackHelper helper = new AppFrontBackHelper();
helper.register(BTongApplication.this, new AppFrontBackHelper.OnAppStatusListener() {
@Override
public void onFront(boolean isLockScreenActivity) {
//应用切到前台处理

int lockScreenValue = UserManager.getScreenLockState();
if (lockScreenValue == 1) {
//安全密码锁已开启
if (UserManager.getAccountLogin()) {
//获取当前时间与保存的时间对比,大于30 秒开启锁屏界面
long forTimeMillis = System.currentTimeMillis();
if (forTimeMillis - backTimeMillis > LOCK_SCREEN_PERIOD) {
if (!isLockScreenActivity) {
Intent intent = new Intent(BTongApplication.this, LockScreenActivity.class);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
BTongApplication.this.startActivity(intent);
}
}
}
}
}

@Override
public void onBack() {
//应用切到后台处理
//记录当前时间
backTimeMillis = System.currentTimeMillis();
}
});
}

工具类
package cc.vv.btong.module_mine.utils;

/**
* Date 2018/2/3
* Describe 应用在后台和前台之间切换的监听
* <p>
* 原理: 根据activity数量来做判断, 按home键或者锁屏按钮的时候,就会执行onStop里面的方法,
* 当重新返回到应用中的时候,会走onResume里面的方法
*
* @auther liuxin
*/

import android.app.Activity;
import android.app.Application;
import android.os.Bundle;

import cc.vv.btong.module_mine.ui.activity.LockScreenActivity;


public class AppFrontBackHelper {
/**
* 切换监听
*/
private OnAppStatusListener mOnAppStatusListener;


public AppFrontBackHelper() {

}

/**
* 注册状态监听,仅在Application中使用,只有在application中可以拿到activity的状态
*
* @param application
* @param listener
*/
public void register(Application application, OnAppStatusListener listener) {
mOnAppStatusListener = listener;
application.registerActivityLifecycleCallbacks(activityLifecycleCallbacks);
}

private Application.ActivityLifecycleCallbacks activityLifecycleCallbacks = new Application.ActivityLifecycleCallbacks() {
//打开的Activity数量统计
private int activityStartCount = 0;

@Override
public void onActivityCreated(Activity activity, Bundle savedInstanceState) {

}

@Override
public void onActivityStarted(Activity activity) {
activityStartCount++;
//数值从0变到1说明是从后台切到前台
if (activityStartCount == 1) {
//从后台切到前台
if (mOnAppStatusListener != null) {

if (activity instanceof LockScreenActivity) {
mOnAppStatusListener.onFront(true);
} else {
mOnAppStatusListener.onFront(false);
}
}
}
}

@Override
public void onActivityResumed(Activity activity) {

}

@Override
public void onActivityPaused(Activity activity) {

}

@Override
public void onActivityStopped(Activity activity) {
activityStartCount--;
//数值从1到0说明是从前台切到后台
if (activityStartCount == 0) {
//从前台切到后台
if (mOnAppStatusListener != null) {
mOnAppStatusListener.onBack();
}
}
}

@Override
public void onActivitySaveInstanceState(Activity activity, Bundle outState) {

}

@Override
public void onActivityDestroyed(Activity activity) {

}
};

public interface OnAppStatusListener {
/**
* 从后台切到前台
*/
void onFront(boolean isLockScreenActivity);

/**
* 从前台切到后台
*/
void onBack();
}
}




posted @ 2018-05-17 17:18  嗨Dorr  阅读(863)  评论(0编辑  收藏  举报