Android 模仿360二维码扫描功能
发布日期:2021-06-30 22:37:41 浏览次数:2 分类:技术文章

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

一、效果图:

这里写图片描述

这里写图片描述

———————————————————————

有需求者请加qq:136137465,非诚勿扰
(java 架构师全套教程,共760G, 让你从零到架构师,每月轻松拿3万)
01.高级架构师四十二个阶段高
02.Java高级系统培训架构课程148课时
03.Java高级互联网架构师课程
04.Java互联网架构Netty、Nio、Mina等-视频教程
05.Java高级架构设计2016整理-视频教程
06.架构师基础、高级片
07.Java架构师必修linux运维系列课程
08.Java高级系统培训架构课程116课时
(送:hadoop系列教程,java设计模式与数据结构, Spring Cloud微服务, SpringBoot入门)
——————————————————————–

二、框架搭建

1、首先,下载最新zxing开源项目。 下载地址:

或 链接: 密码:hqcg

2、分析项目结构,明确扫描框架需求。在zxing中,有很多其他的功能,项目结构比较复杂;针对二维码QRCode扫描,我们需要几个包:

(1)com.google.zxing.client.android.Camera 基于Camera调用以及参数配置,核心包
(2)DecodeFormatManager、DecodeThread、DecodeHandler 基于解码格式、解码线程、解码结果处理的解码类
(3)ViewfinderView、ViewfinderResultPointCallBack 基于取景框视图定义的View类
(4)CaptureActivity、CaptureActivityHandler 基于扫描Activity以及扫描结果处理的Capture类
(5)InactivityTimer、BeepManager、FinishListener 基于休眠、声音、退出的辅助管理类
(6)Intents、IntentSource、PrefrencesActivity 基于常量存储的常量类

3、新建工程,添加如下权限permission:

4、 添加core.jar文件,并BuildPath;将上述类或包加入工程后,会报一系列错误,原因有几点:

(1)资源文件缺乏,将zxing下需要的资源文件copy到新工程下
(2)版本兼容问题,zxing下很多技术都是使用4.0版本及以上,集成到低版本之后,须做相应改动,详情参照项目源码
(3)包结构引用问题,需要重新导入包引用

5、最后框架

这里写图片描述

三、具体实现

1、创建MainActivity用于跳转到扫描页面

/** * 二维码扫描 * @Project    App_ZXing * @Package    com.android.scan * @author     chenlin * @version    1.0 * @Date       2014年3月6日 */public class MainActivity extends Activity {
private Button mBtnScan; private Button mBtnBack; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); mBtnBack = (Button) findViewById(R.id.btn_back); mBtnBack.setVisibility(View.GONE); mBtnScan = (Button) findViewById(R.id.btn_scan); mBtnScan.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { startActivity(new Intent(MainActivity.this, ScanActivity.class)); } }); }}

布局文件

二、扫描页面

