Android图形验证码
1. 前言
图形验证码可以让服务器以图片的形式传给客户端,也可以让客户端自己实现。那客户端要怎么做呢?其实很简单,可以使用Android的Canvas、Paint和Random来实现。用Random来随机生成数字、字母、颜色、画笔原点等等,设置Paint的颜色和样式,然后再Canvas上面绘制,这样一个图形验证码就生成好了。
2. 具体实现
根据上面所说的,我们可以封装一个工具类来使用,详细功能有:
- 自定义验证码类型:数字、字母、数字字母组合
- 自定义验证码大小
- 自定义验证码背景颜色
- 自定义干扰线数量
- 自定义字体大小、数量、间距
具体代码如下:
package com.fantasy.blogdemo.captcha;import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;import java.util.Random;/*** 图形验证码工具* <pre>* author : Fantasy* version : 1.0, 2019-06-27* since : 1.0, 2019-06-27* </pre>*/
public class Captcha {private static final char[] CHARS_NUMBER = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9'};private static final char[] CHARS_LETTER = {'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j','k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w','x', 'y', 'z', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J','K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W','X', 'Y', 'Z'};private static final char[] CHARS_ALL = {'0', '1', '2', '3', '4', '5', '6','7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j','k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w','x', 'y', 'z', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J','K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W','X', 'Y', 'Z'};/*** 验证码图片的宽度*/private int mWidth;/*** 验证码图片的高度*/private int mHeight;private int mBackgroundColor;/*** 验证码的长度*/private int mLength;/*** 干扰线的数量*/private int mLineNumber;private int mFontSize;/*** 字体左边距*/private int mFontPaddingLeft;/*** 字体左边距范围值*/private int mFontPaddingLeftRang;/*** 字体上边距*/private int mFontPaddingTop;/*** 字体上边距范围值*/private int mFontPaddingTopRang;private TYPE mType;private Random mRandom;private static Captcha mInstance;/*** 生成的验证码*/private String mCode;public enum TYPE {NUMBER, LETTER, CHARS}private Captcha() {mType = TYPE.CHARS;mWidth = 200;mHeight = 80;mBackgroundColor = Color.WHITE;mLength = 4;mLineNumber = 2;mFontSize = 50;mFontPaddingLeft = 20;mFontPaddingLeftRang = 20;mFontPaddingTop = 45;mFontPaddingTopRang = 15;mRandom = new Random();}public static Captcha getInstance() {if (mInstance == null) {synchronized (Captcha.class) {mInstance = new Captcha();}}return mInstance;}/*** 设置验证码类型,有:数字、英文字母、数字加英文字母** @param type 类型* @return CaptchaUtils实例*/public Captcha setType(TYPE type) {mType = type;return mInstance;}/*** 设置验证码图片大小** @param width 宽度* @param height 高度* @return CaptchaUtils实例*/public Captcha setSize(int width, int height) {mWidth = width;mHeight = height;return mInstance;}/*** 设置背景颜色** @param color 颜色* @return CaptchaUtils实例*/public Captcha setBackgroundColor(int color) {mBackgroundColor = color;return mInstance;}/*** 设置验证码的长度** @param length 长度* @return CaptchaUtils实例*/public Captcha setLength(int length) {mLength = length;return mInstance;}/*** 设置干扰性数量** @param number 数量* @return CaptchaUtils实例*/public Captcha setLineNumber(int number) {mLineNumber = number;return mInstance;}/*** 设置字体大小** @param size 字体大小* @return CaptchaUtils实例*/public Captcha setFontSize(int size) {mFontSize = size;return mInstance;}/*** 设置字体间距** @param paddingLeft 左边距* @param paddingTop 上边距* @return CaptchaUtils实例*/public Captcha setFontPadding(int paddingLeft, int paddingTop) {mFontPaddingLeft = paddingLeft;mFontPaddingTop = paddingTop;return mInstance;}/*** 设置字体间距** @param paddingLeft 左边距* @param paddingLeftRang 左边距范围值* @param paddingTop 上边距* @param paddingTopRang 上边距范围值* @return CaptchaUtils实例*/public Captcha setFontPadding(int paddingLeft, int paddingLeftRang, int paddingTop,int paddingTopRang) {mFontPaddingLeft = paddingLeft;mFontPaddingLeftRang = paddingLeftRang;mFontPaddingTop = paddingTop;mFontPaddingTopRang = paddingTopRang;return mInstance;}/*** 获取生成的图形验证码** @return 图形验证码的字符串*/public String getCode() {return mCode;}/*** 生成图形验证码** @return 图形验证码的图片*/public Bitmap create() {mCode = createCode();Bitmap bitmap = Bitmap.createBitmap(mWidth, mHeight, Bitmap.Config.ARGB_8888);Canvas canvas = new Canvas(bitmap);canvas.drawColor(mBackgroundColor);Paint paint = new Paint();paint.setTextSize(mFontSize);int fontPaddingLeft = 0;for (int i = 0; i < mCode.length(); i++) {getRandomTextStyle(paint);fontPaddingLeft += getRandomFontPaddingLeft();canvas.drawText(String.valueOf(mCode.charAt(i)), fontPaddingLeft, getRandomFontPaddingTop(), paint);}for (int i = 0; i < mLineNumber; i++) {drawLine(canvas, paint);}canvas.save();canvas.restore();return bitmap;}/*** 生成图形验证码** @return 图形验证码的字符串*/private String createCode() {StringBuilder buffer = new StringBuilder();switch (mType) {case NUMBER:for (int i = 0; i < mLength; i++) {buffer.append(CHARS_NUMBER[mRandom.nextInt(CHARS_NUMBER.length)]);}break;case LETTER:for (int i = 0; i < mLength; i++) {buffer.append(CHARS_LETTER[mRandom.nextInt(CHARS_LETTER.length)]);}break;case CHARS:for (int i = 0; i < mLength; i++) {buffer.append(CHARS_ALL[mRandom.nextInt(CHARS_ALL.length)]);}break;default:for (int i = 0; i < mLength; i++) {buffer.append(CHARS_ALL[mRandom.nextInt(CHARS_ALL.length)]);}break;}return buffer.toString();}/*** 获取随机颜色** @return 颜色*/private int getRandomColor() {int red = mRandom.nextInt(256);int green = mRandom.nextInt(256);int blue = mRandom.nextInt(256);return Color.rgb(red, green, blue);}/*** 获取随机文本样式** @param paint 涂料*/private void getRandomTextStyle(Paint paint) {int color = getRandomColor();paint.setColor(color);paint.setFakeBoldText(mRandom.nextBoolean()); // true为粗体,false为非粗体int skewX = mRandom.nextInt(11) / 10;skewX = mRandom.nextBoolean() ? skewX : -skewX;paint.setTextSkewX(skewX); // 负数表示右斜,整数左斜// paint.setUnderlineText(true); // true为下划线,false为非下划线// paint.setStrikeThruText(true); // true为删除线,false为非删除线}/*** 获取随机字体左边距** @return 左边距*/private int getRandomFontPaddingLeft() {return mFontPaddingLeft + mRandom.nextInt(mFontPaddingLeftRang);}/*** 获取随机字体上边距** @return 上边距*/private int getRandomFontPaddingTop() {return mFontPaddingTop + mRandom.nextInt(mFontPaddingTopRang);}/*** 生成干扰性** @param canvas 画布* @param paint 涂料*/private void drawLine(Canvas canvas, Paint paint) {int color = getRandomColor();int startX = mRandom.nextInt(mWidth);int startY = mRandom.nextInt(mHeight);int stopX = mRandom.nextInt(mWidth);int stopY = mRandom.nextInt(mHeight);paint.setStrokeWidth(1);paint.setColor(color);canvas.drawLine(startX, startY, stopX, stopY, paint);}}
3. 使用方式
获取实例并设置
mCaptcha = Captcha.getInstance().setType(Captcha.TYPE.CHARS).setSize(200, 80).setBackgroundColor(Color.WHITE).setLength(4).setLineNumber(2).setFontSize(50).setFontPadding(20, 20, 45, 15);
生成图形验证码,并且在ImageView中显示
mIvCaptcha.setImageBitmap(mCaptcha.create());
获取验证码的字符串,可用于比对输入是否正确
if (result.equals(mCaptcha.getCode())) {showToast(R.string.captcha_correct);
} else {showToast(R.string.captcha_wrong);
}
4. 效果图
想看完整代码可以到我的GitHub上面看看BlogDemo。
如果想进一步交流和学习的同学,可以加一下QQ群哦!
Android图形验证码相关推荐
- Android图形验证码工具类
移动端获取图形验证码有两种形式,一种是在本地随机生成进行验证,另一种是根据服务端返回的图片流设置到页面上,今天我们要做的就是根据服务端返回的操作图形验证码,完整demo地址:https://downl ...
- android请求动态验证码,androidstudio实现图形验证码
androidstudio实现图形验证码 xml文件: android:layout_width="match_parent" android:layout_height=&quo ...
- Django博客系统注册(图形验证码接口设计和定义)
1. 准备captcha包(该包用于生成图形验证码) 1.将生成图片验证码的库复制到新建的libs包中. 2.安装Python处理图片的库 这儿可能会变红显示错误: 解决方案:在虚拟环境中安装Pill ...
- 美多商城之验证码(图形验证码)
一.图形验证码 1.1 图形验证码逻辑分析 需要新建应用verifications 知识要点 将图形验证码的文字信息保存到Redis数据库,为短信验证码做准备. UUID 用于唯一区分该图形验证码属于 ...
- 4.Spring Security 添加图形验证码
添加验证码大致可以分为三个步骤:根据随机数生成验证码图片:将验证码图片显示到登录页面:认证流程中加入验证码校验.Spring Security的认证校验是由UsernamePasswordAuthen ...
- Python模拟登录,Python识别图形验证码实现自动登陆
前言 利用Python识别图形验证码,selenium模块实现自动登陆.废话不多说. 让我们愉快地开始吧~ 开发工具 Python版本: 3.6.4 相关模块: re: numpy模块: pytess ...
- 前端 验证码隐藏怎么实现_完成图形验证码
使用 svg-captcha 这个包并结合后端实现图形验证码功能. 基本使用 在我们项目中安装 svg-captcha 包. $ npm install svg-captcha --save 官方文档 ...
- java验证码局部刷新_JS局部刷新图形验证码
开发过程当中,网络安全采取的方法之一,采用验证码功能.一般在注册.登录的程序当中见得比较多.其自己在实现这一功能时,静态页面有一段调用图形验证码的PHP文件,//,验证码是随机生成的,一般将生成的验证 ...
- 图形验证码最佳攻略2
下面是注册 如果是手机用户注册,需要发送短信验证码 说明: 发送图形验证码是为了拦截发送短信的.但是不拦截"注册帐号" 但是,用户体验很别扭,因为图形验证码很显然是错误的,但是却 ...
最新文章
- 慢动作频闪怎么解决_Vlog的视频解决方案——索尼A6400
- 为什么要用OKR?OKR在什么情况下用?
- 20159208 《网络攻防实践》第七周学习总结
- 数据单位:bit、Byte、KB、MB、GB、TB、PB、EB、ZB、YB、BB、NB、DB、、、
- linux crm高可用网卡,Linux运维——pacemaker实现高可用-Go语言中文社区
- step1 . day4 C语言基础练习之日历
- 实验八——函数定义及调用总结
- php获得指定目录文件,PHP遍历指定文件夹获取路径及大小(包含子文件夹)
- jggrid使用multiselect时修改默认排序
- 单目视觉里程计 mono vo
- JVM中8种垃圾收集器小结
- 2022年计算机专业程序员笔记本电脑推荐
- ServletResponse的常用方法:getWriter,setContentType
- JavaScript 设计模式之-单例模式(Singleton Pattern)
- 网站seo优化方式途径
- 自恢复保险丝与一次性保险丝较量,孰强孰弱
- Tenth season fifth episode,Rachel‘s sister came again???????
- 德鲁克日志读后感之五十三
- 使用k3s部署轻量Kubernetes集群快速教程
- C/C++ 与 Python
热门文章
- 关于AJAX的ScriptManager.RegisterClientScriptBlock无法弹出对话框的解决方法【归类】
- OpenCV3特征提取与目标检测之HOG(一)——HOG的概述与原理
- 服务器命令栏不显示,Linux栏 Linux指令(未完)
- 国产公链一哥:BUMO技术领先在哪里?
- android手机寿命,手机寿命有多长 苹果用3年而安卓只有2年
- 2008的最后.期盼
- mysql mgr监控_MGR监控报警
- 当我不再依赖你的时候说说_「精选」关于依赖一个人的说说()-说说控
- 谷歌性能测评工具lighthouse使用
- 计算机文件名正确胶卷成功,吴宪