Android基于google Zxing实现二维码的生成

最近项目用到了二维码的生成与识别,之前没有接触这块,然后就上网搜了搜,发现有好多这方面的资源,特别是google Zxing对二维码的封装,实现的已经不错了,可以直接拿过来引用,下载了他们的源码后,只做了少少的改动,就是在Demo中增加了长按识别的功能,网上虽然也有长按识别的Demo,但好多下载下来却无法运行,然后总结了一下,加在了下面的Demo中。  
下面来介绍这个Demo的主类

public class BarCodeTestActivity extends Activity { 

private TextView resultTextView;
private EditText qrStrEditText;
private ImageView qrImgImageView;
private String time;
 private File file = null;
 @Override
 public void onCreate(Bundle savedInstanceState) {
  super.onCreate(savedInstanceState);
  setContentView(R.layout.main);
  resultTextView = (TextView) this.findViewById(R.id.tv_scan_result);
  qrStrEditText = (EditText) this.findViewById(R.id.et_qr_string);
  qrImgImageView = (ImageView) this.findViewById(R.id.iv_qr_image); 

  Button scanBarCodeButton = (Button) this.findViewById(R.id.btn_scan_barcode);
  scanBarCodeButton.setOnClickListener(new OnClickListener() { 

@Override
public void onClick(View v) {
//打开扫描界面扫描条形码或二维码
Intent openCameraIntent = new Intent(BarCodeTestActivity.this,CaptureActivity.class);
startActivityForResult(openCameraIntent, 0);
}
});
qrImgImageView.setOnLongClickListener(new OnLongClickListener() { 

@Override
public boolean onLongClick(View v) {
// 长按识别二维码 

 saveCurrentImage();
return true;
}
});
  Button generateQRCodeButton = (Button) this.findViewById(R.id.btn_add_qrcode);
  generateQRCodeButton.setOnClickListener(new OnClickListener() { 

@Override
public void onClick(View v) {
try {
String contentString = qrStrEditText.getText().toString();
if (!contentString.equals("")) {
//根据字符串生成二维码图片并显示在界面上,第二个参数为图片的大小(350*350)
Bitmap qrCodeBitmap = EncodingHandler.createQRCode(contentString, 350);
qrImgImageView.setImageBitmap(qrCodeBitmap);
}else {
//提示文本不能是空的
Toast.makeText(BarCodeTestActivity.this, "Text can not be empty", Toast.LENGTH_SHORT).show();
} 

} catch (WriterException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
});
 } 

 //这种方法状态栏是空白,显示不了状态栏的信息
 private void saveCurrentImage()
 {
  //获取当前屏幕的大小
  int width = getWindow().getDecorView().getRootView().getWidth();
  int height = getWindow().getDecorView().getRootView().getHeight();
  //生成相同大小的图片
  Bitmap temBitmap = Bitmap.createBitmap( width, height, Bitmap.Config.ARGB_8888 );
  //找到当前页面的根布局
  View view = getWindow().getDecorView().getRootView();
  //设置缓存
  view.setDrawingCacheEnabled(true);
  view.buildDrawingCache();
  //从缓存中获取当前屏幕的图片,创建一个DrawingCache的拷贝,因为DrawingCache得到的位图在禁用后会被回收
  temBitmap = view.getDrawingCache();
  SimpleDateFormat df = new SimpleDateFormat("yyyymmddhhmmss");
  time = df.format(new Date());
  if(Environment.MEDIA_MOUNTED.equals(Environment.getExternalStorageState())){
   file = new File(Environment.getExternalStorageDirectory().getAbsolutePath() + "/screen",time + ".png");
   if(!file.exists()){
    file.getParentFile().mkdirs();
    try {
     file.createNewFile();
    } catch (IOException e) {
     // TODO Auto-generated catch block
     e.printStackTrace();
    }
   }
   FileOutputStream fos = null;
   try {
    fos = new FileOutputStream(file);
    temBitmap.compress(Bitmap.CompressFormat.PNG, 100, fos);
    fos.flush();
    fos.close();
   } catch (FileNotFoundException e) {
    e.printStackTrace();
   } catch (IOException e) {
    // TODO Auto-generated catch block
    e.printStackTrace();
   }
   new Thread(new Runnable() {
    @Override
    public void run() {
     String path = Environment.getExternalStorageDirectory().getAbsolutePath() + "/screen/" + time + ".png";
     final Result result = parseQRcodeBitmap(path);
     runOnUiThread(new Runnable() {
      public void run() {
      if(null!=result){
      resultTextView.setText(result.toString());
      }else{
       Toast.makeText(BarCodeTestActivity.this, "无法识别", Toast.LENGTH_LONG).show();
      }
      }
     });
    }
   }).start();
   //禁用DrawingCahce否则会影响性能 ,而且不禁止会导致每次截图到保存的是缓存的位图
   view.setDrawingCacheEnabled(false);
  }
 } 

 //解析二维码图片,返回结果封装在Result对象中
 private com.google.zxing.Result parseQRcodeBitmap(String bitmapPath){
  //解析转换类型UTF-8
  Hashtable<DecodeHintType, String> hints = new Hashtable<DecodeHintType, String>();
  hints.put(DecodeHintType.CHARACTER_SET, "utf-8");
  //获取到待解析的图片
  BitmapFactory.Options options = new BitmapFactory.Options();
  //如果我们把inJustDecodeBounds设为true,那么BitmapFactory.decodeFile(String path, Options opt)
  //并不会真的返回一个Bitmap给你,它仅仅会把它的宽,高取回来给你
  options.inJustDecodeBounds = true;
  //此时的bitmap是null,这段代码之后,options.outWidth 和 options.outHeight就是我们想要的宽和高了
  Bitmap bitmap = BitmapFactory.decodeFile(bitmapPath,options);
  //我们现在想取出来的图片的边长(二维码图片是正方形的)设置为400像素
  /**
   options.outHeight = 400;
   options.outWidth = 400;
   options.inJustDecodeBounds = false;
   bitmap = BitmapFactory.decodeFile(bitmapPath, options);
  */
  //以上这种做法,虽然把bitmap限定到了我们要的大小,但是并没有节约内存,如果要节约内存,我们还需要使用inSimpleSize这个属性
  options.inSampleSize = options.outHeight / 400;
  if(options.inSampleSize <= 0){
   options.inSampleSize = 1; //防止其值小于或等于0
  }
  /**
   * 辅助节约内存设置
   *
   * options.inPreferredConfig = Bitmap.Config.ARGB_4444; // 默认是Bitmap.Config.ARGB_8888
   * options.inPurgeable = true;
   * options.inInputShareable = true;
   */
  options.inJustDecodeBounds = false;
  bitmap = BitmapFactory.decodeFile(bitmapPath, options);
  //新建一个RGBLuminanceSource对象,将bitmap图片传给此对象
  RGBLuminanceSource rgbLuminanceSource = new RGBLuminanceSource(bitmap);
  //将图片转换成二进制图片
  BinaryBitmap binaryBitmap = new BinaryBitmap(new HybridBinarizer(rgbLuminanceSource));
  //初始化解析对象
  QRCodeReader reader = new QRCodeReader();
  //开始解析
  Result result = null;
  try {
   result = reader.decode(binaryBitmap, hints);
  } catch (Exception e) {
   // TODO: handle exception
  } 

  return result;
 } 

@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
//处理扫描结果(在界面上显示)
if (resultCode == RESULT_OK) {
Bundle bundle = data.getExtras();
String scanResult = bundle.getString("result");
resultTextView.setText(scanResult);
}
}
} 

然后长按识别二维码调用了RGBLuminanceSource这个类

public class RGBLuminanceSource extends LuminanceSource {
private byte bitmapPixels[]; 

protected RGBLuminanceSource(Bitmap bitmap) {
super(bitmap.getWidth(), bitmap.getHeight()); 

// 首先,要取得该图片的像素数组内容
int[] data = new int[bitmap.getWidth() * bitmap.getHeight()];
this.bitmapPixels = new byte[bitmap.getWidth() * bitmap.getHeight()];
bitmap.getPixels(data, 0, getWidth(), 0, 0, getWidth(), getHeight()); 

// 将int数组转换为byte数组,也就是取像素值中蓝色值部分作为辨析内容
for (int i = 0; i < data.length; i++) {
this.bitmapPixels[i] = (byte) data[i];
}
} 

@Override
public byte[] getMatrix() {
// 返回我们生成好的像素数据
return bitmapPixels;
} 

@Override
public byte[] getRow(int y, byte[] row) {
// 这里要得到指定行的像素数据
System.arraycopy(bitmapPixels, y * getWidth(), row, 0, getWidth());
return row;
}
} 

相机识别二维码调用了CaptureActivity这个类

public class CaptureActivity extends Activity implements Callback { 

private CaptureActivityHandler handler;
private ViewfinderView viewfinderView;
private boolean hasSurface;
private Vector<BarcodeFormat> decodeFormats;
private String characterSet;
private InactivityTimer inactivityTimer;
private MediaPlayer mediaPlayer;
private boolean playBeep;
private static final float BEEP_VOLUME = 0.10f;
private boolean vibrate;
private Button cancelScanButton; 

/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.camera); 

CameraManager.init(getApplication());
viewfinderView = (ViewfinderView) findViewById(R.id.viewfinder_view);
cancelScanButton = (Button) this.findViewById(R.id.btn_cancel_scan);
hasSurface = false;
inactivityTimer = new InactivityTimer(this);
} 