/** * 条形码扫描 *  * @Project App_ZXing * @Package com.android.scan * @author chenlin * @version 1.0 * @Date 2014年3月6日 */public class ScanActivity extends Activity implements Callback {
private static final float BEEP_VOLUME = 0.10f; protected static final String RESULT_TEXT = "result"; protected static final String RESULT_BITMAP = "bitmap"; /** 扫描界面 */ private SurfaceView mSurfaceView; /** 自定义的View,就是我们看见的拍摄时中间的框框了 */ private ViewfinderView mFindView; /** 解码处理类,负责调用另外的线程进行解码。 */ private CaptureActivityHandler mHandler; /** 判断是否创建了SurfaceView */ private boolean hasSurface; /** decodeFormats 条形码,二维码等的集合 */ private Vector
mDecodeFormats; /** 字符编码 */ private String characterSet; /** 定时器 */ private InactivityTimer inactivityTimer; /** 媒体播放器 */ private MediaPlayer mediaPlayer; /** 是否播放声音 */ private boolean playBeep; /** 是否震动 */ private boolean vibrate; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_scan); init(); } /** * 初始化 */ private void init() { mSurfaceView = (SurfaceView) findViewById(R.id.preview_view); mFindView = (ViewfinderView) findViewById(R.id.viewfinder_view); CameraManager.init(getApplication()); hasSurface = false; inactivityTimer = new InactivityTimer(this); } /** * 暂停后恢复时处理内容 */ @SuppressWarnings("all") @Override protected void onResume() { super.onResume(); // 先重新获得holder SurfaceHolder surfaceHolder = mSurfaceView.getHolder(); if (hasSurface) { initCamera(surfaceHolder); } else { surfaceHolder.addCallback(this); surfaceHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS); } mDecodeFormats = 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 (mHandler != null) { mHandler.quitSynchronously(); mHandler = null; } // 关闭摄像头信息 CameraManager.get().closeDriver(); } @Override protected void onDestroy() { // 关闭定时器 inactivityTimer.shutdown(); super.onDestroy(); } /** * 处理扫描结果 * * @param result * @param barcode */ public void handleDecode(Result result, Bitmap barcode) { // 添加定时器 inactivityTimer.onActivity(); // 响铃和震动 playBeepSoundAndVibrate(); String resultString = result.getText(); if (TextUtils.isEmpty(resultString)) { ToastUtil.show(this, "扫描失败"); ScanActivity.this.finish(); } else { //扫描完成后传递结果 Intent resultIntent = new Intent(); resultIntent.setClass(ScanActivity.this, ScanResultActivity.class); resultIntent.putExtra(RESULT_TEXT, resultString); ByteArrayOutputStream baos = new ByteArrayOutputStream(); barcode.compress(Bitmap.CompressFormat.PNG, 100, baos); byte[] bitmapByte = baos.toByteArray(); resultIntent.putExtra(RESULT_BITMAP, bitmapByte); startActivity(resultIntent); overridePendingTransition(R.anim.activity_in_from_rigth, R.anim.activity_out_to_scale); ScanActivity.this.finish(); } } private void initCamera(SurfaceHolder surfaceHolder) { try { CameraManager.get().openDriver(surfaceHolder); } catch (IOException ioe) { return; } catch (RuntimeException e) { return; } if (mHandler == null) { mHandler = new CaptureActivityHandler(this, mDecodeFormats, 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 mFindView; } public Handler getHandler() { return mHandler; } public void drawViewfinder() { mFindView.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); // 第一个参数,指代一个震动的频率数组。每两个为一组,每组的第一个为等待时间,第二个为震动时间。 // 比如 [2000,500,100,400],会先等待2000毫秒,震动500,再等待100,震动400 // 第二个参数,repest指代从 第几个索引(第一个数组参数) 的位置开始循环震动。 // 会一直保持循环,我们需要用 vibrator.cancel()主动终止 // vibrator.vibrate(new long[]{300,500},0); } } /** * 注册事件。当播放完毕一次后,重新指向流文件的开头,以准备下次播放。 */ private final MediaPlayer.OnCompletionListener beepListener = new MediaPlayer.OnCompletionListener() { public void onCompletion(MediaPlayer mediaPlayer) { mediaPlayer.seekTo(0); } };}

布局文件

3、结果页面

/** *  * @Project App_ZXing * @Package com.android.scan * @author chenlin * @version 1.0 * @Date 2014年3月6日 * @Note TODO */public class ScanResultActivity extends Activity {
private EditText mEtScan; private Button mBtnBack; private Button mBtnCopy; private ImageView mImageView; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_scan_result); initViews(); init(); } private void init() { final String result = getIntent().getStringExtra(ScanActivity.RESULT_TEXT); mEtScan.setText(result); final ClipboardManager cm = (ClipboardManager) getSystemService(CLIPBOARD_SERVICE); mBtnBack.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { ScanResultActivity.this.finish(); } }); mBtnCopy.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { if (result!=null) { ClipData myClip = ClipData.newPlainText("text", result); cm.setPrimaryClip(myClip); } } }); //设置图片信息 byte[] imgByte = getIntent().getByteArrayExtra(ScanActivity.RESULT_BITMAP); if (imgByte != null) { Drawable drawable = BitmapUtil.byte2Drawable(imgByte); if (drawable != null) { mImageView.setImageDrawable(drawable); } } } // public void paste(View view){
// ClipData abc = myClipboard.getPrimaryClip(); // ClipData.Item item = abc.getItemAt(0); // String text = item.getText().toString(); // pasteField.setText(text); // Toast.makeText(getApplicationContext(), "Text Pasted", // Toast.LENGTH_SHORT).show(); // } private void initViews() { mEtScan = (EditText) findViewById(R.id.et_scan_result); mBtnBack = (Button) findViewById(R.id.btn_back); mBtnCopy = (Button) findViewById(R.id.btn_copy); }}

四、代码下载

链接: 密码:tyyw

转载地址:https://lovoo.blog.csdn.net/article/details/51596966 如侵犯您的版权,请留言回复原文章的地址,我们会给您删除此文章,给您带来不便请您谅解!

上一篇:Android jni字符串如何加密
下一篇:Android Gallery Adapter的基本写法

发表评论

最新留言

初次前来,多多关照!
[***.217.46.12]2024年04月20日 13时11分52秒