zxing开源库的基本使用
如果你的项目中有模块跟二维码相关的话,那你一定听过或者用过大名鼎鼎的zxing开源库。
什么是zxing?
ZXing是一个开源的,用Java实现的多种格式的1D/2D条码图像处理库,它包含了联系到其他语言的端口。zxing可以实现使用手机的内置的摄像头完成条形码的扫描及解码。
本篇文章就来学习zxing的基本使用,学习了以下几个内容就能满足大部分项目中的二维码相关需求:
- 通过摄像头扫描二维码图片,读取图片内容
- 从相册中选取二维码图片,读取图片内容
- 自己输入字符串内容,生成二维码图片
- 长按识别自己生成的二维码图片
如何依赖zxing到项目中?
如果你还在使用zxing的jar包、或者你是把zxing的代码复制到项目中,使用这两种方式依赖的话那就out了,现在Android Studio可支持zxing在线依赖,目前最新版本是3.3.3。在线依赖的好处我就不多说了,相信大家都懂。
新建项目,在app/build.gradle文件中在线依赖:
implementation 'com.google.zxing:core:3.3.3'
加入权限
因为扫描二维码需要摄像头权限,把图片保存到本地需要sdcard权限,所以需要在AndroidManifest.xml中加入相应的权限
<uses-permission android:name="android.permission.CAMERA" />
<uses-permission android:name="android.permission.VIBRATE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-feature android:name="android.hardware.camera" />
<uses-feature android:name="android.hardware.camera.autofocus" />
当然现在市面上的手机大部分都是6.0以上的操作系统了,所以还得在MainActivity的onCreate方法中动态申请以上这两个权限。
//6.0版本或以上需请求权限
String[] permissions=new String[]{Manifest.permission.
WRITE_EXTERNAL_STORAGE, Manifest.permission.CAMERA};
if (Build.VERSION.SDK_INT > Build.VERSION_CODES.LOLLIPOP_MR1) {
requestPermissions(permissions,PERMS_REQUEST_CODE);
}
扫描二维码
项目依赖进来了,权限也有了,开始用代码实现第一个功能。点击扫描二维码按钮,开启一个ScanActivity,这个Activity是我之前封装好的,里面处理了扫描二维码的整个流程,扫描成功后会把扫描结果返回。ScanActivity类的代码有点多,就不贴出来了,有兴趣的自己看源码。
Intent intent = new Intent(MainActivity.this,ScanActivity.class);
startActivityForResult(intent,SCAN_REQUEST_CODE);
重写onActivityResult方法,监听扫描结果。
@Override
protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent intent) {
super.onActivityResult(requestCode, resultCode, intent);
if (requestCode == SCAN_REQUEST_CODE && resultCode == RESULT_OK) {
String input = intent.getStringExtra(ScanActivity.INTENT_EXTRA_RESULT);
showToast("扫描结果:"+input);
}
}
从相册中选择二维码图片进行识别
首先启动系统相册,从相册中选择一张图片。
Intent innerIntent = new Intent(Intent.ACTION_PICK,
MediaStore.Images.Media.EXTERNAL_CONTENT_URI);
Intent wrapperIntent = Intent.createChooser(innerIntent, "选择二维码图片");
startActivityForResult(wrapperIntent, SELECT_IMAGE_REQUEST_CODE);
然后在onActivityResult中获取选择图片路径,调用BitmapUtil.parseQRcode方法解析二维码图片。
@Override
protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent intent) {
super.onActivityResult(requestCode, resultCode, intent);
if(requestCode==SELECT_IMAGE_REQUEST_CODE){//从图库选择图片
String[] proj = {MediaStore.Images.Media.DATA};
// 获取选中图片的路径
Cursor cursor = this.getContentResolver().query(intent.getData(),proj, null, null, null);
if (cursor.moveToFirst()) {
int columnIndex = cursor.getColumnIndexOrThrow(MediaStore.Images.Media.DATA);
String photoPath = cursor.getString(columnIndex);
String result= BitmapUtil.parseQRcode(photoPath);
if (!TextUtils.isEmpty(result)) {
showToast("从图库选择的图片识别结果:"+result);
} else {
showToast("从图库选择的图片不是二维码图片");
}
}
cursor.close();
}
}
接下来看parseQRcode方法,
/**
* 解析二维码图片
* @param bitmapPath 文件路径
* @return
*/
public static String parseQRcode(String bitmapPath){
Bitmap bitmap = BitmapFactory.decodeFile(bitmapPath, null);
String result=parseQRcode(bitmap);
return result;
}
从上面的方法中看到直接把文件路径读取成Bitmap,继续调用parseQRcode方法把Bitmap对象传进去,这里用到了方法重载。
public static String parseQRcode(Bitmap bmp){
bmp=comp(bmp);//bitmap压缩 如果不压缩的话在低配置的手机上解码很慢
int width = bmp.getWidth();
int height = bmp.getHeight();
int[] pixels = new int[width * height];
bmp.getPixels(pixels, 0, width, 0, 0, width, height);
QRCodeReader reader = new QRCodeReader();
Map<DecodeHintType, Object> hints = new EnumMap<>(DecodeHintType.class);
hints.put(DecodeHintType.TRY_HARDER, Boolean.TRUE);//优化精度
hints.put(DecodeHintType.CHARACTER_SET,"utf-8");//解码设置编码方式为:utf-8
try {
Result result = reader.decode(new BinaryBitmap(
new HybridBinarizer(new RGBLuminanceSource(width, height, pixels))), hints);
return result.getText();
} catch (NotFoundException e) {
Log.i("ansen",""+e.toString());
e.printStackTrace();
} catch (ChecksumException e) {
e.printStackTrace();
} catch (FormatException e) {
e.printStackTrace();
}
return null;
}
如果传入的是一个Bitmap对象,先调用comp方法对Bitmap进行压缩(压缩代码这里不贴出),获取图片宽高,把图像的每个像素颜色转为int值,存入pixels数组。
然后初始化QRCodeReader对象,调用decode方法进行解码,这个方法有两个参数,参数1是一个BinaryBitmap对象,第二个参数是一个Map类型,key的值是DecodeHintType枚举类型,这里我们put了两个值,优化精度跟设置编码方式为。这个方法还会返回一个Result对象,最后调用result.getText()方法获取二维码内容。
生成二维码图片
生成二维码图片调用CreateQRBitmp.createQRCodeBitmap方法生成,这个方法是我们自己封装的,需要传入两个参数,参数1:图片内容、参数2:二维码图片最中间显示的logo(Bitmap对象)。
String contentString = etInput.getText().toString().trim();
if(TextUtils.isEmpty(contentString)){
showToast("请输入二维码内容");
return ;
}
Log.i("ansen","输入的内容:"+contentString);
Bitmap portrait = BitmapFactory.decodeResource(getResources(),R.mipmap.ic_launcher);
//两个方法,一个不传大小,使用默认
qrCodeBitmap = CreateQRBitmp.createQRCodeBitmap(contentString, portrait);
ivQrImage.setImageBitmap(qrCodeBitmap);
createQRCodeBitmap源码如下:
public static Bitmap createQRCodeBitmap(String content,Bitmap portrait) {
// 用于设置QR二维码参数
Hashtable<EncodeHintType, Object> qrParam = new Hashtable<>();
// 设置QR二维码的纠错级别——这里选择最高H级别
qrParam.put(EncodeHintType.ERROR_CORRECTION, ErrorCorrectionLevel.H);
// 设置编码方式
qrParam.put(EncodeHintType.CHARACTER_SET, "UTF-8");
// 生成QR二维码数据——这里只是得到一个由true和false组成的数组
// 参数顺序分别为:编码内容,编码类型,生成图片宽度,生成图片高度,设置参数
try {
BitMatrix bitMatrix = new MultiFormatWriter().encode(content,
BarcodeFormat.QR_CODE, QRCODE_SIZE, QRCODE_SIZE, qrParam);
// 开始利用二维码数据创建Bitmap图片,分别设为黑白两色
int w = bitMatrix.getWidth();
int h = bitMatrix.getHeight();
int[] data = new int[w * h];
for (int y = 0; y < h; y++) {
for (int x = 0; x < w; x++) {
if (bitMatrix.get(x, y))
data[y * w + x] = 0xff000000;// 黑色
else
data[y * w + x] = 0x00ffffff;// -1 相当于0xffffffff 白色
}
}
// 创建一张bitmap图片,采用最高的图片效果ARGB_8888
Bitmap bitmap = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888);
// 将上面的二维码颜色数组传入,生成图片颜色
bitmap.setPixels(data, 0, w, 0, 0, w, h);
if(portrait!=null){
createQRCodeBitmapWithPortrait(bitmap,initProtrait(portrait));
}
return bitmap;
} catch (WriterException e) {
e.printStackTrace();
}
return null;
}
大部分代码都有注释,首先就是调用MultiFormatWriter对象的encode方法生成BitMatrix对象,这里我们传入5个参数,参数1:内容、参数2:二维码格式、参数3:图片宽、参数4:图片高、参数5:二维码生成的参数(例如编码方法以及纠错级别)。
拿到BitMatrix对象后开始利用二维码数据创建Bitmap图片,分别设为黑白两色,创建一个宽高一样的Bitmap对象,调用setPixels方法把上面的二维码颜色数组传入,生成图片颜色。如果中间需要添加logo调用createQRCodeBitmapWithPortrait方法。最后把Bitmap对象返回。
长按识别二维码以及保存图片
识别二维码跟从相册中选择图片进行识别功能上很相似,所以就不在做重复介绍了,就介绍一下保存图片功能。
从下面源码中看到,首先获取rootView,从rootView中获取根布局的Bitmap,然后调用ImageUtil.savePicToLocal方法保存图片。
View view = getWindow().getDecorView().getRootView();//找到当前页面的根布局
view.setDrawingCacheEnabled(true);//禁用绘图缓存
view.buildDrawingCache();
Bitmap temBitmap = view.getDrawingCache();
ImageUtil.savePicToLocal(temBitmap,MainActivity.this);
//禁用DrawingCahce否则会影响性能 ,而且不禁止会导致每次截图到保存的是缓存的位图
view.setDrawingCacheEnabled(false);//识别完成之后开启绘图缓存
showToast("保存图片到本地成功");
ImageUtil.savePicToLocal方法也比较简单,就是把一个Bitmap保存到本地Sdcard上。需要注意的是记得发送一个广播,不然需要重启手机才能在系统相册中看到这个图片。
public static void savePicToLocal(Bitmap bitmap, Context context) {
String filePath=Environment.getExternalStorageDirectory()
.getAbsolutePath() + "/screen"+File.separator + System.currentTimeMillis() + ".png";
if (bitmap != null) {
try {
// 图片文件路径
Log.i("ansen", "filePath:" + filePath);
File file = new File(filePath);
if (!file.getParentFile().exists()) {
file.getParentFile().mkdirs();
}
FileOutputStream os = new FileOutputStream(file);
bitmap.compress(Bitmap.CompressFormat.PNG, 100, os);
Intent intent = new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE);
Uri uri = Uri.fromFile(new File(filePath));
intent.setData(uri);
context.sendBroadcast(intent);
os.flush();
os.close();
} catch (Exception e) {
}
}
}
代码终于写完了,接下来看看效果,由于模拟器没有摄像头,而真机又不能录制Gif图片,所以摄像头扫描二维码就不演示啦,大家自己下载源码运行查看效果。

