(转载)Android项目实战(二十八):Zxing二维码实现及优化
Android项目实战(二十八):Zxing二维码实现及优化
前言:
多年之前接触过zxing实现二维码,没想到今日项目中再此使用竟然使用的还是zxing,百度之,竟是如此牛的玩意。
当然,项目中我们也许只会用到二维码的扫描和生成两个功能,所以不必下载完整的jar包,使用简化版的即可,下文可见。
这篇文章讲述:1、如果快速在项目中集成zxing,实现扫描和生成二维码功能
2、根据项目需求去修改源码实现我们的要求并进行优化
一、快速集成zxing二维码
1、下载库文件 : http://download.csdn.NET/detail/u013210620/9036083 ,文件名:BarCodeTest
下载完成后可以看到:
我们从这些文件中拷贝需要的到自己的项目中,下面开始:
①、res 目录下 : raw文件夹 整个复制到个人项目相对位置
②、res --> values目录下:ids.xml文件中的内容全部复制到个人项目相对位置,个人项目没有则直接复制文件到相对位置
③、res --> values目录下:colors.xml文件中的内容全部复制到个人项目的相对位置
④、res --> layout目录下:camera.xml 布局文件复制到个人项目相对位置
⑤、res --> drawable_mdpi 目录下:navbar.9.png图片复制到个人项目相对位置,这张图片是标题栏背景图片,这里建议先改成navbar.png 不要使用.9图片
⑥、libs目录下:zxing.jar文件复制到个人项目相对位置,并且右键点击as library
⑦、src --> com目录下:zxing 文件夹复制到个人项目相对位置 ,会报错,修改R的目录结构即可
⑧、AndroidManifest.xml文件中 添加 (二维码扫描activity,这个需要后面自己去修改,用于实现自己的要求)
- <activity android:name="com.zxing.activity.CaptureActivity"/>
⑨、AndroidManifest.xml文件中 添加权限
- <uses-permission android:name="android.permission.CAMERA" />
- <uses-permission android:name="android.permission.VIBRATE" />
- <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
- <uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS" />
- <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
2、准备工作完成了,下面开始写demo
现在需求是一个主界面MainActivity.java 里面有两个按钮,分别跳转 生成二维码界面和 扫描二维码界面
然后分别开始写两个activity功能的实现:
①、 生成二维码
先写布局文件 ,一个图片 , 一个开始生成按钮 , 一个输入框(二维码需要根据文本信息生成,没有文本信息无法生成)
activity代码: 代码比较简单 ,不在此解释了

- private ImageView create_img;
- private Button create_btn;
- private EditText create_edit;
- @Override
- protected void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- setContentView(R.layout.activity_create);
- initView();
- initEvent();
- }
- private void initEvent() {
- create_btn.setOnClickListener(this);
- }
- private void initView() {
- create_img = (ImageView) findViewById(R.id.create_img);
- create_btn = (Button) findViewById(R.id.create_btn);
- create_edit = (EditText) findViewById(R.id.create_edit);
- }
- @Override
- public void onClick(View v) {
- switch (v.getId()){
- case R.id.create_btn:
- String content = "" ;
- if (create_edit.getText().toString().equals("")){
- Toast.makeText(this,"请输入二维码信息",Toast.LENGTH_SHORT).show();
- return;
- }
- content = create_edit.getText().toString();
- try {
- //生成二维码图片,第一个参数是二维码的内容,第二个参数是正方形图片的边长,单位是像素
- Bitmap qrcodeBitmap = EncodingHandler.createQRCode(content, 800);
- if (qrcodeBitmap!=null) {
- create_img.setImageBitmap(qrcodeBitmap);
- }else{
- Toast.makeText(this,"生成二维码失败",Toast.LENGTH_SHORT).show();
- }
- } catch (Exception e) {
- // TODO Auto-generated catch block
- e.printStackTrace();
- }
- break;
- }
- }
- public byte[] Bitmap2Bytes(Bitmap bm) {
- ByteArrayOutputStream baos = new ByteArrayOutputStream();
- bm.compress(Bitmap.CompressFormat.PNG, 100, baos);
- return baos.toByteArray();
- }

效果图:
②、扫描二维码
这个就更简单了,只需要打开一个zxing提供的activity 然后获取到扫描得到的字符串即可
看ScanActivity(扫描Activity)的关键代码

- private TextView zxing_content;
- @Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_scan);
zxing_content = (TextView) findViewById(R.id.zxing_content);
Intent startScan = new Intent(this,CaptureActivity.class);
startActivityForResult(startScan, 0); //实际打开了一个zxing提供给我们的扫描activity,当然我们后面会对这个activity进行一些优化修改- }
- /**
* 扫一扫,成功后返回值进行判断
*/
@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (resultCode == -1) {
String result = data.getExtras().getString("result");
zxing_content.setText(result); //显示扫描二维码得到的数据
}
}

