最近在做android项目需要用到二维码条形码扫描功能,我用的是Eclipse网上源码大多是GitHup上的Android studio版本的所以我改了一版集成到项目中去。
效果图:
左边版本的扫码框是自定义的。右边版本的扫码框和扫描线是图片因为太丑所以最终换成左边样式。
自定义版本我是仿着微信的样式大小来做的。
以左边图片样式为例
1.首先将源码中com.google.zxing五个包引入到自己的项目中。
2.拷贝资源目录raw至本项目中,beep.ogg是扫描成功时的提示音。
3.拷贝或合并文件内容values里面的xml文件。
4.权限配置在AndroidManifest.xml中添加权限申请代码:
还要配置CaptureActivity.java
完成上述集成之后,通过调用CaptureActivity就可以实现扫码功能。
MainActivity源码部分:
package com.example.scandemo2;
import android.Manifest;
import android.app.Activity;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.os.Bundle;
import android.support.v4.app.ActivityCompat;
import android.support.v4.content.ContextCompat;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;
import android.widget.Toast;
import com.dommy.qrcode.util.Constant;
import com.google.zxing.activity.CaptureActivity;
public class MainActivity extends Activity implements View.OnClickListener {
Button btnQrCode; // 扫码
TextView tvResult; // 结果
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
initView();
}
private void initView() {
btnQrCode = (Button) findViewById(R.id.btn_qrcode);
btnQrCode.setOnClickListener(this);
tvResult = (TextView) findViewById(R.id.txt_result);
}
// 开始扫码
private void startQrCode() {
// 二维码扫码
Intent intent = new Intent(MainActivity.this, CaptureActivity.class);
startActivityForResult(intent, Constant.REQ_QR_CODE);
}
@Override
public void onClick(View view) {
switch (view.getId()) {
case R.id.btn_qrcode:
startQrCode();
break;
}
}
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
//扫描结果回调
if (requestCode == Constant.REQ_QR_CODE && resultCode == RESULT_OK) {
Bundle bundle = data.getExtras();
String scanResult = bundle.getString(Constant.INTENT_EXTRA_KEY_QR_SCAN);
//将扫描出的信息显示出来
tvResult.setText(scanResult);
}
}
}
activity_scanner.xml
CaptureActivity.java
package com.google.zxing.activity;
import android.app.Activity;
import android.app.ProgressDialog;
import android.content.ContentResolver;
import android.content.Context;
import android.content.Intent;
import android.content.res.AssetFileDescriptor;
import android.database.Cursor;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.media.AudioManager;
import android.media.MediaPlayer;
import android.media.MediaPlayer.OnCompletionListener;
import android.net.Uri;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.os.Vibrator;
import android.provider.MediaStore;
import android.text.TextUtils;
import android.view.Menu;
import android.view.MenuItem;
import android.view.SurfaceHolder;
import android.view.SurfaceHolder.Callback;
import android.view.SurfaceView;
import android.view.View;
import android.widget.Button;
import android.widget.ImageButton;
import android.widget.ImageView;
import android.widget.TextView;
import android.widget.Toast;
import com.dommy.qrcode.util.Constant;
import com.dommy.qrcode.util.UriUtil;
import com.example.scandemo2.R;
import com.google.zxing.BarcodeFormat;
import com.google.zxing.BinaryBitmap;
import com.google.zxing.ChecksumException;
import com.google.zxing.DecodeHintType;
import com.google.zxing.FormatException;
import com.google.zxing.NotFoundException;
import com.google.zxing.Result;
import com.google.zxing.camera.CameraManager;
import com.google.zxing.common.HybridBinarizer;
import com.google.zxing.decoding.CaptureActivityHandler;
import com.google.zxing.decoding.InactivityTimer;
import com.google.zxing.decoding.RGBLuminanceSource;
import com.google.zxing.qrcode.QRCodeReader;
import com.google.zxing.view.ViewfinderView;
import java.io.IOException;
import java.util.Hashtable;
import java.util.Vector;
public class CaptureActivity extends Activity implements Callback {
private static final int REQUEST_CODE_SCAN_GALLERY = 100;
private CaptureActivityHandler handler;
private ViewfinderView viewfinderView;
private ImageButton back;
private ImageButton btnFlash;
private Button btnAlbum; // 相册
private boolean isFlashOn = false;
private boolean hasSurface;
private Vector 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 ProgressDialog mProgress;
private String photo_path;
private Bitmap scanBitmap;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_scanner);
CameraManager.init(getApplication());
viewfinderView = (ViewfinderView) findViewById(R.id.viewfinder_content);
btnFlash = (ImageButton) findViewById(R.id.btn_flash);
btnFlash.setOnClickListener(flashListener);
hasSurface = false;
inactivityTimer = new InactivityTimer(this);
}
//返回
public void btn_back(View view){
this.finish();
}
@Override
protected void onActivityResult(final int requestCode, int resultCode, Intent data) {
if (resultCode==RESULT_OK) {
switch (requestCode) {
case REQUEST_CODE_SCAN_GALLERY:
handleAlbumPic(data);
break;
}
}
super.onActivityResult(requestCode, resultCode, data);
}
/**
* 处理选择的图片
* @param data
*/
private void handleAlbumPic(Intent data) {
//获取选中图片的路径
photo_path = UriUtil.getRealPathFromUri(CaptureActivity.this, data.getData());
mProgress = new ProgressDialog(CaptureActivity.this);
mProgress.setMessage("正在扫描...");
mProgress.setCancelable(false);
mProgress.show();
runOnUiThread(new Runnable() {
@Override
public void run() {
mProgress.dismiss();
Result result = scanningImage(photo_path);
if (result != null) {
Intent resultIntent = new Intent();
Bundle bundle = new Bundle();
bundle.putString(Constant.INTENT_EXTRA_KEY_QR_SCAN ,result.getText());
resultIntent.putExtras(bundle);
CaptureActivity.this.setResult(RESULT_OK, resultIntent);
finish();
} else {
Toast.makeText(CaptureActivity.this, "识别失败", Toast.LENGTH_SHORT).show();
}
}
});
}
/**
* 扫描二维码图片的方法
* @param path
* @return
*/
public Result scanningImage(String path) {
if(TextUtils.isEmpty(path)){
return null;
}
Hashtable hints = new Hashtable<>();
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);
RGBLuminanceSource source = new RGBLuminanceSource(scanBitmap);
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;
}
@Override
protected void onResume() {
super.onResume();
SurfaceView surfaceView = (SurfaceView) findViewById(R.id.scanner_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;
}
@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 (TextUtils.isEmpty(resultString)) {
Toast.makeText(CaptureActivity.this, "Scan failed!", Toast.LENGTH_SHORT).show();
} else {
Intent resultIntent = new Intent();
Bundle bundle = new Bundle();
bundle.putString(Constant.INTENT_EXTRA_KEY_QR_SCAN, 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) {
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);
}
}
private final OnCompletionListener beepListener = new OnCompletionListener() {
public void onCompletion(MediaPlayer mediaPlayer) {
mediaPlayer.seekTo(0);
}
};
/**
* 闪光灯开关按钮
*/
private View.OnClickListener flashListener = new View.OnClickListener() {
@Override
public void onClick(View view) {
try {
boolean isSuccess = CameraManager.get().setFlashLight(!isFlashOn);
if(!isSuccess){
Toast.makeText(CaptureActivity.this, "暂时无法开启闪光灯", Toast.LENGTH_SHORT).show();
return;
}
if (isFlashOn) {
// 关闭闪光灯
btnFlash.setImageResource(R.drawable.flash_off);
isFlashOn = false;
} else {
// 开启闪光灯
btnFlash.setImageResource(R.drawable.flash_on);
isFlashOn = true;
}
}catch (Exception e){
e.printStackTrace();
}
}
};
}
自定义扫码框大小上下位置不会设置请参考-->android Zxing修改二维码中扫描框的大小仿微信
如果调整扫码框绿色边角粗细扫描线扫码速度请打开
com.google.zxing.view.ViewfinderView.java文件在这里设置
首先扫描框扫描线是图片的样式Eclipse版本。
源码下载-->android Zxing扫描二维码条形码功能仿微信扫码框扫描线为图片样式Eclipse版本
然后这是自定义扫码框扫描线边框样式Eclipse版本。
源码下载-->android Zxing扫描二维码条形码功能仿微信自定义扫码框扫描线边框样式Eclipse版本
最后是自定义扫码框扫描线边框样式Android studio版本。
源码下载-->android Zxing扫描二维码条形码功能仿微信自定义扫码框扫描线边框样式Android studio版本
需要哪一版自己去下载。