当前位置: 移动技术网 > IT编程>移动开发>Android > Android中的二维码生成与扫描功能

Android中的二维码生成与扫描功能

2019年07月24日  | 移动技术网IT编程  | 我要评论

攀枝花恒大城,黑龙江省省长,品客堂

0. 前言

今天这篇文章主要描述二维码的生成与扫描,使用目前流行的zxing,为什么要讲二维码,因为二维码太普遍了,随便一个android app都会有二维码扫描。本篇旨在帮助有需求的同学快速完成二维码生成和扫描的功能。

1.    zxing的使用

github上下载项目后,可以看到整体代码结构如下:

这里写图片描述

我们只需将zxing包下的所有代码copy一份到我们的项目中去,除了这些还需要zxing的jar包,最后相应的资源文件,包括values文件下的ids文件、raw文件中的资源文件(可以替换)、layout文件下的activity_capture.xml(可以进行相应的订制) 和图片资源。 

2.    生成二维码的实现

等上面工作全部准备完毕后,就可以创建我们的二维码了。如何生成二维码?

需要encodingutils这个二维码生成工具类。通过调用工具类中的createqrcode()方法来生成二维码。该方法参数介绍如下:

/* 
* content:二维码内容 
* widthpix:二维码宽度 
* heightpix:二维码高度 
* logobm:二维码中间的logo对应的bitmap 
*/ 
public static bitmap createqrcode(string content, int widthpix, int heightpix, bitmap logobm)

下面完成的是生成的一个百度地址的二维码,中间logo是android小机器人。并保存图片到本地,方便后续测试二维码的本地读取功能。

/** 
 * 创建、展示二维码并将bitmap保存在本地 
 */ 
 private void create() { 
 int width = densityutil.dip2px(this, 200); 
 bitmap bitmap = encodingutils.createqrcode("http://www.baidu.com", 
  width, width, bitmapfactory.decoderesource(getresources(),r.drawable.ic_launcher)); 
 iv_zxing.setimagebitmap(bitmap); 
 savebitmap(bitmap); 
 } 
 /** 
 * 将bitmap保存在本地 
 * 
 * @param bitmap 
 */ 
 public void savebitmap(bitmap bitmap) { 
 // 首先保存图片 
 file appdir = new file(environment.getexternalstoragedirectory(),"zxing_image"); 
 if (!appdir.exists()) { 
  appdir.mkdir(); 
 } 
 string filename = "zxing_image" + ".jpg"; 
 file file = new file(appdir, filename); 
 try { 
  fileoutputstream fos = new fileoutputstream(file); 
  bitmap.compress(compressformat.jpeg, 100, fos); 
  fos.flush(); 
  fos.close(); 
 } catch (exception e) { 
  e.printstacktrace(); 
 } 
 // 把文件插入到系统图库 
 try { 
  mediastore.images.media.insertimage(this.getcontentresolver(),file.getabsolutepath(), filename, null); 
 } catch (filenotfoundexception e) { 
  e.printstacktrace(); 
 } 
 // 通知图库更新 
 sendbroadcast(new intent(intent.action_media_scanner_scan_file, 
  uri.parse("file://" + "/sdcard/namecard/"))); 
} 

看到如下效果:

这里写图片描述

3.    读取二维码的实现

3.1  摄像头扫描的方式

二维码扫描需要借助于captureactivity这个类,打开captureactivity界面并进行扫描,扫描完毕后回调onactivityresult()方法,从onactivityresult()中得到扫描后的结果。效果就不演示的,因为使用的是模拟器。详细代码如下:

 /** 
 * 打开二维码扫描 
 */ 
private void open() { 
 config(); 
 startactivityforresult(new intent(mainactivity.this,captureactivity.class), 0); 
} 
/** 
 * 提高屏幕亮度 
 */ 