@Override
protected void onResume() {
super.onResume();
SurfaceView surfaceView = (SurfaceView) findViewById(R.id.preview_view);
SurfaceHolder surfaceHolder = surfaceView.getHolder();
if (hasSurface) {
initCamera(surfaceHolder);
} else {
surfaceHolder.addCallback(this);
surfaceHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
}
decodeFormats = null;
characterSet = null; 

playBeep = true;
AudioManager audioService = (AudioManager) getSystemService(AUDIO_SERVICE);
if (audioService.getRingerMode() != AudioManager.RINGER_MODE_NORMAL) {
playBeep = false;
}
initBeepSound();
vibrate = true; 

//quit the scan view
cancelScanButton.setOnClickListener(new OnClickListener() { 

@Override
public void onClick(View v) {
CaptureActivity.this.finish();
}
});
} 

@Override
protected void onPause() {
super.onPause();
if (handler != null) {
handler.quitSynchronously();
handler = null;
}
CameraManager.get().closeDriver();
} 

@Override
protected void onDestroy() {
inactivityTimer.shutdown();
super.onDestroy();
} 

/**
* Handler scan result
* @param result
* @param barcode
*/
public void handleDecode(Result result, Bitmap barcode) {
inactivityTimer.onActivity();
playBeepSoundAndVibrate();
String resultString = result.getText();
//FIXME
if (resultString.equals("")) {
//扫描失败
Toast.makeText(CaptureActivity.this, "Scan failed!", Toast.LENGTH_SHORT).show();
}else {
// System.out.println("Result:"+resultString);
Intent resultIntent = new Intent();
Bundle bundle = new Bundle();
bundle.putString("result", resultString);
resultIntent.putExtras(bundle);
this.setResult(RESULT_OK, resultIntent);
}
CaptureActivity.this.finish();
} 

