android studio下引入zxing二维码扫描并修改为竖屏

本文介绍了如何在Android Studio项目中集成ZXing二维码扫描库,并详细步骤指导如何将扫描界面修改为竖屏显示。包括下载源码、添加依赖、配置权限、精简源码以及修改相机参数以实现竖屏显示。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

step1: 

下载zxing源代码 


step2:

build.gradle中加入必须的核心库

dependencies {

     /**zxing二维码生成与识别核心库**/
compile 'com.google.zxing:core:latest.integration'
/**zxing二维码扫描for android核心库**/
compile 'com.google.zxing:android-core:latest.integration'

}


step3:

增加使用摄像头所需要的权限

     <uses-permission android:name="android.permission.CAMERA"/>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<uses-feature android:name="android.hardware.camera"/>
<uses-feature android:name="android.hardware.camera.autofocus"/>
<uses-permission android:name="android.permission.VIBRATE"/>
<uses-permission android:name="android.permission.FLASHLIGHT"/>


step4:

精简源码

4.1 将zxing源码中->camera包下所有文件copy到需要移植的项目里面


4.2 新建一个decode包将解码相关的文件导入

CaptureActivityHandler.java 

DecodeFormatManager.java 

DecodeHandler.java 

DecodeThread.java 

FinishListener.java

InactivityTimer.java 

Intents.java


4.3新建一个preference包将相关文件导入(虽然没多大用处,导入相关文件并不会影响程序,能减少引用error,减少麻烦就加进来了)

PreferencesActivity.java

PreferencesFragment.java


4.4 copy 自定义view

ViewfinderView.java 

ViewfinderResultPointCallback.java


4.5 导入manager

闪光灯 AmbientLightManager.java 

提示音 BeepManager.java 

解析管理 DecodeFormatManager.java DecodeHintManager.java


4.6 建议不要使用源码下的CaptureActivity.java 建议自己新建一个

     package com.denong.happilitt.com3rd.zxing;

import android.app.Activity;
import android.app.AlertDialog;
import android.content.Intent;
import android.graphics.Bitmap;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.view.View;
import android.widget.TextView;

import com.denong.happilitt.R;
import com.denong.happilitt.com3rd.zxing.camera.CameraManager;
import com.denong.happilitt.com3rd.zxing.decoding.CaptureActivityHandler;
import com.denong.happilitt.com3rd.zxing.decoding.FinishListener;
import com.denong.happilitt.com3rd.zxing.decoding.InactivityTimer;
import com.denong.happilitt.com3rd.zxing.decoding.Intents;
import com.denong.happilitt.com3rd.zxing.view.ViewfinderView;
import com.denong.happilitt.frame.log.Logger;
import com.google.zxing.BarcodeFormat;
import com.google.zxing.DecodeHintType;
import com.google.zxing.Result;

import java.io.IOException;
import java.util.Collection;
import java.util.Map;

import butterknife.Bind;
import butterknife.ButterKnife;


/**
 * Created by chendy on 15/12/3.
 */
public class CaptureActivity extends Activity implements SurfaceHolder.Callback {

    @Bind(R.id.preview_view)
    android.view.SurfaceView previewView;
    @Bind(R.id.viewfinder_view)
    ViewfinderView viewfinderView;
    @Bind(R.id.txtResult)
    TextView txtResult;

    private CameraManager cameraManager;
    private BeepManager beepManager;
    private AmbientLightManager ambientLightManager;
    private CaptureActivityHandler handler;
    private Result savedResultToShow;
    private Collection<BarcodeFormat> decodeFormats;
    private Map<DecodeHintType,?> decodeHints;
    private String characterSet;
    private InactivityTimer inactivityTimer;
    private boolean hasSurface;

    public ViewfinderView getViewfinderView() {
        return viewfinderView;
    }

    public Handler getHandler() {
        return handler;
    }

    public CameraManager getCameraManager() {
        return cameraManager;
    }

