实现二维码扫描

第一步,先导入zxing类库和jar包





第二步,在layout中添加两个布局

capture_activity.xml  :扫描界面的布局

[html]  view plain  copy
  1. <?xml version="1.0" encoding="utf-8"?>  
  2. <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"  
  3.     android:layout_width="match_parent"  
  4.     android:layout_height="match_parent"  
  5.     android:background="@android:color/transparent"  
  6.     android:orientation="vertical">  
  7.   
  8.     <SurfaceView  
  9.         android:id="@+id/capture_surfaceview"  
  10.         android:layout_width="match_parent"  
  11.         android:layout_height="match_parent" />  
  12.   
  13.     <RelativeLayout  
  14.         android:id="@+id/capture_container"  
  15.         android:layout_width="match_parent"  
  16.         android:layout_height="match_parent">  
  17.   
  18.         <ImageView  
  19.             android:id="@+id/capture_mask_top"  
  20.             android:layout_width="match_parent"  
  21.             android:layout_height="120dp"  
  22.             android:layout_alignParentTop="true"  
  23.             android:background="@mipmap/shadow" />  
  24.   
  25.         <RelativeLayout  
  26.             android:id="@+id/capture_crop_view"  
  27.             android:layout_width="220dp"  
  28.             android:layout_height="220dp"  
  29.             android:layout_below="@id/capture_mask_top"  
  30.             android:layout_centerHorizontal="true"  
  31.             android:background="@mipmap/zcapture">  
  32.   
  33.             <ImageView  
  34.                 android:id="@+id/capture_scan_line"  
  35.                 android:layout_width="match_parent"  
  36.                 android:layout_height="wrap_content"  
  37.                 android:layout_alignParentTop="true"  
  38.                 android:layout_marginBottom="5dp"  
  39.                 android:layout_marginTop="5dp"  
  40.                 android:src="@mipmap/scan_line" />  
  41.   
  42.         </RelativeLayout>  
  43.   
  44.         <ImageView  
  45.             android:id="@+id/capture_mask_bottom"  
  46.             android:layout_width="match_parent"  
  47.             android:layout_height="wrap_content"  
  48.             android:layout_alignParentBottom="true"  
  49.             android:layout_below="@id/capture_crop_view"  
  50.             android:background="@mipmap/shadow" />  
  51.   
  52.         <ImageView  
  53.             android:id="@+id/capture_mask_left"  
  54.             android:layout_width="wrap_content"  
  55.             android:layout_height="match_parent"  
  56.             android:layout_above="@id/capture_mask_bottom"  
  57.             android:layout_alignParentLeft="true"  
  58.             android:layout_below="@id/capture_mask_top"  
  59.             android:layout_toLeftOf="@id/capture_crop_view"  
  60.             android:background="@mipmap/shadow" />  
  61.   
  62.         <ImageView  
  63.             android:id="@+id/capture_mask_right"  
  64.             android:layout_width="wrap_content"  
  65.             android:layout_height="match_parent"  
  66.             android:layout_above="@id/capture_mask_bottom"  
  67.             android:layout_alignParentRight="true"  
  68.             android:layout_below="@id/capture_mask_top"  
  69.             android:layout_toRightOf="@id/capture_crop_view"  
  70.             android:background="@mipmap/shadow" />  
  71.     </RelativeLayout>  
  72.   
  73. </RelativeLayout>  

zxing_start_layout.xml :启动扫描界面的布局

[html]  view plain  copy
  1. <?xml version="1.0" encoding="utf-8"?>  
  2. <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"  
  3.     android:layout_width="match_parent"  
  4.     android:layout_height="match_parent"  
  5.     android:orientation="vertical">  
  6.   
  7.     <TextView  
  8.         android:layout_width="match_parent"  
  9.         android:layout_height="wrap_content"  
  10.         android:id="@+id/zxing_text"/>  
  11.     <Button  
  12.         android:layout_width="match_parent"  
  13.         android:layout_height="wrap_content"  
  14.         android:id="@+id/button1"  
  15.         android:text="扫码"/>  
  16. </LinearLayout>  

第三步,在res目录下新建目录raw存放音频文件,用于扫描成功后的提示音


