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

 更新时间:2017年01月13日 16:16:04   作者:SEU_Calvin  
二维码在我们身边真的非常普遍,今天小编给大家分享二维码生成与扫描功能,依然使用目前比较流行的zxing方法,具体实现思路大家通过本文一起学习吧

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中的二维码生成与扫描功能,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对脚本之家网站的支持!

相关文章

  • Android 按指定大小读取图片的实例

    Android 按指定大小读取图片的实例

    本文主要介绍Android 按指定大小读取图片,在Android开发过程中经常会遇到图片超过屏幕,或者图片过小问题,这里给一个实例解决读取图片大小的问题,希望能帮助有需要的小伙伴
    2016-07-07
  • Android scrollview实现底部继续拖动查看图文详情

    Android scrollview实现底部继续拖动查看图文详情

    这篇文章主要为大家详细介绍了Android scrollview实现底部继续拖动查看图文详情,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2019-02-02
  • Android中NavigationView的使用与相关问题解决

    Android中NavigationView的使用与相关问题解决

    大家都知道NavigationView的引入让 Android侧边栏实现起来相当方便,最近公司项目中也使用这个新的控件完成了侧边栏的改版。在使用过程中遇到一些问题所以记录一下。本文分为两个部分,一是基本使用,二是相关问题的解决,感兴趣的朋友们下面来一起看看吧。
    2016-10-10
  • Android 实现ViewPager边界回弹效果实例代码

    Android 实现ViewPager边界回弹效果实例代码

    这篇文章主要介绍了Android 实现ViewPager边界回弹效果的实例代码,非常不错,具有参考借鉴价值,需要的朋友可以参考下
    2017-05-05
  • Android实现打开手机淘宝并自动识别淘宝口令弹出商品信息功能

    Android实现打开手机淘宝并自动识别淘宝口令弹出商品信息功能

    最近项目经理给我们安排一个活儿,基于Android开发实现打开手机淘宝,并自动识别淘口令,弹出商品信息,今天小编就抽空给大家分享下这个需求是怎么实现的,需要的朋友参考下吧
    2017-11-11
  • Android ScrollView 下嵌套 ListView 或 GridView出现问题解决办法

    Android ScrollView 下嵌套 ListView 或 GridView出现问题解决办法

    这篇文章主要介绍了ScrollView 下嵌套 ListView 或 GridView 会发列表现数据只能显示一行。因为他们都是滚动结构,两个滚动条放到一起就会引起冲突,这里提供解决办法相关资料,需要的朋友可以参考下
    2017-07-07
  • Android开发中关于获取当前Activity的一些思考

    Android开发中关于获取当前Activity的一些思考

    这篇文章主要为大家详细介绍了Android开发过程中,关于获取当前Activity的一些思考,感兴趣的小伙伴们可以参考一下
    2016-02-02
  • 详解Android 检测权限的三种写法

    详解Android 检测权限的三种写法

    这篇文章主要介绍了详解Android 检测权限的三种写法,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2018-10-10
  • Flutter 全局点击空白处隐藏键盘实战

    Flutter 全局点击空白处隐藏键盘实战

    这篇文章主要介绍了Flutter 全局点击空白处隐藏键盘实战,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2020-09-09
  • Android编程实现通知栏进度条效果的方法示例

    Android编程实现通知栏进度条效果的方法示例

    这篇文章主要介绍了Android编程实现通知栏进度条效果的方法,结合实例形式较为详细的分析了Android通知栏进度条效果的功能、布局相关实现方法与操作注意事项,需要的朋友可以参考下
    2018-02-02

最新评论