博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
自定义ZXing二维码扫描界面并解决取景框拉伸等问题
阅读量:5810 次
发布时间:2019-06-18

本文共 9998 字,大约阅读时间需要 33 分钟。

hot3.png

先看效果

 

扫描内容是下面这张,二维码是用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.content.res.AssetFileDescriptor;import android.graphics.Bitmap;import android.media.AudioManager;import android.media.MediaPlayer;import android.media.MediaPlayer.OnCompletionListener;import android.os.Handler;import android.os.Vibrator;import android.view.SurfaceHolder;import android.view.SurfaceHolder.Callback;import android.view.SurfaceView;import android.widget.Toast;import com.ericssonlabs.R;import com.google.zxing.BarcodeFormat;import com.google.zxing.Result;import com.zxing.camera.CameraManager;import com.zxing.decoding.CaptureActivityHandler;import com.zxing.decoding.CaptureActivityHandler.DecodeCallback;import com.zxing.decoding.InactivityTimer;import com.zxing.view.ViewfinderView;/** * Initial the camera * @author Ryan.Tang * @modifier Lemon * @use extends CaptureActivity并且在setContentView方法后调用init方法 */public abstract class CaptureActivity extends Activity implements Callback, DecodeCallback {	//	private static final String TAG = "CaptureActivity";	protected Activity context;	protected SurfaceView surfaceView;	protected ViewfinderView viewfinderView;	/**初始化,必须在setContentView之后	 * @param context	 * @param viewfinderView	 */	protected void init(Activity context, SurfaceView surfaceView, ViewfinderView viewfinderView) {		this.context = context;		this.surfaceView = surfaceView;		this.viewfinderView = viewfinderView;		CameraManager.init(getApplication());		hasSurface = false;		inactivityTimer = new InactivityTimer(this);	}	private CaptureActivityHandler handler;	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; @Override protected void onResume() { super.onResume(); 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(); } public static final String RESULT_QRCODE_STRING = "RESULT_QRCODE_STRING"; /** * 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(); } setResult(RESULT_OK, new Intent().putExtra(RESULT_QRCODE_STRING, resultString)); 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, viewfinderView, this); } } @Override public void drawViewfinder() { viewfinderView.drawViewfinder(); } @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 Handler getHandler() { return handler; } 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); } };}

使用方法: 新建一个Activity继承CaptureActivity并且在setContentView方法后调用init方法即可。

示例:

CameraScanActivity.java

package zuo.biao.activity;import zuo.biao.R;import zuo.biao.library.interfaces.OnBottomDragListener;import zuo.biao.util.ActivityUtil;import android.content.Context;import android.content.Intent;import android.os.Bundle;import android.view.SurfaceHolder.Callback;import android.view.SurfaceView;import android.view.View;import android.view.View.OnClickListener;import com.zxing.activity.CaptureActivity;import com.zxing.camera.CameraManager;import com.zxing.view.ViewfinderView;/**扫描二维码Activity * @author Lemon * @use 参考zuo.biao.library.ModelActivity */public class CameraScanActivity extends CaptureActivity implements Callback, OnClickListener, OnBottomDragListener {	public static final String TAG = ActivityUtil.TAG_CAMERA_SCAN_ACTIVITY;	//启动方法<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<	/**启动这个Activity的Intent	 * @param context	 * @param title	 * @return	 */	public static Intent createIntent(Context context) {		return new Intent(context, CameraScanActivity.class);	}	//启动方法>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>	@Override	protected void onCreate(Bundle savedInstanceState) {		super.onCreate(savedInstanceState);		setContentView(R.layout.camera_scan_activity);		init(this, (SurfaceView) findViewById(R.id.svCameraScan), (ViewfinderView) findViewById(R.id.vfvCameraScan));		//功能归类分区方法,必须调用<<<<<<<<<<		initView();		initData();		initListener();		//功能归类分区方法,必须调用>>>>>>>>>>	}	//UI显示区(操作UI,但不存在数据获取或处理代码,也不存在事件监听代码)<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<	public void initView() {//必须调用	}	//UI显示区(操作UI,但不存在数据获取或处理代码,也不存在事件监听代码)>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>	//data数据区(存在数据获取或处理代码,但不存在事件监听代码)<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<	public void initData() {//必须调用	}	//data数据区(存在数据获取或处理代码,但不存在事件监听代码)>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>	//listener事件监听区(只要存在事件监听代码就是)<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<	public void initListener() {//必须调用		findViewById(R.id.tvCameraScanReturn).setOnClickListener(this);		findViewById(R.id.ivCameraScanReturn).setOnClickListener(this);		findViewById(R.id.ivCameraScanLight).setOnClickListener(this);		findViewById(R.id.ivCameraScanMyQRCode).setOnClickListener(this);	}	//系统自带监听方法<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<	@Override	public void onDragBottom(boolean rightToLeft) {		if (rightToLeft) {			return;		}		finish();	}	@Override	public void onClick(View v) {		switch (v.getId()) {		case R.id.tvCameraScanReturn:		case R.id.ivCameraScanReturn:			onDragBottom(false);			break;		case R.id.ivCameraScanLight:			switchLight(! isOpen);			break;		case R.id.ivCameraScanMyQRCode:			//			break;		default:			break;		}	}	private boolean isOpen = false;	/**打开或关闭闪关灯	 * @param open	 */	private void switchLight(boolean open) {		if (open == isOpen) {			return;		}		isOpen = CameraManager.get().switchLight(open);	}	//类相关监听<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<	//类相关监听>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>	//系统自带监听方法>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>	//listener事件监听区(只要存在事件监听代码就是)>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>	//内部类,尽量少用<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<	//内部类,尽量少用>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>}

CameraScanActivity布局文件camera_scan_activity.xml

布局文件因为使用了ZBLibrary中的一些style,color等,只有这个layout的话会出现一些错误。自己新建一个layout文件并把ViewfinderView放到最外层布局文件内就行了。当然下载好下面附上的源码就没这问题了。

对了,记得在AndroidManifest.xml中加上这些权限:

    <uses-permission android:name="android.permission.CAMERA" />

    <uses-feature android:name="android.hardware.camera" />

    <uses-feature android:name="android.hardware.camera.autofocus" />

    <uses-permission android:name="android.permission.FLASHLIGHT" />

 

附源码(欢迎Star,欢迎Fork)

 

GitHub源码       

开源中国源码     

 

转载于:https://my.oschina.net/tommylemon/blog/687986

你可能感兴趣的文章
锐捷交换机密码恢复(1)
查看>>
Kali linux virtualbox rc=1908 错误解决办法
查看>>
linux软件包管理之三(源代码安装)
查看>>
数据库三范式是什么?
查看>>
[转载]设置Ubuntu自动连接无线,无须再输入密钥环和无线密码
查看>>
九叔Xen App测试报告
查看>>
Apache配置
查看>>
Ext gridPanel 单元格数据的渲染
查看>>
Android SDK 的下载代理
查看>>
Method Swizzling对Method的要求
查看>>
佛祖保佑,永不宕机
查看>>
四、配置开机自动启动Nginx + PHP【LNMP安装 】
查看>>
LNMP一键安装
查看>>
SQL Server数据库概述
查看>>
Linux 目录结构及内容详解
查看>>
startx命令--Linux命令应用大词典729个命令解读
查看>>
华为3026c交换机配置tftp备份命令
查看>>
Oracle命令导入dmp文件
查看>>
OCP读书笔记(24) - 题库(ExamD)
查看>>
Http、TCP/IP协议与Socket之间的区别(转载)
查看>>