private void initCamera(SurfaceHolder surfaceHolder) {
try {
CameraManager.get().openDriver(surfaceHolder);
} catch (IOException ioe) {
return;
} catch (RuntimeException e) {
return;
}
if (handler == null) {
handler = new CaptureActivityHandler(this, decodeFormats,
characterSet);
}
} 

@Override
public void surfaceChanged(SurfaceHolder holder, int format, int width,
int height) { 

} 

@Override
public void surfaceCreated(SurfaceHolder holder) {
if (!hasSurface) {
hasSurface = true;
initCamera(holder);
} 

} 

@Override
public void surfaceDestroyed(SurfaceHolder holder) {
hasSurface = false;
}
public ViewfinderView getViewfinderView() {
return viewfinderView;
}
public Handler getHandler() {
return handler;
}
public void drawViewfinder() {
viewfinderView.drawViewfinder();
}
private void initBeepSound() {
if (playBeep && mediaPlayer == null) {
// The volume on STREAM_SYSTEM is not adjustable, and users found it
// too loud,
// so we now play on the music stream.
setVolumeControlStream(AudioManager.STREAM_MUSIC);
mediaPlayer = new MediaPlayer();
mediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
mediaPlayer.setOnCompletionListener(beepListener); 

AssetFileDescriptor file = getResources().openRawResourceFd(
R.raw.beep);
try {
mediaPlayer.setDataSource(file.getFileDescriptor(),
file.getStartOffset(), file.getLength());
file.close();
mediaPlayer.setVolume(BEEP_VOLUME, BEEP_VOLUME);
mediaPlayer.prepare();
} catch (IOException e) {
mediaPlayer = null;
}
}
} 

