欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  移动技术

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

程序员文章站 2024-02-22 11:54:40
0. 前言 今天这篇文章主要描述二维码的生成与扫描,使用目前流行的zxing,为什么要讲二维码,因为二维码太普遍了,随便一个android app都会有二维码扫描。本篇旨...

0. 前言

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

1.    zxing的使用

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

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

我们只需将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/"))); 
} 

看到如下效果:

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

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方法。运行程序效果如下,扫描出来的是之前定义的百度地址。

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

最后不要忘了申明权限和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中的二维码生成与扫描功能,希望对大家有所帮助