在mipmap目录下放几张图片,作为扫描线,阴影,边框

qrcode_scan_line.png



scan_line.9.png


shadow.png



zcapture.9.png



目录:


第四步,在values目录下添加ids.xml文件

ids.xml

[html]  view plain  copy
  1. <?xml version="1.0" encoding="utf-8"?>  
  2. <resources>  
  3.     <item name="decode" type="id"/>  
  4.     <item name="decode_failed" type="id"/>  
  5.     <item name="decode_succeeded" type="id"/>  
  6.     <item name="quit" type="id"/>  
  7.     <item name="restart_preview" type="id"/>  
  8.     <item name="return_scan_result" type="id"/>  
  9.   
  10. </resources>  

第五步,新建一个StartCaptureActivity,用于启动扫描界面

[java]  view plain  copy
  1. package com.ard.captureapp.zxing.activity;  
  2.   
  3. import android.app.Activity;  
  4. import android.content.Intent;  
  5. import android.os.Bundle;  
  6. import android.view.View;  
  7. import android.widget.TextView;  
  8.   
  9. import com.ard.captureapp.R;  
  10.   
  11. public class StartCaptureActivity extends Activity {  
  12.     TextView tv=null;  
  13.     @Override  
  14.     protected void onCreate(Bundle savedInstanceState) {  
  15.         super.onCreate(savedInstanceState);  
  16.         setContentView(R.layout.zxing_start_layout);  
  17.         tv= (TextView) findViewById(R.id.zxing_text);  
  18.         findViewById(R.id.button1).setOnClickListener(new View.OnClickListener() {  
  19.             @Override  
  20.             public void onClick(View v) {  
  21.                 Intent intent = new Intent(StartCaptureActivity.this, CaptureActivity.class);  
  22.                 startActivityForResult(intent, 0x1);  
  23.             }  
  24.         });  
  25.     }  
  26. //重写该方法获取扫描完成后得到的结果  
  27.     @Override  
  28.     protected void onActivityResult(int requestCode, int resultCode, Intent data) {  
  29.         super.onActivityResult(requestCode, resultCode, data);  
  30.         if(resultCode==RESULT_OK&&data!=null){  
  31.             Bundle bundle=data.getExtras();  
  32.             tv.setText(bundle.getString("result"));  
  33.         }  
  34.     }  
  35. }  


修改CaptureActivity,重写其中的 handleDecode(Result rawResult, Bundle bundle)方法,使之将扫描的结果返回给StartCaptureActivity

