Java 使用摄像头扫描二维码导致应用程序崩溃|可能修复?

Java 使用摄像头扫描二维码导致应用程序崩溃|可能修复?,java,android,camera,Java,Android,Camera,我正在尝试使用设备摄像头和移动视觉API扫描二维码。为此,我创建了一个SurfaceView,将图像流提取到SurfaceView,并启用了条码检测器,然后使用所需的方法读取检测到的二维码。以下是活动的代码: QrScanActivity.class public class QrScanActivity extends AppCompatActivity { private SurfaceView cameraView; private TextView barcodeInfo

我正在尝试使用设备摄像头和移动视觉API扫描二维码。为此,我创建了一个
SurfaceView
,将图像流提取到
SurfaceView
,并启用了
条码检测器
,然后使用所需的方法读取检测到的二维码。以下是活动的代码:

QrScanActivity.class

public class QrScanActivity extends AppCompatActivity
{
    private SurfaceView cameraView;
    private TextView barcodeInfo;
    private BarcodeDetector barcodeDetector;
    private CameraSource cameraSource;
    private static final String TAG = "QR_ACTIVITY";
    private static final int REQUEST_CAMERA = 0;


    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_qr_scan);

        cameraView = (SurfaceView) findViewById(R.id.camera_view);
        barcodeInfo = (TextView) findViewById(R.id.code_info);

        barcodeDetector =
                new BarcodeDetector.Builder(this)
                        .setBarcodeFormats(Barcode.QR_CODE)
                        .build();

        cameraSource = new CameraSource
                .Builder(this, barcodeDetector)
                .setRequestedPreviewSize(640, 480)
                .build();

        cameraView.getHolder().addCallback(new SurfaceHolder.Callback() {
            @Override
            public void surfaceCreated(SurfaceHolder holder) {
                if (ActivityCompat.checkSelfPermission(QrScanActivity.this, Manifest.permission.CAMERA)
                        != PackageManager.PERMISSION_GRANTED) {
                    requestCameraPermission();

                }
                try {
                    cameraSource.start(cameraView.getHolder());
                } catch (IOException ie) {
                    Log.e("CAMERA SOURCE", ie.getMessage());
                }
            }

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

            @Override
            public void surfaceDestroyed(SurfaceHolder holder) {
                cameraSource.stop();
            }
        });

        barcodeDetector.setProcessor(new Detector.Processor<Barcode>() {
            @Override
            public void release() {
            }

            @Override
            public void receiveDetections(Detector.Detections<Barcode> detections) {
                final SparseArray<Barcode> barcodes = detections.getDetectedItems();

                if (barcodes.size() != 0) {
                    barcodeInfo.post(new Runnable() {    // Use the post method of the TextView
                        public void run() {
                            barcodeInfo.setText(    // Update the TextView
                                    barcodes.valueAt(0).displayValue
                            );
                        }
                    });
                }
            }
        });
    }

        private void requestCameraPermission() {
        Log.i("CAM","CAMERA permission has NOT been granted. Requesting permission.");

        // BEGIN_INCLUDE(camera_permission_request)
        if (ActivityCompat.shouldShowRequestPermissionRationale(this,Manifest.permission.CAMERA))
        {

            Snackbar.make(findViewById(android.R.id.content), R.string.permission_camera_rationale,
                    Snackbar.LENGTH_INDEFINITE)
                    .setAction(R.string.ok, new View.OnClickListener() {
                        @Override
                        public void onClick(View view) {
                            ActivityCompat.requestPermissions(QrScanActivity.this,
                                    new String[]{Manifest.permission.CAMERA},
                                    REQUEST_CAMERA);
                        }
                    })
                    .show();
        } else {


            ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.CAMERA},
                    REQUEST_CAMERA);
        }
        // END_INCLUDE(camera_permission_request)
    }


    @Override
    public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions,
                                           @NonNull int[] grantResults) {

        if (requestCode == REQUEST_CAMERA)
        {

            Log.i(TAG, "Received response for Camera permission request.");
           if (grantResults.length == 1 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
                  Log.i(TAG, "CAMERA permission has now been granted. Showing preview.");
                Snackbar.make(findViewById(android.R.id.content), R.string.permision_available_camera,
                        Snackbar.LENGTH_SHORT).show();
            } else {
                Log.i(TAG, "CAMERA permission was NOT granted.");
                Snackbar.make(findViewById(android.R.id.content), R.string.permissions_not_granted,
                        Snackbar.LENGTH_SHORT).show();

            }


        }
        else {
            super.onRequestPermissionsResult(requestCode, permissions, grantResults);
        }
    }




}
公共类QrScanActivity扩展了AppCompatActivity
{
私人水面观景摄像师;
私有文本视图条码信息;
专用条码检测器条码检测器;
私人摄像源摄像源;
私有静态最终字符串TAG=“QR\U活动”;
专用静态最终int请求\u摄像机=0;
@凌驾
创建时受保护的void(Bundle savedInstanceState){
super.onCreate(savedInstanceState);
setContentView(R.layout.activity\u qr\u scan);
cameraView=(SurfaceView)findViewById(R.id.camera\U视图);
barcodeInfo=(TextView)findViewById(R.id.code\u信息);
条形码检测器=
新条形码检测器.Builder(此)
.setBarcodeFormats(条形码.QR\U码)
.build();
cameraSource=新的cameraSource
.Builder(这是条形码检测器)
.setRequestedPreviewSize(640480)
.build();
cameraView.getHolder().addCallback(新的SurfaceHolder.Callback()){
@凌驾
已创建的公共空白表面(表面持有人){
if(ActivityCompat.checkSelfPermission(QrScanActivity.this、Manifest.permission.CAMERA)
!=PackageManager.权限(已授予){
requestCameraPermission();
}
试一试{
cameraSource.start(cameraView.getHolder());
}捕获(IOIE){
Log.e(“摄像机源”,即getMessage());
}
}
@凌驾
公共空白表面更改(表面文件夹持有者、整型格式、整型宽度、整型高度){
}
@凌驾
公共空间表面覆盖(表面覆盖物持有人){
cameraSource.stop();
}
});
条形码检测器.setProcessor(新检测器.Processor(){
@凌驾
公开无效释放(){
}
@凌驾
公共空隙接收检测(检测器。检测){
最终SparseArray条形码=检测。getDetectedItems();
如果(条形码大小()!=0){
post(new Runnable(){//使用TextView的post方法
公开募捐{
barcodeInfo.setText(//更新TextView
条形码.valueAt(0).显示值
);
}
});
}
}
});
}
私有void requestCameraPermission(){
Log.i(“CAM”,“尚未授予摄像头权限。正在请求权限”);
//开始包括(摄像机许可请求)
if(ActivityCompat.shouldshowRequestPermissionRegulation(这是Manifest.permission.CAMERA))
{
Snackbar.make(findviewbyd(android.R.id.content)、R.string.permission\u camera\u原理、,
蛇形杆。长度(不确定)
.setAction(R.string.ok,new View.OnClickListener(){
@凌驾
公共void onClick(视图){
ActivityCompat.requestPermissions(QrScanActivity.this,
新字符串[]{Manifest.permission.CAMERA},
请求(摄像头);
}
})
.show();
}否则{
ActivityCompat.requestPermissions(这个新字符串[]{Manifest.permission.CAMERA},
请求(摄像头);
}
//结束包括(摄像机许可请求)
}
@凌驾
public void onRequestPermissionsResult(int-requestCode,@NonNull字符串[]权限,
@非空int[]grantResults){
if(requestCode==请求\摄像机)
{
Log.i(标记“已收到照相机许可请求的响应”);
if(grantResults.length==1&&grantResults[0]==PackageManager.PERMISSION\u已授予){
Log.i(标记“相机权限已授予。显示预览”);
Snackbar.make(findviewbyd(android.R.id.content)、R.string.permission\u available\u camera、,
Snackbar.LENGTH_SHORT).show();
}否则{
Log.i(标记“未授予相机许可”);
Snackbar.make(findviewbyd(android.R.id.content)、R.string.permissions\u not\u provided、,
Snackbar.LENGTH_SHORT).show();
}
}
否则{
super.onRequestPermissionsResult(请求代码、权限、授权结果);
}
}
}
活动\u qr\u scan.xml

    <?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/activity_qr_scan"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <SurfaceView
        android:layout_width="400dp"
        android:layout_height="280dp"
        android:layout_marginTop="30dp"
        android:id="@+id/camera_view"
        />

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:id="@+id/code_info"
        android:layout_below="@+id/camera_view"
        android:textSize="20sp"
        android:layout_marginTop="30dp"
        android:layout_centerHorizontal="true"
        android:text="Nothing to read."

        />


</RelativeLayout>

运行应用程序时获得的logcat:

Logcat

E/AndroidRuntime:致命异常:主 进程:com.shreybank.shrey,PID:12044 java.lang.RuntimeException:无法连接到摄影机服务 在android.hardware.Camera。(Camera.java:518) 打开(Camera.java:360) 位于com.google.android.gms.vision.CameraSource.zzBZ(未知来源) 位于com.google.android.gms.vision.CameraSource.start(未知源) 在com.shreybank.shrey.activities.QrScanActivity$1.surfaceCreated(QrScanActivity.jav
if (android.os.Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
    if (ContextCompat.checkSelfPermission(MainActivity.this, Manifest.permission.CAMERA) != PackageManager.PERMISSION_GRANTED) {
        ActivityCompat.requestPermissions(MainActivity.this, new String[]{Manifest.permission.CAMERA}, REQUEST_READ_CAMERA);
    }
    else {
        // Already grant Camera permission. Now call your QR scan Activity
    }
}else {
    // call your QR scan Activity
}
@Override
public void onRequestPermissionsResult(int requestCode,
                                       String permissions[], int[] grantResults) {
    switch (requestCode) {
        case REQUEST_READ_CAMERA: {
            if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
                // permission has granted . Call the QR scan Activity
            } else {
                // permission denied
            }
            return;
        }
    }
}
public class QrScanActivity extends AppCompatActivity
{
    private SurfaceView cameraView;
    private TextView barcodeInfo;
    private BarcodeDetector barcodeDetector;
    private CameraSource cameraSource;
    private static final String TAG = "QR_ACTIVITY";
    private static final int REQUEST_CAMERA = 0;


    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_qr_scan);
        int permissionCheck = ContextCompat.checkSelfPermission(this,
                Manifest.permission.CAMERA);
        if(permissionCheck ==  PackageManager.PERMISSION_GRANTED)
            initCameraSource
        else
            requestCameraPermission();

    }

        private void requestCameraPermission() {
        Log.i("CAM","CAMERA permission has NOT been granted. Requesting permission.");

        // BEGIN_INCLUDE(camera_permission_request)
        if (ActivityCompat.shouldShowRequestPermissionRationale(this,Manifest.permission.CAMERA))
        {

            Snackbar.make(findViewById(android.R.id.content), R.string.permission_camera_rationale,
                    Snackbar.LENGTH_INDEFINITE)
                    .setAction(R.string.ok, new View.OnClickListener() {
                        @Override
                        public void onClick(View view) {
                            ActivityCompat.requestPermissions(QrScanActivity.this,
                                    new String[]{Manifest.permission.CAMERA},
                                    REQUEST_CAMERA);
                        }
                    })
                    .show();
        } else {


            ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.CAMERA},
                    REQUEST_CAMERA);
        }
        // END_INCLUDE(camera_permission_request)
    }


    @Override
    public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions,
                                           @NonNull int[] grantResults) {

        if (requestCode == REQUEST_CAMERA)
        {

            Log.i(TAG, "Received response for Camera permission request.");
           if (grantResults.length == 1 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
                  Log.i(TAG, "CAMERA permission has now been granted. Showing preview.");
                  initCameraSource();
            } else {
                Log.i(TAG, "CAMERA permission was NOT granted.");
                Snackbar.make(findViewById(android.R.id.content), R.string.permissions_not_granted,
                        Snackbar.LENGTH_SHORT).show();

            }


        }
        else {
            super.onRequestPermissionsResult(requestCode, permissions, grantResults);
        }
    }


    private void initCameraSource(){
         cameraView = (SurfaceView) findViewById(R.id.camera_view);
         barcodeInfo = (TextView) findViewById(R.id.code_info);

         barcodeDetector =
                 new BarcodeDetector.Builder(this)
                         .setBarcodeFormats(Barcode.QR_CODE)
                         .build();

         cameraSource = new CameraSource
                 .Builder(this, barcodeDetector)
                 .setRequestedPreviewSize(640, 480)
                 .build();

         cameraView.getHolder().addCallback(new SurfaceHolder.Callback() {
             @Override
             public void surfaceCreated(SurfaceHolder holder) {
                 if (ActivityCompat.checkSelfPermission(QrScanActivity.this, Manifest.permission.CAMERA)
                         != PackageManager.PERMISSION_GRANTED) {
                     requestCameraPermission();

                 }
                 try {
                     cameraSource.start(cameraView.getHolder());
                 } catch (IOException ie) {
                     Log.e("CAMERA SOURCE", ie.getMessage());
                 }
             }

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

             @Override
             public void surfaceDestroyed(SurfaceHolder holder) {
                 cameraSource.stop();
             }
         });

         barcodeDetector.setProcessor(new Detector.Processor<Barcode>() {
             @Override
             public void release() {
             }

             @Override
             public void receiveDetections(Detector.Detections<Barcode> detections) {
                 final SparseArray<Barcode> barcodes = detections.getDetectedItems();

                 if (barcodes.size() != 0) {
                     barcodeInfo.post(new Runnable() {    // Use the post method of the TextView
                         public void run() {
                             barcodeInfo.setText(    // Update the TextView
                                     barcodes.valueAt(0).displayValue
                             );
                         }
                     });
                 }
             }
         });
    }


}