当然少不了源码,下载地址如下:
如果你想第一时间看我的后期文章,扫码关注公众号,长期推送Android开发文章、最新动态、开源项目,让你各种涨姿势。
Android开发666 - 安卓开发技术分享
扫描二维码加关注

zxing开源库的基本使用的更多相关文章
- android 使用开源库zxing生成二维码,扫描二维码【转】
转自:http://blog.csdn.net/qq_16064871/article/details/52422723 zxing是一个开放源码的,用Java实现的多种格式的1D/2D条码图像处理库 ...
- 二维码扫描开源库ZXing定制化【转】
转自:http://www.cnblogs.com/sickworm/p/4562081.html 最近在用ZXing这个开源库做二维码的扫描模块,开发过程的一些代码修改和裁剪的经验和大家分享一下. ...
- 二维码扫描开源库ZXing定制化
最近在用ZXing这个开源库做二维码的扫描模块,开发过程的一些代码修改和裁剪的经验和大家分享一下. 建议: 如果需要集成到自己的app上,而不是做一个demo,不推荐用ZXing的Android外围开 ...
- 100个Github上Android开源库
项目名称 项目简介 1. react-native 这个是 Facebook 在 React.js Conf 2015 大会上推出的基于 JavaScript 的开源框架 React Native, ...
- GitHub上排名前100的Android开源库介绍(来自github)
本项目主要对目前 GitHub 上排名前 100 的 Android 开源库进行简单的介绍,至于排名完全是根据 GitHub 搜索 Java 语言选择 (Best Match) 得到的结果,然后过滤了 ...
- GitHub Top 100的Android开源库
摘要: 本项目主要对目前 GitHub 上排名前 100 的 Android 开源库进行简单的介绍, 至于排名完全是根据GitHub搜索Java语言选择「Best M... 本项目主要对目前 GitH ...
- GitHub 上排名前 100 的 Android 开源库进行简单的介绍
若有任何疑问可通过邮件或微博联系我 项目名称 项目简介 1. react-native 这个是 Facebook 在 React.js Conf 2015 大会上推出的基于 JavaScript 的开 ...
- GitHub开源库排名一百的简单介绍,值得收藏!
GitHub Android Libraries Top 100 简介 本项目主要对目前 GitHub 上排名前 100 的 Android 开源库进行简单的介绍, 至于排名完全是根据 GitHub ...
- iOS第三方开源库的吐槽和备忘(转)
原文:http://www.cocoachina.com/industry/20140123/7746.html 做iOS开发总会接触到一些第三方库,这里整理一下,做一些吐槽. 目前比较活跃的社区 ...
随机推荐
- iOS----KVC和KVO 详解
一. KVC 1.KVC介绍 KVC 就是键值编码(key-value-coding). 2.KVC 的主要作用: (1)通过键值路径为对象的属性赋值.主要是可以为私有的属性赋值. AppleView ...
- ubuntu16.04 服务器允许远程连接
ubuntu默认安装了openssh-client,openssh-server需要手动安装. 查看是否安装了ssh服务 apt-cache policy openssh-client openssh ...
- Man方法
Main方法相当一个主线程,JVM会自动寻找class文件中的main方法并执行(请思考tomcat加载java web项目启动的线程数和每次tomcat服务器接收到请求,是不是要发起一个线程去处理) ...
- Tomcat中server.xml配置详解(2)
Tomcat中配置文件详解 Server.xml配置文件说明,以及Tomcat组件的说明 Tomcat服务器是由一系列可以配置的组件构成,其中核心组件是Catalina Servlet,它是最顶层组件 ...
- API防重放机制
说说API的防重放机制 我们在设计接口的时候,最怕一个接口被用户截取用于重放攻击.重放攻击是什么呢?就是把你的请求原封不动地再发送一次,两次...n次,一般正常的请求都会通过验证进入到正常逻辑中,如果 ...
- secureCRT常见命令
一.ls 只列出文件名 (相当于dir,dir也可以使用) -A:列出所有文件,包含隐藏文件. -l:列表形式,包含文件的绝大部分属性. -R:递归显示. --help:此命令的帮助. 二.cd 改变 ...
- kubernetes 安装kong、kong-ingress-controlor
一.关于kong的详细内容这里不再赘述,可以查看官网. kong升级到1.0以后功能越来越完善,并切新版本的kong可以作为service-mesh使用,并可以将其作为kubernetes的ingre ...
- HBuilder的安装及用法
一,简介HBuilder 1.1,什么是Hbuilder? HBuilder是DCloud(数字天堂)推出的一款支持HTML5的Web开发IDE.HBuilder的编写用到了Java.C.Web和Ru ...
- MariaDB/MySQL备份和恢复(二):数据导入、导出
MariaDB/MySQL备份恢复系列: 备份和恢复(一):mysqldump工具用法详述 备份和恢复(二):导入.导出表数据 备份和恢复(三):xtrabackup用法和原理详述 1.导出.导入数据 ...
- Perl列表相关函数
内置的列表函数有: grep, join, map, qw//, reverse, sort, unpack join:将多个元素使用给定字符串联起来join grep:从列表中筛选符合条件的元素执行 ...