    public void drawViewfinder() {
        viewfinderView.drawViewfinder();
    }

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.qrcode_capture_page);
        ButterKnife.bind(this);
        inactivityTimer = new InactivityTimer(this);
        beepManager = new BeepManager(this);
        ambientLightManager = new AmbientLightManager(this);
    }

    @Override
    protected void onResume() {
        super.onResume();
        // CameraManager must be initialized here, not in onCreate(). This is necessary because we don't
        // want to open the camera driver and measure the screen size if we're going to show the help on
        // first launch. That led to bugs where the scanning rectangle was the wrong size and partially
        // off screen.
        cameraManager = new CameraManager(getApplication());
        viewfinderView.setCameraManager(cameraManager);

        beepManager.updatePrefs();
        ambientLightManager.start(cameraManager);
        inactivityTimer.onResume();

        SurfaceHolder surfaceHolder = previewView.getHolder();
        if (hasSurface) {
            initCamera(surfaceHolder);
        } else {
            surfaceHolder.addCallback(this);
//            surfaceHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
        }
        decodeFormats = null;
        characterSet = null;

        Intent intent = getIntent();
        if(null != intent){
            String action = intent.getAction();
            if (Intents.Scan.ACTION.equals(action)) {
                // Scan the formats the intent requested, and return the result to the calling activity.
                decodeFormats = DecodeFormatManager.parseDecodeFormats(intent);
                decodeHints = DecodeHintManager.parseDecodeHints(intent);
                if (intent.hasExtra(Intents.Scan.WIDTH) && intent.hasExtra(Intents.Scan.HEIGHT)) {
                    int width = intent.getIntExtra(Intents.Scan.WIDTH, 0);
                    int height = intent.getIntExtra(Intents.Scan.HEIGHT, 0);
                    if (width > 0 && height > 0) {
                        cameraManager.setManualFramingRect(width, height);
                    }
                }

                if (intent.hasExtra(Intents.Scan.CAMERA_ID)) {
                    int cameraId = intent.getIntExtra(Intents.Scan.CAMERA_ID, -1);
                    if (cameraId >= 0) {
                        cameraManager.setManualCameraId(cameraId);
                    }
                }

            }
        }

        viewfinderView.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                if(i == 0){
                    cameraManager.openLight();
                    i = 1;
                }else{
                    cameraManager.offLight();
                    i = 0;
                }
            }
        });
    }

    private int i = 0;

    @Override
    protected void onPause() {
        if (handler != null) {
            handler.quitSynchronously();
            handler = null;
        }
        inactivityTimer.onPause();
        ambientLightManager.stop();
        beepManager.close();
        cameraManager.closeDriver();
        //historyManager = null; // Keep for onActivityResult
        if (!hasSurface) {
            SurfaceView surfaceView = (SurfaceView) findViewById(R.id.preview_view);
            SurfaceHolder surfaceHolder = surfaceView.getHolder();
            surfaceHolder.removeCallback(this);
        }
        super.onPause();
    }


    @Override
    protected void onDestroy() {
        inactivityTimer.shutdown();
        super.onDestroy();
    }


    @Override
    public void surfaceCreated(SurfaceHolder holder) {
        if (holder == null) {
            Logger.output("*** WARNING *** surfaceCreated() gave us a null surface!");
        }
        if (!hasSurface) {
            hasSurface = true;
            initCamera(holder);
        }
    }

    @Override
    public void surfaceDestroyed(SurfaceHolder holder) {
        hasSurface = false;
    }

    @Override
    public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {

    }

    private void initCamera(SurfaceHolder surfaceHolder) {
        if (surfaceHolder == null) {
            throw new IllegalStateException("No SurfaceHolder provided");
        }
        if (cameraManager.isOpen()) {
            Logger.output("initCamera() while already open -- late SurfaceView callback?");
            return;
        }
        try {
            cameraManager.openDriver(surfaceHolder);
            // Creating the handler starts the preview, which can also throw a RuntimeException.
            if (handler == null) {
                handler = new CaptureActivityHandler(this, decodeFormats, decodeHints, characterSet, cameraManager);
            }
            decodeOrStoreSavedBitmap(null, null);
        } catch (IOException ioe) {
            Logger.output("Exception:" + ioe.getMessage());
            displayFrameworkBugMessageAndExit();
        } catch (RuntimeException e) {
            // Barcode Scanner has seen crashes in the wild of this variety:
            // java.?lang.?RuntimeException: Fail to connect to camera service
            Logger.output("Exception:" + e.getMessage());
            displayFrameworkBugMessageAndExit();
        }
    }

    private void displayFrameworkBugMessageAndExit() {
        AlertDialog.Builder builder = new AlertDialog.Builder(this);
        builder.setTitle(getString(R.string.app_name));
        builder.setMessage(getString(R.string.msg_camera_framework_bug));
        builder.setPositiveButton(R.string.STR_COMMON_03, new FinishListener(this));
        builder.setOnCancelListener(new FinishListener(this));
        builder.show();
    }

    private void decodeOrStoreSavedBitmap(Bitmap bitmap, Result result) {
        // Bitmap isn't used yet -- will be used soon
        if (handler == null) {
            savedResultToShow = result;
        } else {
            if (result != null) {
                savedResultToShow = result;
            }
            if (savedResultToShow != null) {
                Message message = Message.obtain(handler, R.id.decode_succeeded, savedResultToShow);
                handler.sendMessage(message);
            }
            savedResultToShow = null;
        }
    }


    /**
     * A valid barcode has been found, so give an indication of success and show the results.
     *
     * @param rawResult The contents of the barcode.
     * @param scaleFactor amount by which thumbnail was scaled
     * @param barcode   A greyscale bitmap of the camera data which was decoded.
     */
    public void handleDecode(Result rawResult, Bitmap barcode, float scaleFactor) {
        inactivityTimer.onActivity();


        boolean fromLiveScan = barcode != null;
        if (fromLiveScan) {
            viewfinderView.drawResultBitmap(barcode);
            txtResult.setText(rawResult.getBarcodeFormat().toString() + ":"
                    + rawResult.getText());
            // Then not from history, so beep/vibrate and we have an image to draw on
            beepManager.playBeepSoundAndVibrate();
        }
    }


}