private void config() { 
 windowmanager.layoutparams lp = getwindow().getattributes(); 
 lp.screenbrightness = 1.0f; 
 getwindow().setattributes(lp); 
} 
@override 
protected void onactivityresult(int requestcode, int resultcode, intent data) { 
 super.onactivityresult(requestcode, resultcode, data); 
 if (resultcode == result_ok) { 
 bundle bundle = data.getextras(); 
 string result = bundle.getstring("result"); 
 tv_result.settext(result); 
 } 

3.2  本地图片扫描的方式

扫描本地图片需要我们在captureactivity中进行相应的修改,为此我在扫描界面底部增加了一个按钮,用来选择本地图片。layout代码这里就不展示,我们直接看点击后的事件处理。

/** 
* 打开本地图片 
*/ 
private void openlocalimage() { 
 // 打开手机中的相册 
 intent innerintent = new intent(intent.action_get_content); 
 innerintent.settype("image/*"); 
 intent wrapperintent = intent.createchooser(innerintent, "选择二维码图片"); 
 this.startactivityforresult(wrapperintent, 0x01); 
} 

打开系统图片库后选择图片,这时需要重写onactivityresult()方法用于返回图片信息。

@override 
 protected void onactivityresult(int requestcode, int resultcode, intent data) { 
 super.onactivityresult(requestcode, resultcode, data); 
 if (resultcode == result_ok) { 
  switch (requestcode) { 
  case 0x01: 
  // 获取选中图片的路径 
  cursor cursor = getcontentresolver().query(data.getdata(),null, null, null, null); 
  if (cursor.movetofirst()) { 
   photo_path = cursor.getstring(cursor.getcolumnindex(mediastore.images.media.data)); 
  } 
  cursor.close(); 
  new thread(new runnable() { 
   @override 
   public void run() { 
   result result = scanningimage(photo_path); 
   if (result != null) { 
    handledecode(result, new bundle()); 
   } 
   } 
  }).start(); 
  break; 
  } 
 } 
} 

获取图片路径photo_path后,调用scanningimage()方法进行扫描,zxing源码中,扫描到的结果都是存放在result结果集中。获取到result后,就进行结果的回传,阅读captureactivity源码可以得知最后result结果集会传递给handledecode()方法。

/** 
 * a valid barcode has been found, so give an indication of success and show 
 * the results. 
 * 
 * @param rawresult 
 *  the contents of the barcode. 
 * @param bundle 
 *  the extras 
 */ 
 public void handledecode(result rawresult, bundle bundle) { 
 inactivitytimer.onactivity(); 
 beepmanager.playbeepsoundandvibrate(); 
 intent resultintent = new intent(); 
 bundle.putint("width", mcroprect.width()); 
 bundle.putint("height", mcroprect.height()); 
 bundle.putstring("result", rawresult.gettext()); 
 resultintent.putextras(bundle); 
 this.setresult(result_ok, resultintent); 
 captureactivity.this.finish(); 
}

获取到图片路径后需要将其二维码信息包装成result对象,因此需要解析图片:

/** 
 * 扫描二维码图片的方法 
 * 
 * @param path 
 * @return 
 */ 
 public result scanningimage(string path) { 
 if (textutils.isempty(path)) { 
  return null; 
 } 
 hashtable<decodehinttype, string> hints = new hashtable<decodehinttype, string>(); 
 hints.put(decodehinttype.character_set, "utf8"); // 设置二维码内容的编码 
 bitmapfactory.options options = new bitmapfactory.options(); 
 options.injustdecodebounds = true; // 先获取原大小 
 scanbitmap = bitmapfactory.decodefile(path, options); 
 options.injustdecodebounds = false; // 获取新的大小 
 int samplesize = (int) (options.outheight / (float) 200); 
 if (samplesize <= 0) 
  samplesize = 1; 
 options.insamplesize = samplesize; 
 scanbitmap = bitmapfactory.decodefile(path, options); 
 int width = scanbitmap.getwidth(); 
 int height = scanbitmap.getheight(); 
 int[] pixels = new int[width * height]; 
 scanbitmap.getpixels(pixels, 0, width, 0, 0, width, height); 
 /** 
 * 第三个参数是图片的像素 
 */ 
 rgbluminancesource source = new rgbluminancesource(width, height, 
  pixels); 
 binarybitmap bitmap1 = new binarybitmap(new hybridbinarizer(source)); 
 qrcodereader reader = new qrcodereader(); 
 try { 
  return reader.decode(bitmap1, hints); 
 } catch (notfoundexception e) { 
  e.printstacktrace(); 
 } catch (checksumexception e) { 
  e.printstacktrace(); 
 } catch (formatexception e) { 
  e.printstacktrace(); 
 } 
 return null; 
 } 

根据路径获取bitmap,最后通过qrcodereader 中的decode方法解析成result对象并返回,最终传递给handledecode方法。运行程序效果如下,扫描出来的是之前定义的百度地址。

这里写图片描述

最后不要忘了申明权限和captureactivity。

<uses-permission android:name="android.permission.write_external_storage"/> 
<uses-permission android:name="android.permission.mount_unmount_filesystems"/> 
<uses-permission android:name="android.permission.camera"/> 
<uses-permission android:name="android.permission.vibrate"/> 
<activity android:name="com.example.zxingtest.zxing.activity.captureactivity"/> 

大家可以参考下这篇文章:android实现二维码扫描和生成的简单方法

以上所述是小编给大家介绍的android中的二维码生成与扫描功能,希望对大家有所帮助

如对本文有疑问,请在下面进行留言讨论,广大热心网友会与你互动!! 点击进行留言回复

相关文章:

验证码:
移动技术网