布局文件:
效果图:
二、修改源码,实现项目的需求
1、修改扫描二维码的界面
对应的是 zxing-->activity-->CaptureActivity.java ,布局文件为 camera.xml
所以修改界面只需要在 camera.xml文件中修改即可。
无非就是把原来的“CANCEL”取消按钮去掉,把顶部的标题栏换一下。
布局里面有一个 <SurfaceView>控件 用于显示相机拍出的画面预览,这里可以根据需求改是全界面显示还是显示局部
<com.zxing.view.ViewfinderView>控件,即扫描框,默认的是宽高比1:1.5,实际需要修改宽高,在下面介绍
2、修改扫描框的宽高
第1步操作做完之后会发现,我们没法修改扫描框的宽高。
修改扫描框宽高很简单,找到 zxing-->camera-->CameraManager.java 文件
这里较为顶部的代码中看到:
- private static final int MIN_FRAME_WIDTH = 240;
- private static final int MIN_FRAME_HEIGHT = 240;
- private static final int MAX_FRAME_WIDTH = 480;
- private static final int MAX_FRAME_HEIGHT = 480;
这四个属性的值即扫描框的宽高,然后可以根据需求直接修改,当然这个值在不同分辨率的设备上宽高不一致 , 有需要的话可以进行一下单位转换
- public static int Dp2Px( Context context,float dp) {
- final float scale = context.getResources().getDisplayMetrics().density;
- return (int) (dp * scale + 0.5f);
- }
效果图: 我修改了扫描框的最小最大宽高分别一致,并且载camera.xml布局中删去了“CANCEL”取消按钮
3、给扫描框添加文字提示
看一下微信的扫描界面,会发现扫描框下面有一段文字提示。 那么我们这里没有,需要添加
找到zxing-->view-->Viewfinderview.java
这里是自定义扫描框的类
找到代码:
- canvas.drawRect(frame.left + 2, middle - 1, frame.right - 1, middle + 2, paint);
- Collection<ResultPoint> currentPossible = possibleResultPoints;
在这两行代码之间我们画上文字提示

- canvas.drawRect(frame.left + 2, middle - 1, frame.right - 1, middle + 2, paint);
- TextPaint textPaint = new TextPaint();
- textPaint.setARGB(0xFF, 0xFF, 0xFF,0xFF); //字体颜色
- textPaint.setTextSize(32); //字体大小
- textPaint.setAntiAlias(true); //设置抗锯齿,否则字迹会很模糊
- StaticLayout layout = new StaticLayout("将二维码放入框内,即可自动扫描",textPaint,
- frame.right-frame.left, Layout.Alignment.ALIGN_NORMAL,1.0F,0.0F,true);
- canvas.translate(frame.left+5, (float) (frame.bottom + (float)30)); //绘制起始位置
- layout.draw(canvas);
- Collection<ResultPoint> currentPossible = possibleResultPoints;

然后在看下扫描界面效果图:
4、解决扫描界面相机预览拉伸变形问题
实现了上面几步的优化,仔细的同学可能会发现,如果我们给SurfaceView设置全屏显示(可以看到的相机画面很多),会发现相机拍摄出来的预览图有些拉伸变形
原因:zxing横屏变竖屏之后,Camera的代码还是采用的横屏代码设置的参数
优化方法:找到 zxing-->camera--> CameraConfigurationManager.java

- initFromCameraParameters方法中,
- 在 Log.d(TAG, "Screen resolution: " + screenResolution);这句之后增加
- Point screenResolutionForCamera = new Point();
- screenResolutionForCamera.x = screenResolution.x;
- screenResolutionForCamera.y = screenResolution.y;
- if (screenResolution.x < screenResolution.y) {
- screenResolutionForCamera.x = screenResolution.y;
- screenResolutionForCamera.y = screenResolution.x;
- }
- 再将cameraResolution = getCameraResolution(parameters, screenResolution);
- 更改为
- cameraResolution = getCameraResolution(parameters, screenResolutionForCamera);