private static final long VIBRATE_DURATION = 200L;
private void playBeepSoundAndVibrate() {
if (playBeep && mediaPlayer != null) {
mediaPlayer.start();
}
if (vibrate) {
Vibrator vibrator = (Vibrator) getSystemService(VIBRATOR_SERVICE);
vibrator.vibrate(VIBRATE_DURATION);
}
} 

/**
* When the beep has finished playing, rewind to queue up another one.
*/
private final OnCompletionListener beepListener = new OnCompletionListener() {
public void onCompletion(MediaPlayer mediaPlayer) {
mediaPlayer.seekTo(0);
}
}; 

} 

下面是主布局mian文件

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
 android:layout_width="fill_parent"
 android:layout_height="fill_parent"
 android:background="@android:color/white"
 android:orientation="vertical" > 

 <Button
  android:id="@+id/btn_scan_barcode"
  android:layout_width="fill_parent"
  android:layout_height="wrap_content"
  android:layout_marginTop="30dp"
  android:text="Open camera" /> 

 <LinearLayout
  android:orientation="horizontal"
  android:layout_marginTop="10dp"
  android:layout_width="fill_parent"
  android:layout_height="wrap_content"> 

  <TextView
  android:layout_width="wrap_content"
  android:layout_height="wrap_content"
  android:textColor="@android:color/black"
  android:textSize="18sp"
  android:text="Scan result:" /> 

  <TextView
  android:id="@+id/tv_scan_result"
  android:layout_width="fill_parent"
  android:textSize="18sp"
  android:textColor="@android:color/black"
  android:layout_height="wrap_content" />
 </LinearLayout> 

 <EditText
  android:id="@+id/et_qr_string"
  android:layout_width="fill_parent"
  android:layout_height="wrap_content"
  android:layout_marginTop="30dp"
  android:hint="Input the text"/> 

 <Button
  android:id="@+id/btn_add_qrcode"
  android:layout_width="fill_parent"
  android:layout_height="wrap_content"
  android:text="Generate QRcode" /> 

 <ImageView
  android:id="@+id/iv_qr_image"
  android:layout_width="250dp"
  android:layout_height="250dp"
  android:scaleType="fitXY"
  android:layout_marginTop="10dp"
  android:layout_gravity="center"/> 

</LinearLayout>

详细了解的请下载demo自己看,Demo中解决了在竖拍解码时二维码被拉伸的现象。
不过我遇到了一个问题是 二维码的扫描框调大后,扫描的灵敏度降低了,希望知道的朋友给指导下
有兴趣的可以下载Demo看一看:google Zxing实现二维码的生成

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持我们。

(0)