[java]  view plain  copy
  1. /* 
  2.  * Copyright (C) 2008 ZXing authors 
  3.  * 
  4.  * Licensed under the Apache License, Version 2.0 (the "License"); 
  5.  * you may not use this file except in compliance with the License. 
  6.  * You may obtain a copy of the License at 
  7.  * 
  8.  *      http://www.apache.org/licenses/LICENSE-2.0 
  9.  * 
  10.  * Unless required by applicable law or agreed to in writing, software 
  11.  * distributed under the License is distributed on an "AS IS" BASIS, 
  12.  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 
  13.  * See the License for the specific language governing permissions and 
  14.  * limitations under the License. 
  15.  */  
  16. package com.ard.captureapp.zxing.activity;  
  17.   
  18. import android.app.Activity;  
  19. import android.app.AlertDialog;  
  20. import android.content.DialogInterface;  
  21. import android.content.Intent;  
  22. import android.graphics.Rect;  
  23. import android.os.Bundle;  
  24. import android.os.Handler;  
  25. import android.util.Log;  
  26. import android.view.SurfaceHolder;  
  27. import android.view.SurfaceView;  
  28. import android.view.Window;  
  29. import android.view.WindowManager;  
  30. import android.view.animation.Animation;  
  31. import android.view.animation.TranslateAnimation;  
  32. import android.widget.ImageView;  
  33. import android.widget.RelativeLayout;  
  34.   
  35.   
  36. import com.ard.captureapp.R;  
  37. import com.ard.captureapp.zxing.camera.CameraManager;  
  38. import com.ard.captureapp.zxing.decode.DecodeThread;  
  39. import com.ard.captureapp.zxing.utils.BeepManager;  
  40. import com.ard.captureapp.zxing.utils.CaptureActivityHandler;  
  41. import com.ard.captureapp.zxing.utils.InactivityTimer;  
  42. import com.google.zxing.Result;  
  43.   
  44. import java.io.IOException;  
  45. import java.lang.reflect.Field;  
  46.   
  47. /** 
  48.  * This activity opens the camera and does the actual scanning on a background 
  49.  * thread. It draws a viewfinder to help the user place the barcode correctly, 
  50.  * shows feedback as the image processing is happening, and then overlays the 
  51.  * results when a scan is successful. 
  52.  * 
  53.  */  
  54. public final class CaptureActivity extends Activity implements SurfaceHolder.Callback {  
  55.   
  56.     private static final String TAG = CaptureActivity.class.getSimpleName();  
  57.   
  58.     private CameraManager cameraManager;  
  59.     private CaptureActivityHandler handler;  
  60.     private InactivityTimer inactivityTimer;  
  61.     private BeepManager beepManager;  
  62.     private SurfaceView scanPreview = null;  
  63.     private RelativeLayout scanContainer;  
  64.     private RelativeLayout scanCropView;  
  65.     private ImageView scanLine;  
  66.   
  67.     private Rect mCropRect = null;  
  68.     private boolean isHasSurface = false;  
  69.   
  70.     public Handler getHandler() {  
  71.         return handler;  
  72.     }  
  73.   
  74.     public CameraManager getCameraManager() {  
  75.         return cameraManager;  
  76.     }  
  77.   
  78.     @Override  
  79.     public void onCreate(Bundle icicle) {  
  80.         super.onCreate(icicle);  
  81.         Window window = getWindow();  
  82.         window.addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);  
  83.         setContentView(R.layout.capture_activity);  
  84.   
  85.         initView();  
  86.   
  87.     }  
  88.   
  89.     private void initView() {  
  90.         scanPreview = (SurfaceView) findViewById(R.id.capture_surfaceview);  
  91.         scanContainer = (RelativeLayout) findViewById(R.id.capture_container);  
  92.         scanCropView = (RelativeLayout) findViewById(R.id.capture_crop_view);  
  93.         scanLine = (ImageView) findViewById(R.id.capture_scan_line);  
  94.   
  95.         inactivityTimer = new InactivityTimer(this);  
  96.         beepManager = new BeepManager(this);  
  97.   
  98.         TranslateAnimation animation = new TranslateAnimation(Animation.RELATIVE_TO_PARENT, 0.0f, Animation  
  99.                 .RELATIVE_TO_PARENT, 0.0f, Animation.RELATIVE_TO_PARENT, 0.0f, Animation.RELATIVE_TO_PARENT,  
  100.                 0.9f);  
  101.         animation.setDuration(4500);  
  102.         animation.setRepeatCount(-1);  
  103.         animation.setRepeatMode(Animation.RESTART);  
  104.         scanLine.startAnimation(animation);  
  105.     }  
  106.   
  107.     @Override  
  108.     protected void onResume() {  
  109.         super.onResume();  
  110.   
  111.         // CameraManager must be initialized here, not in onCreate(). This is  
  112.         // necessary because we don't  
  113.         // want to open the camera driver and measure the screen size if we're  
  114.         // going to show the help on  
  115.         // first launch. That led to bugs where the scanning rectangle was the  
  116.         // wrong size and partially  
  117.         // off screen.  
  118.         cameraManager = new CameraManager(getApplication());  
  119.   
  120.         handler = null;  
  121.   
  122.         if (isHasSurface) {  
  123.             // The activity was paused but not stopped, so the surface still  
  124.             // exists. Therefore  
  125.             // surfaceCreated() won't be called, so init the camera here.  
  126.             initCamera(scanPreview.getHolder());  
  127.         } else {  
  128.             // Install the callback and wait for surfaceCreated() to init the  
  129.             // camera.  
  130.             scanPreview.getHolder().addCallback(this);  
  131.         }  
  132.   
  133.         inactivityTimer.onResume();  
  134.     }  
  135.   
  136.     @Override  
  137.     protected void onPause() {  
  138.         if (handler != null) {  
  139.             handler.quitSynchronously();  
  140.             handler = null;  
  141.         }  
  142.         inactivityTimer.onPause();  
  143.         beepManager.close();  
  144.         cameraManager.closeDriver();  
  145.         if (!isHasSurface) {  
  146.             scanPreview.getHolder().removeCallback(this);  
  147.         }  
  148.         super.onPause();  
  149.     }  
  150.   
  151.     @Override  
  152.     protected void onDestroy() {  
  153.         inactivityTimer.shutdown();  
  154.         super.onDestroy();  
  155.     }  
  156.   
  157.     @Override  
  158.     public void surfaceCreated(SurfaceHolder holder) {  
  159.         if (holder == null) {  
  160.             Log.e(TAG, "*** WARNING *** surfaceCreated() gave us a null surface!");  
  161.         }  
  162.         if (!isHasSurface) {  
  163.             isHasSurface = true;  
  164.             initCamera(holder);  
  165.         }  
  166.     }  
  167.   
  168.     @Override  
  169.     public void surfaceDestroyed(SurfaceHolder holder) {  
  170.         isHasSurface = false;  
  171.     }  
  172.   
  173.     @Override  
  174.     public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {  
  175.   
  176.     }  
  177.   
  178.     /** 
  179.      * A valid barcode has been found, so give an indication of success and show 
  180.      * the results. 
  181.      * 
  182.      * @param rawResult The contents of the barcode. 
  183.      * @param bundle    The extras 
  184.      */  
  185.     public void handleDecode(Result rawResult, Bundle bundle) {  
  186.         inactivityTimer.onActivity();  
  187.         beepManager.playBeepSoundAndVibrate();  
  188. /** 
  189.  * 返回解析数据 
  190.  * 注:用真机测试 
  191.  */  
  192.         Intent resultIntent = new Intent();  
  193.         bundle.putString("result", rawResult.getText());  
  194.         resultIntent.putExtras(bundle);  
  195.         this.setResult(RESULT_OK, resultIntent);  
  196.         CaptureActivity.this.finish();  
  197.     }  
  198.   
  199.     private void initCamera(SurfaceHolder surfaceHolder) {  
  200.         if (surfaceHolder == null) {  
  201.             throw new IllegalStateException("No SurfaceHolder provided");  
  202.         }  
  203.         if (cameraManager.isOpen()) {  
  204.             Log.w(TAG, "initCamera() while already open -- late SurfaceView callback?");  
  205.             return;  
  206.         }  
  207.         try {  
  208.             cameraManager.openDriver(surfaceHolder);  
  209.             // Creating the handler starts the preview, which can also throw a  
  210.             // RuntimeException.  
  211.             if (handler == null) {  
  212.                 handler = new CaptureActivityHandler(this, cameraManager, DecodeThread.ALL_MODE);  
  213.             }  
  214.   
  215.             initCrop();  
  216.   
  217.   
  218.         } catch (IOException ioe) {  
  219.             Log.w(TAG, ioe);  
  220.             displayFrameworkBugMessageAndExit();  
  221.         } catch (RuntimeException e) {  
  222.             // Barcode Scanner has seen crashes in the wild of this variety:  
  223.             // java.?lang.?RuntimeException: Fail to connect to camera service  
  224.             Log.w(TAG, "Unexpected error initializing camera", e);  
  225.             displayFrameworkBugMessageAndExit();  
  226.         }  
  227.     }  
  228.   
  229.     private void displayFrameworkBugMessageAndExit() {  
  230.         // camera error  
  231.         AlertDialog.Builder builder = new AlertDialog.Builder(this);  
  232.         builder.setTitle(getString(R.string.app_name));  
  233.         builder.setMessage("Camera error");  
  234.         builder.setPositiveButton("OK"new DialogInterface.OnClickListener() {  
  235.   
  236.             @Override  
  237.             public void onClick(DialogInterface dialog, int which) {  
  238.                 finish();  
  239.             }  
  240.   
  241.         });  
  242.         builder.setOnCancelListener(new DialogInterface.OnCancelListener() {  
  243.   
  244.             @Override  
  245.             public void onCancel(DialogInterface dialog) {  
  246.                 finish();  
  247.             }  
  248.         });  
  249.         builder.show();  
  250.     }  
  251.   
  252.     public void restartPreviewAfterDelay(long delayMS) {  
  253.         if (handler != null) {  
  254.             handler.sendEmptyMessageDelayed(R.id.restart_preview, delayMS);  
  255.         }  
  256.     }  
  257.   
  258.     public Rect getCropRect() {  
  259.         return mCropRect;  
  260.     }  
  261.   
  262.     /** 
  263.      * 初始化截取的矩形区域 
  264.      */  
  265.     private void initCrop() {  
  266.         int cameraWidth = cameraManager.getCameraResolution().y;  
  267.         int cameraHeight = cameraManager.getCameraResolution().x;  
  268.   
  269.         /** 获取布局中扫描框的位置信息 */  
  270.         int[] location = new int[2];  
  271.         scanCropView.getLocationInWindow(location);  
  272.   
  273.         int cropLeft = location[0];  
  274.         int cropTop = location[1] - getStatusBarHeight();  
  275.   
  276.         int cropWidth = scanCropView.getWidth();  
  277.         int cropHeight = scanCropView.getHeight();  
  278.   
  279.         /** 获取布局容器的宽高 */  
  280.         int containerWidth = scanContainer.getWidth();  
  281.         int containerHeight = scanContainer.getHeight();  
  282.   
  283.         /** 计算最终截取的矩形的左上角顶点x坐标 */  
  284.         int x = cropLeft * cameraWidth / containerWidth;  
  285.         /** 计算最终截取的矩形的左上角顶点y坐标 */  
  286.         int y = cropTop * cameraHeight / containerHeight;  
  287.   
  288.         /** 计算最终截取的矩形的宽度 */  
  289.         int width = cropWidth * cameraWidth / containerWidth;  
  290.         /** 计算最终截取的矩形的高度 */  
  291.         int height = cropHeight * cameraHeight / containerHeight;  
  292.   
  293.         /** 生成最终的截取的矩形 */  
  294.         mCropRect = new Rect(x, y, width + x, height + y);  
  295.     }  
  296.   
  297.     private int getStatusBarHeight() {  
  298.         try {  
  299.             Class<?> c = Class.forName("com.android.internal.R$dimen");  
  300.             Object obj = c.newInstance();  
  301.             Field field = c.getField("status_bar_height");  
  302.             int x = Integer.parseInt(field.get(obj).toString());  
  303.             return getResources().getDimensionPixelSize(x);  
  304.         } catch (Exception e) {  
  305.             e.printStackTrace();  
  306.         }  
  307.         return 0;  
  308.     }  
  309. }  