4.7 新建布局文件qrcode_capture_page.xml布局如下

     <FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent">

    <SurfaceView
        android:id="@+id/preview_view"
        android:layout_width="fill_parent"
        android:layout_height="fill_parent"
        android:layout_centerInParent="true" />

    <com.denong.happilitt.com3rd.zxing.view.ViewfinderView
        android:id="@+id/viewfinder_view"
        android:layout_width="fill_parent"
        android:layout_height="fill_parent"
        android:background="@android:color/transparent" />

    <TextView
        android:id="@+id/txtResult"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="二维码扫描" />

</FrameLayout>


4.8 根据错误提示导入相关资源文件


step5 切换竖屏

5.1 将CameraConfigurationManager.java 中 setDesiredCameraParameters()加入

     //将摄像头旋转90
setDisplayOrientation(camera, 90);

并添加方法

       /**
   *
   * 改变相机成像方向
   *
   */
  protected void setDisplayOrientation(Camera camera, int angle) {

    Method downPolymorphic;

    try {

      downPolymorphic = camera.getClass().getMethod("setDisplayOrientation", new Class[] { int.class });

      if (downPolymorphic != null)

        downPolymorphic.invoke(camera, new Object[] { angle });

    } catch (Exception e1) {
      e1.printStackTrace();
    }

}



修改initFromCameraParameters()为如下:

     void initFromCameraParameters(Camera camera) {
    Camera.Parameters parameters = camera.getParameters();
    WindowManager manager = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
    Display display = manager.getDefaultDisplay();
    Point theScreenResolution = new Point();
    display.getSize(theScreenResolution);
    screenResolution = theScreenResolution;
    Log.i(TAG, "Screen resolution: " + screenResolution);
    //解决竖屏后图像拉伸问题
    Point screenResolutionForCamera = new Point();
    screenResolutionForCamera.x = screenResolution.x;
    screenResolutionForCamera.y = screenResolution.y;
    // preview size is always something like 480*320, other 320*480
    if (screenResolution.x < screenResolution.y) {
      screenResolutionForCamera.x = screenResolution.y;
      screenResolutionForCamera.y = screenResolution.x;
    }
    cameraResolution = CameraConfigurationUtils.findBestPreviewSizeValue(parameters, screenResolution);
    Log.i(TAG, "Camera resolution: " + cameraResolution);
  }

5.2 将CameraManager.java ->getFramingRectInPreview()

      //横屏模式
 rect.left = rect.left * cameraResolution.x / screenResolution.x;
 rect.right = rect.right * cameraResolution.x / screenResolution.x;
 rect.top = rect.top * cameraResolution.y / screenResolution.y;
 rect.bottom = rect.bottom * cameraResolution.y / screenResolution.y;
替换为
      //竖屏模式
 rect.left = rect.left * cameraResolution.x / screenResolution.x;
 rect.right = rect.right * cameraResolution.x / screenResolution.x;
 rect.top = rect.top * cameraResolution.y / screenResolution.y;
 rect.bottom = rect.bottom * cameraResolution.y / screenResolution.y;

最后别忘了将该文件中buildLuminanceSource()heightwidth顺序调换

     return new PlanarYUVLuminanceSource(data, width, height, rect.left, rect.top,
                                       rect.width(), rect.height(), false);
替换为

    

     //切换竖屏注意要将width和height顺序调换,不然会抛IllegalArgumentException
return new PlanarYUVLuminanceSource(data, height, width, rect.left, rect.top,
            rect.width(), rect.height(), false);

 















































评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值