完成之后,在进行扫描操作,这时候相机拍出来的预览界面就正常显示,不再有拉伸变形问题。
至此便给项目引入了一个可以使用的二维码模块功能了。
(转载)Android项目实战(二十八):Zxing二维码实现及优化的更多相关文章
- Android项目实战(十二):解决OOM的一种偷懒又有效的办法
在程序的manifest文件的application节点加入android:largeHeap=“true” 即可. 对,只需要一句话! 那么这行代码的意思是什么呢? 简单的说就是使该APP获取最大可 ...
- Android项目实战(十九):Android Studio 优秀插件: Parcelable Code Generator
Android Studio 优秀插件系列: Android Studio 优秀插件(一):GsonFormat Android Studio 优秀插件(二): Parcelable Code Gen ...
- Android开发实战(十八):Android Studio 优秀插件:GsonFormat
Android Studio 优秀插件系列: Android Studio 优秀插件(一):GsonFormat Android Studio 优秀插件(二): Parcelable Code Gen ...
- 【慕课网实战】Spark Streaming实时流处理项目实战笔记十八之铭文升级版
铭文一级: 功能二:功能一+从搜索引擎引流过来的 HBase表设计create 'imooc_course_search_clickcount','info'rowkey设计:也是根据我们的业务需求来 ...
- Android项目实战(十六):QQ空间实现(一)—— 展示说说中的评论内容并有相应点击事件
大家都玩QQ空间客户端,对于每一个说说,我们都可以评论,那么,对于某一条评论: 白雪公主 回复 小矮人 : 你们好啊~ 我们来分析一下: .QQ空间允许我们 点击 回复人和被回复人的名字就可以进入对于 ...
- Android项目实战(十四):TextView显示html样式的文字
项目需求: TextView显示一段文字,格式为:(消息个数,不确定)条消息 这段文字中名字和数字的长度是不确定的,还要求名字和数字各自有各自的颜色. 一开始我想的是用(转) SpannableStr ...
- Android项目实战(十):自定义倒计时的TextView
项目总结 -------------------------------------------------------------------------------------------- 有这 ...
- android 项目学习随笔十八(三级缓存)
xUtils的BitmapUtils模块用的就是三级缓存,在项目中尽量还是应用BitmapUtils 三级缓存(机制) import com.itheima.zhsh66.R; import andr ...
- Android项目实战(十五):自定义不可滑动的ListView和GridView
不可滑动的ListView (RecyclweView类似) public class NoScrollListView extends ListView { public NoScrollListV ...
- (二十八)golang--二维数组
初始化: var array [2][3]int = [2][3]int{{0,0,0},{0,0,0}} var array [2][3]int = [...][3]int{{0,0,0},{0,0 ...
随机推荐
- anuglar.js ui-router传递参数
anuglar.js ui-router 传递参数的方法有: 一: ui-sref 传递参数,传递一个参数的时候 首先路有这样写: .state('edit', { //线路编辑页面 url: '/e ...
- 【转】Oralce基础—Sqlplus工具运用 礼记八目 2017-12-20 20:22:45
原文地址:https://www.toutiao.com/i6501603661565657614/ 一.数据库连接: sqlplus [user_name[/password][@ host_str ...
- 使用dom4j生成word的方法
http://blog.csdn.net/zhyh1986/article/details/8727523#t6 http://blog.csdn.net/zuozuofuwaiwai/article ...
- Java根据HttpServletRequest请求获取服务器的IP地址
以下总结了两种根据HttpServletRequest请求获取发出请求浏览器客户端所在服务器的IP地址方法: 代码: import javax.servlet.http.HttpServletRequ ...
- 路飞学城Python-Day182
Evernote Export 集群介绍 1.集群介绍 集群:将多个物理机器组成一个逻辑计算机,实现负载和容错 计算机集群简称集群,是一种计算机系统,它通过一组松散集成的计算机软件或硬件连接起来高度紧 ...
- jquery bind 传参数
方法一. ? 1 2 3 4 function GetCode(event) { alert(event.data.foo); } ? 1 2 3 4 $(document).ready(functi ...
- ASCII 码对照表
ASCII值 控制字符 ASCII值 控制字符 ASCII值 控制字符 ASCII值 控制字符 0 NUT 32 (space) 64 @ 96 . 1 SOH 33 ! 65 A 97 a 2 ST ...
- 51nod-完美字符串(贪心)
约翰认为字符串的完美度等于它里面所有字母的完美度之和.每个字母的完美度可以由你来分配,不同字母的完美度不同,分别对应一个1-26之间的整数. 约翰不在乎字母大小写.(也就是说字母F和f)的完美度相同. ...
- [luogu3237 HNOI2014] 米特运输 (树形dp)
传送门 Description 米特是D星球上一种非常神秘的物质,蕴含着巨大的能量.在以米特为主要能源的D星上,这种米特能源的运输和储存一直是一个大问题. D星上有N个城市,我们将其顺序编号为1到N, ...
- java实现QQ空间模拟登录
import java.io.File; import java.io.FileNotFoundException; import java.io.FileOutputStream; import j ...