但使书种多,会有岁稔时。这篇文章主要讲述Android开发——本地验证码的简易实现(防止暴力登录)相关的知识,希望能为你提供帮助。
0.前言
验证码无处不在,
有人问我,
你知道达芬奇密码下面是什么吗,
对,
答案就是达芬奇验证码。
验证码一个最主要的作用就是防止恶意暴力破解登录,
防止不间断的登录尝试,
其实可以在服务器端对该终端进行登录间隔检测,
如果间隔太短可以展示拒绝的姿态。但是还是本地验证码作用更加实在,
可以减轻服务器端的压力。这篇将使用自定义View来实现一个如下效果的简易本地验证码。算是对自定义View知识的复习吧。
文章图片
1.布局结构
<
RelativeLayout xmlns:android=
"
http://schemas.android.com/apk/res/android"
xmlns:myattribute=
"
http://schemas.android.com/apk/res-auto"
android:layout_width=
"
match_parent"
android:layout_height=
"
match_parent"
>
<
com.calvin.verification_code.MyView
android:layout_width=
"
wrap_content"
android:layout_height=
"
wrap_content"
android:layout_centerInParent=
"
true"
android:padding=
"
10dp"
myattribute:text=
"
0 0 0 0 "
myattribute:textcolor=
"
#000"
myattribute:textsize=
"
40sp"
android:id=
"
@
+
id/myView"
/>
<
EditText
android:layout_width=
"
wrap_content"
android:layout_height=
"
wrap_content"
android:inputType=
"
number"
android:hint=
"
刷新后输入"
android:layout_below=
"
@
+
id/myView"
android:layout_centerHorizontal=
"
true"
android:layout_marginTop=
"
20dp"
android:id=
"
@
+
id/editText"
/>
<
Button
android:text=
"
确认"
android:layout_width=
"
wrap_content"
android:layout_height=
"
wrap_content"
android:layout_alignBottom=
"
@
+
id/editText"
android:layout_alignParentEnd=
"
true"
android:layout_marginEnd=
"
10dp"
android:id=
"
@
+
id/button"
/>
<
/RelativeLayout>
在自定义控件MyView中使用了自定义属性, 面试的时候偶尔也会被问到, 其实并不难。这里使用文字内容、颜色和字号三个自定义属性。命名空间别忘了加。
自定义属性声明只需要在values目录下声明一个xml文件即可。文件名字不重要, 重要的是这个name属性, 因为我们会在自定义控件类中通过R.styleable.MyView来找到这个自定义属性声明信息。
<
?xml version=
"
1.0"
encoding=
"
utf-8"
?>
<
resources>
<
declare-styleable name=
"
MyView"
>
<
attr name=
"
text"
format=
"
string"
/>
<
attr name=
"
textcolor"
format=
"
color"
/>
<
attr name=
"
textsize"
format=
"
dimension"
/>
<
/declare-styleable>
<
/resources>
2.自定义View类
看一下这个类的构造函数:
public MyView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
TypedArray a =
context.obtainStyledAttributes(attrs, R.styleable.MyView);
for (int i =
0;
i <
a.getIndexCount();
i+
+
) {
int attr =
a.getIndex(i);
switch (attr) {
case R.styleable.MyView_text:
mText =
a.getString(attr);
break;
case R.styleable.MyView_textcolor:
//二参为默认颜色
mTextColor =
a.getColor(attr, Color.BLACK);
break;
case R.styleable.MyView_textsize:
// 默认字体大小为16sp,
TypeValue把sp转化为px
mTextSize =
a.getDimensionPixelSize(attr,
(int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_SP,
16, getResources().getDisplayMetrics()));
break;
}
}
a.recycle();
mPaint =
new Paint();
mPaint.setTextSize(mTextSize);
mBound =
new Rect();
//获得绘制文本的宽和高
mPaint.getTextBounds(mText, 0, mText.length(), mBound);
this.setOnClickListener(new OnClickListener() {
@
Override
public void onClick(View v) {
//生成一个随机的四位数字,
并发送一个自定义广播
mText =
randomText();
postInvalidate();
}});
}
核心代码就是解析自定义属性, 并初始化一个画笔, 并把解析出来的字体大小设置给画笔, 设计点击时间, 使其被点击后重新随机产生四位数字验证码, 并使用postInvalidate()刷新界面。最后使用mBound记录这个四位数文本的宽高。
2.自定义View类中的其他细节
@
Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
int width =
0;
int height =
0;
int specMode =
MeasureSpec.getMode(widthMeasureSpec);
int specSize =
MeasureSpec.getSize(widthMeasureSpec);
switch (specMode) {
case MeasureSpec.EXACTLY:
width =
getPaddingLeft() +
getPaddingRight() +
specSize;
break;
case MeasureSpec.AT_MOST:
width =
getPaddingLeft() +
getPaddingRight() +
mBound.width();
break;
}
//同样逻辑处理高
setMeasuredDimension(width, height);
}@
Override
protected void onDraw(Canvas canvas) {
mPaint.setColor(Color.YELLOW);
canvas.drawRect(0, 0, getMeasuredWidth(), getMeasuredHeight(), mPaint);
mPaint.setColor(mTextColor);
canvas.drawText(mText, getWidth() / 2 - mBound.width() / 2, getHeight() / 2 +
mBound.height() / 2, mPaint);
Random random =
new Random();
for(int i =
0;
i <
=
3;
i+
+
){
int temp =
random.nextInt(colors.length);
mPaint.setColor(colors[temp]);
mPaint.setStrokeWidth(3);
canvas.drawLine(randomStartWidth(),randomStartHeight(),randomEndWidth(),randomEndHeight(),mPaint);
}
}
【Android开发——本地验证码的简易实现(防止暴力登录)】其实主要还是measure和draw的过程了。
在onMeasure()方法中最重要的逻辑应该就是处理MeasureSpec.AT_MOST的这种情况了, 这时候前面的mBound.width()就起作用了。还有就是不管何种测量模式, 都手动处理了padding的情况。
onDraw()方法中首先绘制了一个黄色矩形作为自定义View的背景, 接着根据自定义属性中的文字内容和颜色绘制四位数字, 最后绘制四条噪声直线, 颜色随机, 并且起始位置和结束位置也是随机产生的。
3.实时改变维护的正确验证码
为了验证用户输入的验证码的正确性, 需要在MainActivity中维护一个变量, 在用户点击自定义View刷新验证码时, 能够实时改变这个变量的值。这里使用自定义广播实现, 在生成一个随机的四位数字, 发送一个自定义广播。
Intent intent =
new Intent();
intent.setAction("
com.seu_calvin.update"
);
intent.putExtra("
data"
, sb.toString());
getContext().sendBroadcast(intent);
接着在MainActivity注册一个广播接收者即可取得此时的验证码信息, 在用户点击确定按钮后在拿到EditText中的值与其进行对比即可。这个逻辑还是比较简单的。
笔者水平有限, 如果有问题或者错误请多留言交流。转载请注明出处: http://blog.csdn.net/seu_calvin/article/details/70156547。
推荐阅读
- AppStore下载Xcode的文件
- Android ListView圆角
- Android启动篇 — init原理
- Android笔记(SurfaceView与SurfaceHolder对象)
- android goback 问题
- android设备不识别awk命令,缺少busybox
- 如何解决( Server Error in '/' Application.)
- Android - View之View的位置参数
- android中使用图文并茂的按钮