相关推荐

  • Android项目实战(二十八):使用Zxing实现二维码及优化实例

    前言: 多年之前接触过zxing实现二维码,没想到今日项目中再此使用竟然使用的还是zxing,百度之,竟是如此牛的玩意. 当然,项目中我们也许只会用到二维码的扫描和生成两个功能,所以不必下载完整的jar包,使用简化版的即可,下文可见. 这篇文章讲述: 1.如果快速在项目中集成zxing,实现扫描和生成二维码功能 2.根据项目需求去修改源码实现我们的要求并进行优化 一.快速集成zxing二维码 1.下载库文件 :http://xiazai.jb51.net/201611/yuanma/ZXingB

  • Android开发框架之自定义ZXing二维码扫描界面并解决取景框拉伸问题

    先给大家展示下效果图: 扫描内容是下面这张,二维码是用zxing库生成的 由于改了好几个类,还是去年的事都忘得差不多了,所以只能上这个类的代码了,主要就是改了这个CaptureActivity.java package com.zxing.activity; import java.io.IOException; import java.util.Vector; import android.app.Activity; import android.content.Intent; import

  • Android基于zxing的二维码(网格)扫描 仿支付宝网格扫描

    前言:对于二维码扫描我们使用的是开源框架Zxing或者Zbar,这里使用基于zxing的二维码扫描,类似支付宝网格扫描. 二维码原理介绍: 二维码是用某种特定的几何图形按一定的规律在平面上分布的黑白相间的图形记录数据符号信息的,在代码编制上巧妙的利用构成计算机内部逻辑基础的0/1比特流的概念,使用若干个与二进制相对应的几何形体来表示文字数值信息,通过图像输入设备或光电扫描设备自动识读以实现信息自动处理:二维码能够在横向和纵向两个方位同时表达信息,因此能在很小的面积内表达大量的信息. 效果: 真机

  • Android中利用zxing实现自己的二维码扫描识别详解

    前言 在上一篇文章中已经简单介绍了zxing的使用,快速集成到自己的项目中,但是使用的扫描我们没办法根据自己的需求来做自己的扫描界面,所以这篇我们来学习一下如何根据自己的需求来实现二维码的扫描.当然用到的库依然还是google的zxing.下面话不多说了,来一起看看详细的介绍吧. 方法如下: 首先我们打开google的zxing的地址,googledezxing地址 (本地下载),打开之后我们会看到这样的界面, 将这个文件下载我们本地,下载好之后我们需要复制android文件下的几个类, 根据这

  • Android 基于google Zxing实现二维码、条形码扫描,仿微信二维码扫描效果(推荐)

    了解二维码这个东西还是从微信中,当时微信推出二维码扫描功能,自己感觉挺新颖的,从一张图片中扫一下竟然能直接加好友,不可思议啊,那时候还不了解二维码,呵呵,然后做项目的时候,老板说要加上二维码扫描功能,然后自己的屁颠屁颠的去百度,google啥的,发现很多朋友都有介绍二维码扫描的功能,然后我就跟着人家的介绍自己搞起了二维码扫描功能,跟着人家的帖子,很快我的项目就加入了扫描二维码的功能,然后自己还很开心. 随着微信的到来,二维码越来越火爆,随处能看到二维码,比如商城里面,肯德基,餐厅等等,对于二维码

  • Android利用ZXing扫描二维码的实例代码解析

    相关阅读: Android开发框架之自定义ZXing二维码扫描界面并解决取景框拉伸问题 此项目源码地址:请点击这里 看一下zxing的项目结构,我这里直接拿过来用的 看一下扫码的activity: package com.fanyafeng.barcode.activity; import android.content.Intent; import android.graphics.Bitmap; import android.net.Uri; import android.os.Bundle

  • Android基于google Zxing实现各类二维码扫描效果

    随着微信的到来,二维码越来越火爆,随处能看到二维码,比如商城里面,肯德基,餐厅等等,对于二维码扫描我们使用的是google的开源框架Zxing,我们可以去http://code.google.com/p/zxing/下载源码和Jar包,之前我项目中的二维码扫描功能只实现了扫描功能,其UI真的是其丑无比,一个好的应用软件,其UI界面也要被大众所接纳,不然人家就不会用你的软件啦,所以说应用软件功能和界面一样都很重要,例如微信,相信微信UI被很多应用软件所模仿,我也仿照微信扫描二维码效果进行模仿,虽然

  • Android中使用ZXing生成二维码(支持添加Logo图案)

    ZXing是谷歌的一个开源库,可以用来生成二维码.扫描二维码.本文所介绍的是第一部分. 首先上效果图: ZXing相关各种文件官方下载地址:https://github.com/zxing/zxing/releases 或者在这里下载(只有本项目所用的jar包,版本号:3.2.0):链接:http://pan.baidu.com/s/1pLqAR5x 1.生成二维码的工具类 /** * 二维码生成工具类 */ public class QRCodeUtil { /** * 生成二维码Bitmap

  • Android上使用ZXing识别条形码与二维码的方法

    目前有越来越多的手机具备自动对焦的拍摄功能,这也意味着这些手机可以具备条码扫描的功能.手机具备条码扫描的功能,可以优化购物流程,快速存储电子名片(二维码)等. 本文所述实例就使用了ZXing 1.6实现条码/二维码识别.ZXing是个很经典的条码/二维码识别的开源类库,早在很久以前,就有开发者在J2ME上使用ZXing了,只不过需要支持JSR-234规范(自动对焦)的手机才能发挥其威力,而目前已经有不少Android手机具备自动对焦的功能. 本文代码运行的结果如下,使用91手机助手截图时,无法截

  • Android Zxing二维码扫描图片拉伸问题的解决方法

    还是这个接手项目,二维码扫描集成的是zxing,扫描界面的图像有明显的拉伸变形. 这种问题,根据以往的经验,一般是x,y轴错位引起的,处理好x,y轴的问题,一般可以解决问题. 由于这个问题,之前有很多人遇到,并分享在网上了,所以,我这里也就不需要重复造轮子了. 这里看了一篇博客:Android Zxing二维码扫描图片拉伸,用了上面的办法, 成功的解决图片拉伸问题. 解决方法如下: 修改CameraConfigurationManager.Java里面的initFromCameraParamet

随机推荐