android基于zBar扫一扫案例
2016-07-25 20:38
531 查看
刚刚工作接到的第二个任务是做出二维码扫描基于ZBar的,代码如下 废话不多说,直接上代码,经本人翻阅大量的资料,发现好像基于ZBar的从相册中直接扫描出二维码的案例,貌似不可能实现!!!如果有人实现这个功能希望共享一下,感激不尽!
布局文件 其中的一些图片没有共享,由于时间很紧,希望谅解!
做这个功能时 记住先下载zbar的包和其中的几个文件,这个可自行百度!这里只给出思路!
扫描成功后的显示结果界面
这个类用于实现扫描
这个类是扫描时最上面的框以及不断滑动的横线
这个类用于显示结果
由于时间现在很紧,所以写的比较仓促,认真读一下代码,应该可以实现出功能!
布局文件 其中的一些图片没有共享,由于时间很紧,希望谅解!
做这个功能时 记住先下载zbar的包和其中的几个文件,这个可自行百度!这里只给出思路!
<?xml version="1.0" encoding="utf-8"?> <FrameLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" > <RelativeLayout android:layout_width="match_parent" android:layout_height="match_parent" android:layout_weight="1" android:background="@drawable/qrcode_frame_icon" > <SurfaceView android:id="@+id/surfaceview" android:layout_width="match_parent" android:layout_height="match_parent" /> <com.example.test5.QRCodeFinderView android:id="@+id/findView" android:layout_width="match_parent" android:layout_height="wrap_content"/> </RelativeLayout> <!-- 返回按钮 --> <!-- 说明部分 --> <RelativeLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_gravity="center_horizontal" android:layout_marginTop="285dp" android:gravity="center_horizontal" > <TextView android:id="@+id/explain" android:layout_width="280dp" android:layout_height="wrap_content" android:layout_centerHorizontal="true" android:layout_marginTop="40dp" android:text="@string/qrcode_notice" android:textColor="@android:color/white" android:textSize="@dimen/fontSize" /> <!-- 闪光灯 --> <RelativeLayout android:id="@+id/qrcodeLight" android:layout_width="200dp" android:layout_height="36dp" android:layout_below="@+id/explain" android:layout_centerHorizontal="true" android:layout_marginTop="10dp" android:background="@drawable/layer_list_ex" android:gravity="center" > <TextView android:id="@+id/light_BtnText" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="center_vertical" android:text="@string/qrcode_light" android:textColor="@android:color/white" android:textSize="@dimen/fontSize" /> </RelativeLayout> <!-- 添加设备 --> <RelativeLayout android:id="@+id/qrcode_adddevice" android:layout_width="200dp" android:layout_height="36dp" android:layout_below="@+id/qrcodeLight" android:layout_centerHorizontal="true" android:layout_marginTop="10dp" android:background="@drawable/layer_list_ex" android:gravity="center" > <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="center_vertical" android:text="@string/add_device" android:textColor="@android:color/white" android:textSize="@dimen/fontSize" /> </RelativeLayout> </RelativeLayout> <RelativeLayout android:layout_width="match_parent" android:layout_height="50dp" android:background="@color/navigation_bar_bg"> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_centerInParent="true" android:layout_centerVertical="true" android:text="@string/activity_qrcode_title" android:textColor="@color/white" android:textSize="@dimen/title_text_size" /> <ImageButton android:id="@+id/qrcode_back" android:layout_width="@dimen/back_imgbtn_width" android:layout_height="@dimen/back_imgbtn_height" android:layout_marginLeft="12dp" android:layout_centerVertical="true" android:background="@drawable/qrcode_back_icon" /> <Button android:id="@+id/btnImage" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignParentTop="true" android:layout_alignParentRight="true" android:text="@string/click" /> </RelativeLayout> </FrameLayout>
扫描成功后的显示结果界面
<?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" > <RelativeLayout android:id="@+id/title_bar" android:layout_width="fill_parent" android:layout_height="50dp" android:background="@color/navigation_bar_bg" > <ImageButton android:id="@+id/qrcode_sucess_back" android:layout_width="@dimen/back_imgbtn_width" android:layout_height="@dimen/back_imgbtn_height" android:layout_centerVertical="true" android:layout_marginLeft="12dp" android:background="@drawable/back_button_selector" /> <TextView android:id="@+id/titleText" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_centerInParent="true" android:layout_centerVertical="true" android:text="@string/result" android:textColor="@color/white" android:textSize="@dimen/title_text_size" /> </RelativeLayout> <TextView android:id="@+id/tvResult" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_centerVertical="true" android:layout_centerHorizontal="true" /> </RelativeLayout>
这个类用于实现扫描
package com.example.test5; import java.util.List; import net.sourceforge.zbar.Config; import net.sourceforge.zbar.Image; import net.sourceforge.zbar.ImageScanner; import net.sourceforge.zbar.Symbol; import net.sourceforge.zbar.SymbolSet; import android.app.Activity; import android.content.Intent; import android.content.pm.ActivityInfo; import android.graphics.Rect; import android.hardware.Camera; import android.hardware.Camera.AutoFocusCallback; import android.hardware.Camera.PreviewCallback; import android.hardware.Camera.Size; import android.net.Uri; import android.os.AsyncTask; import android.os.Bundle; import android.os.Handler; import android.util.Log; import android.view.SurfaceHolder; import android.view.SurfaceView; import android.view.View; import android.view.View.OnClickListener; import android.widget.Button; import android.widget.Toast; public class MfrmQRCode extends Activity implements SurfaceHolder.Callback { private static final int DOAUTOFOCUSDELAY = 1000; // surfaceView private SurfaceHolder mHolder; private SurfaceView surfaceView; // 用于自动聚焦 private Handler autoFocusHandler; private AsyncDecode asyncDecode; // 图片扫描器 ImageScanner scanner; // 相机 private Camera mCamera; public static final String TAG = "MfrmQRCode"; private String QRcode; // 扫描surfaceView private QRCodeFinderView findView; Button btnImage; Image barcode; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_qrcode); initVaraible(); addListener(); } private void addListener() { btnImage.setOnClickListener(new ClickImage()); } private void initVaraible() { findView = (QRCodeFinderView) findViewById(R.id.findView); // 强制竖屏 setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT); // 获取照相机 // mCamera = getCameraInstance(); autoFocusHandler = new Handler(); // 图形初始化 scanner = new ImageScanner(); scanner.setConfig(0, Config.X_DENSITY, 3); scanner.setConfig(0, Config.Y_DENSITY, 3); surfaceView = (SurfaceView) findViewById(R.id.surfaceview); mHolder = surfaceView.getHolder(); mHolder.addCallback(this); // android 3.0以下版本需要增加此方法 mHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS); asyncDecode = new AsyncDecode(); btnImage = (Button) findViewById(R.id.btnImage); } // callBack中的方法 @Override public void surfaceChanged(SurfaceHolder holder, int format, int width, int hight) { if (mHolder.getSurface() == null || mCamera == null) { return; } try { mCamera.stopPreview(); } catch (Exception e) { } try { mCamera.setDisplayOrientation(90); mCamera.setPreviewDisplay(mHolder); mCamera.setPreviewCallback(previewCallback); mCamera.startPreview(); mCamera.autoFocus(autoFocusCallback); } catch (Exception e) { Log.d(TAG, "Error starting canera preview:" + e.getMessage()); } } // Image类用于获取二维码图片,ImageScanner类用于对图片的初步解析,而图片的最终解析是在SymbolSet类和 // Symbol中去实现的 PreviewCallback previewCallback = new PreviewCallback() { @Override public void onPreviewFrame(byte[] date, Camera camera) { if (asyncDecode.stoped) { Camera.Parameters parameters = camera.getParameters(); Size size = parameters.getPreviewSize(); Image barcodeImage = new Image(size.width, size.height, "Y800"); Rect scanImageRect = findView.getScanImageRect(size.height, size.width); barcodeImage.setCrop(scanImageRect.top, scanImageRect.left, scanImageRect.bottom, scanImageRect.right); barcodeImage.setData(date); asyncDecode = new AsyncDecode(); asyncDecode.execute(barcodeImage); } } }; private class AsyncDecode extends AsyncTask<Image, Void, Void> { // ------------------------------------- private boolean stoped = true; @Override protected Void doInBackground(Image... params) { stoped = false; barcode = params[0]; int result = scanner.scanImage(barcode); if (result != 0) { SymbolSet syms = scanner.getResults(); // 扫描成功跳转到设备详情页面 for (Symbol sym : syms) { QRcode = sym.getData(); if (QRcode != null) { Intent intent = new Intent(MfrmQRCode.this, Result.class); intent.putExtra("Code", sym.getData()); startActivity(intent); } else { Toast.makeText(getApplicationContext(), "错误", Toast.LENGTH_SHORT).show(); } return null; } } return null; } @Override protected void onPostExecute(Void result) { super.onPostExecute(result); stoped = true; } } // 自动对焦回调 AutoFocusCallback autoFocusCallback = new AutoFocusCallback() { @Override public void onAutoFocus(boolean success, Camera camera) { autoFocusHandler.postDelayed(doAutoFocus, DOAUTOFOCUSDELAY); } }; // 自动对焦 private Runnable doAutoFocus = new Runnable() { @Override public void run() { if (mCamera == null || autoFocusCallback == null) { return; } mCamera.autoFocus(autoFocusCallback); } }; @Override public void surfaceCreated(SurfaceHolder holder) { try { mCamera = Camera.open(0); if (mCamera != null) { Camera.Parameters parameters = mCamera.getParameters(); if (parameters.getPreviewSize().width > 1920) { List<Size> supportedPreviewSizes = parameters .getSupportedPreviewSizes(); for (int i = 0; i < supportedPreviewSizes.size(); i++) { if (supportedPreviewSizes.get(i).width == 1920 && supportedPreviewSizes.get(i).height == 1080) { parameters.setPreviewSize(1920, 1080); mCamera.setParameters(parameters); break; } else if (supportedPreviewSizes.get(i).width == 1280 && supportedPreviewSizes.get(i).height == 720) { parameters.setPreviewSize(1280, 720); mCamera.setParameters(parameters); break; } else if (supportedPreviewSizes.get(i).width == 640 && supportedPreviewSizes.get(i).height == 480) { parameters.setPreviewSize(640, 480); mCamera.setParameters(parameters); break; } } } mCamera.setDisplayOrientation(90); mCamera.setPreviewDisplay(mHolder); mCamera.setPreviewCallback(previewCallback); mCamera.startPreview(); } } catch (Exception e) { Log.d(TAG, "JSONException :" + e); mCamera = null; } } @Override public void surfaceDestroyed(SurfaceHolder holder) { if (mCamera != null) { mCamera.setPreviewCallback(null); mCamera.release(); mCamera = null; } } class ClickImage implements OnClickListener { @Override public void onClick(View v) { Intent intent = new Intent(); intent.setType("image/*"); intent.setAction(Intent.ACTION_GET_CONTENT); startActivityForResult(intent, 0); } } @Override protected void onActivityResult(int requestCode, int resultCode, Intent data) { if (data != null) { // 得到图片的全路径 Uri uri = data.getData(); // 通过路径加载图片 // 这里省去了图片缩放操作,如果图片过大,可能会导致内存泄漏 // 图片缩放的实现,请看:http://blog.csdn.net/reality_jie_blog/article/details/16891095 /* * Log.e("TAG--------------", uri+""); ContentResolver cr = * this.getContentResolver(); bmp = MediaStore.Images.Media.getBitmap(cr, uri); */ // 获取图片的缩略图,可能为空! // Bitmap bitmap = data.getParcelableExtra("data"); // this.iv_image.setImageBitmap(bitmap); } super.onActivityResult(requestCode, resultCode, data); } }
这个类是扫描时最上面的框以及不断滑动的横线
package com.example.test5; import android.content.Context; import android.graphics.Canvas; import android.graphics.Paint; import android.graphics.Rect; import android.graphics.drawable.Drawable; import android.util.AttributeSet; import android.view.View; public class QRCodeFinderView extends View{ private static final long ANIMATION_DELAY = 30; private static final int LINE_HEIGHT = 30; private Paint finderMaslPaint; private int measureedWidth; private int measureedHeight; private Rect topRect = new Rect(); private Rect bottomRect = new Rect(); private Rect rightRect = new Rect(); private Rect leftRect = new Rect(); private Rect middleRect = new Rect(); private Rect lineRect = new Rect(); private Drawable zx_code_kuang; private Drawable zx_code_line; private int lineHeight; public QRCodeFinderView(Context context,AttributeSet attrs){ super(context, attrs); init(context); } @Override protected void onDraw(Canvas canvas) { // TODO Auto-generated method stub super.onDraw(canvas); //确定矩形框的大小 canvas.drawRect(leftRect,finderMaslPaint); canvas.drawRect(topRect,finderMaslPaint); canvas.drawRect(rightRect,finderMaslPaint); canvas.drawRect(bottomRect,finderMaslPaint); //画框 zx_code_kuang.setBounds(middleRect); zx_code_kuang.draw(canvas); //线的循环位置 if(lineRect.bottom < middleRect.bottom){ zx_code_line.setBounds(lineRect); lineRect.top = lineRect.top + lineHeight / 5; lineRect.bottom = lineRect.bottom +lineHeight /5; }else{ lineRect.set(middleRect); lineRect.bottom = lineRect.top +lineHeight; zx_code_line.setBounds(lineRect); } zx_code_line.draw(canvas); postInvalidateDelayed(ANIMATION_DELAY, middleRect.left, middleRect.top, middleRect.right, middleRect.bottom); } private void init(Context context) { // 设置底层半透明 int finder_mask = context.getResources().getColor(R.color.qecode_transparent_bg); finderMaslPaint = new Paint(Paint.ANTI_ALIAS_FLAG); finderMaslPaint.setColor(finder_mask); //引入项目所需的图 zx_code_kuang = context.getResources().getDrawable(R.drawable.qrcode_frame_icon); zx_code_line = context.getResources().getDrawable(R.drawable.qrcode_line_icon); //线的高度 lineHeight = LINE_HEIGHT; } public Rect getScanImageRect(int w, int h) { //先求出实际矩形 Rect rect = new Rect(); float temp_w = w / (float) measureedWidth; rect.left = (int)(middleRect.left * temp_w); rect.right = (int)(middleRect.right * temp_w); float temp_h = h / (float) measureedHeight; rect.top = (int) (middleRect.top * temp_h); rect.bottom = (int) (middleRect.bottom * temp_h); return rect; } //自定义View重载函数 @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { // TODO Auto-generated method stub super.onMeasure(widthMeasureSpec, heightMeasureSpec); //屏幕初始值 measureedWidth = MeasureSpec.getSize(widthMeasureSpec); measureedHeight = MeasureSpec.getSize(heightMeasureSpec); int borderWidth = measureedWidth / 2 +100; //矩形框的位置[对应位置设置,依次为左上右下,数值越大矩形扫描位置更改越大。] middleRect.set((measureedWidth - borderWidth) /2,(measureedHeight - borderWidth) / 4,(measureedWidth - borderWidth) / 2 + borderWidth,(measureedHeight - borderWidth) / 4 + borderWidth); lineRect.set(middleRect); //确定矩形框大小,分别减去左上右下的多余部分,确定大小 leftRect.set(0, middleRect.top, middleRect.left,middleRect.bottom); topRect.set(0,0, measureedWidth,middleRect.top); rightRect.set(middleRect.right, middleRect.top, measureedWidth, middleRect.bottom); bottomRect.set(0, middleRect.bottom, measureedWidth,measureedHeight); } }
这个类用于显示结果
package com.example.test5; import android.app.Activity; import android.content.Intent; import android.os.Bundle; import android.text.style.BackgroundColorSpan; import android.view.View; import android.view.View.OnClickListener; import android.widget.Button; import android.widget.ImageButton; import android.widget.TextView; public class Result extends Activity { private TextView tView; private ImageButton imageButton; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.result); init(); addListener(); } private void init() { tView = (TextView) findViewById(R.id.tvResult); imageButton = (ImageButton) findViewById(R.id.qrcode_sucess_back); /* 取出Intent中附加的数据 */ Bundle sBundle = getIntent().getExtras(); CharSequence mResult = sBundle.getCharSequence("Code"); tView.setText(mResult); } private void addListener() { imageButton.setOnClickListener(new Back()); } class Back implements OnClickListener { @Override public void onClick(View v) { Intent intent = new Intent(Result.this, MfrmQRCode.class); startActivity(intent); } } }
由于时间现在很紧,所以写的比较仓促,认真读一下代码,应该可以实现出功能!
相关文章推荐
- Android事件分发机制
- Android SharedPreferences的剖析
- ANDROID中vnd.android.cursor的解释
- android studio 怎么引入签名文件
- Android Studio中Android应用程序签名打包方法
- 引入layoutlib.jar
- dispatchTouchEvent源码解析
- 深入理解Android之Gradle
- Android Camera之CameraMetadata分析
- android实现中间卡位下方viewpager效果展示
- Android Activity.startActivity流程简介
- android五种进程
- android检查更新(强制更新)
- Android 人脸检测
- 自定义View
- Android计时器
- Android官方数据绑定框架DataBinding
- Android下logcat用法详解
- 【转】关于使用Android6.0编译程序时,出现getSlotFromBufferLocked: unknown buffer: 0xac0f8650问题的解释
- Android开源框架Universal-Image-Loader详解