注意:要在清单文件中配置这两个Activity,并添加相关权限

[html]  view plain  copy
  1. <?xml version="1.0" encoding="utf-8"?>  
  2. <manifest xmlns:android="http://schemas.android.com/apk/res/android"  
  3.     package="com.ard.captureapp" >  
  4.   
  5.   
  6.     <!-- 摄像头权限 -->   <!-- 二维码扫码 -->  
  7.     <uses-permission android:name="android.permission.CAMERA" />  
  8.     <uses-permission android:name="android.permission.FLASHLIGHT" />  
  9.     <uses-permission android:name="android.permission.VIBRATE" />  
  10.   
  11.     <uses-feature android:name="android.hardware.camera" />  
  12.     <uses-feature android:name="android.hardware.camera.autofocus" />  
  13.     <application  
  14.         android:allowBackup="true"  
  15.         android:icon="@mipmap/ic_launcher"  
  16.         android:label="@string/app_name"  
  17.         android:supportsRtl="true"  
  18.         android:theme="@style/AppTheme" >  
  19.         <activity android:name=".zxing.activity.StartCaptureActivity" >  
  20.             <intent-filter>  
  21.                 <action android:name="android.intent.action.MAIN" />  
  22.   
  23.                 <category android:name="android.intent.category.LAUNCHER" />  
  24.             </intent-filter>  
  25.         </activity>  
  26.         <activity android:name=".zxing.activity.CaptureActivity"/>  
  27.     </application>  
  28.   
  29. </manifest>  

猜你喜欢

转载自blog.csdn.net/supercreators/article/details/80159430