java - 移动视觉条码扫描器 : Why does SurfaceView not update CameraSource?

标签 java android android-layout android-camera barcode-scanner

我一直在关注以下tutorial ,它使用移动视觉 api 创建条形码/二维码扫描仪。虽然我已经输入了它所说的确切代码(至少我认为),但来自 cameraSource 的摄像头馈送。

我在这个过程中添加了一些额外的代码,看看它是否会有所作为,但它仍然没有。问题是当我启动应用程序时,SurfaceView 应该显示 CAMERA_FACING_BACK 提要,但它是纯黑色的。如果您能告诉我为什么提要没有显示,如果有的话,代码需要更改,我们将不胜感激。

主要 Activity .java:

package com.example.neekondev.barcodeshortened;

import android.Manifest;
import android.content.pm.PackageManager;
import android.support.v4.app.ActivityCompat;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import android.util.SparseArray;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.widget.TextView;

import com.google.android.gms.vision.CameraSource;
import com.google.android.gms.vision.Detector;
import com.google.android.gms.vision.barcode.Barcode;
import com.google.android.gms.vision.barcode.BarcodeDetector;

import java.io.IOException;

import static com.google.android.gms.vision.CameraSource.CAMERA_FACING_BACK;
import static com.google.android.gms.vision.CameraSource.CAMERA_FACING_FRONT;

public class MainActivity extends AppCompatActivity {

    SurfaceView cameraView;
    TextView barcodeInfo;

    BarcodeDetector barcodeDetector;
    CameraSource cameraSource;


    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        cameraView = (SurfaceView) findViewById(R.id.camera_view);
        barcodeInfo = (TextView) findViewById(R.id.code_info);
        barcodeDetector =
                new BarcodeDetector.Builder(this)
                        .setBarcodeFormats(Barcode.CODE_39 | Barcode.CODE_93 | Barcode.CODE_128)
                        .build();

        cameraSource = new CameraSource
                .Builder(this, barcodeDetector)
                .setRequestedPreviewSize(640, 480)
                .setRequestedFps(20.0f)
                .setFacing(CAMERA_FACING_BACK)
                .build();
        cameraView.getHolder().addCallback(new SurfaceHolder.Callback() {
            @Override
            public void surfaceCreated(SurfaceHolder holder) {
                try {
                    if (ActivityCompat.checkSelfPermission(getApplicationContext(),
                            Manifest.permission.CAMERA) !=
                            PackageManager.PERMISSION_GRANTED) {
                        // TODO: Consider calling
                        //    ActivityCompat#requestPermissions
                        // here to request the missing permissions, and then overriding
                        //   public void onRequestPermissionsResult(int requestCode, String[] permissions,
                        //                                          int[] grantResults)
                        // to handle the case where the user grants the permission. See the documentation
                        // for ActivityCompat#requestPermissions for more details.
                        return;
                    }
                    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
                            );
                        }
                    });
                }
            }
        });
    }
}

activity_main.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_main"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:paddingBottom="@dimen/activity_vertical_margin"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    tools:context="com.example.neekondev.barcodeshortened.MainActivity">

    <SurfaceView
        android:layout_width="640px"
        android:layout_height="480px"
        android:layout_centerVertical="true"
        android:layout_alignParentLeft="true"
        android:id="@+id/camera_view"
        />

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:id="@+id/code_info"
        android:layout_toRightOf="@+id/camera_view"
        android:textSize="20sp"
        android:layout_marginLeft="16dp"
        android:text="Nothing yet..."
        android:layout_alignParentTop="true"
        />
</RelativeLayout>

list .xml:

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.neekondev.barcodeshortened">

    <meta-data android:name="com.google.android.gms.vision.DEPENDENCIES" android:value="barcode"/>

    <uses-permission android:name="android.permission.CAMERA" />
    <uses-permission android:name="android.permission.Camera"/>

    <application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:supportsRtl="true"
        android:theme="@style/AppTheme">
        <activity android:name=".MainActivity">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    </application>

</manifest>

最佳答案

没关系,这是我自己想出来的,虽然我认为其他人可能会在教程结束后问同样的问题,所以我会告诉你哪里出了问题。你看,虽然我在Manifest中声明了权限,但是android.permissions.CAMERA是一个“高风险权限”,也就是说需要用户手动同意才可能被执行。因为我从未制作过直接向用户请求的权限对话框,所以无法执行所有使用相机权限的代码,从而给了我们空白屏幕与相机的提要。一个简单的解决方法是进入设置并在那里允许权限,但也可以使用以下代码,通过对话框方便地请求相机权限;

import android.Manifest;
import android.content.Intent;
import android.content.pm.ActivityInfo;
import android.content.pm.PackageManager;
import android.hardware.Camera;
import android.media.Image;
import android.os.Bundle;
import android.support.v4.app.ActivityCompat;
import android.support.v4.content.ContextCompat;
import android.support.v7.app.AppCompatActivity;
import android.util.Log;
import android.util.SparseArray;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.view.View;
import android.widget.ImageButton;
import android.widget.ImageView;
import android.widget.RelativeLayout;
import android.widget.TextView;

import com.google.android.gms.vision.CameraSource;
import com.google.android.gms.vision.Detector;
import com.google.android.gms.vision.barcode.Barcode;
import com.google.android.gms.vision.barcode.BarcodeDetector;
import com.google.firebase.database.DatabaseReference;
import com.google.firebase.database.FirebaseDatabase;

import java.io.IOException;
import java.text.DateFormat;
import java.util.ArrayList;
import java.util.Date;

import static junit.framework.Assert.assertNotNull;

public class MainActivity
        extends AppCompatActivity {

    FirebaseDatabase database;
    DatabaseReference myRef;

    SurfaceView cameraView;
    TextView barcodeInfo;

    BarcodeDetector barcodeDetector;
    CameraSource cameraSource;

    private static final int CAMERA_PERMISSION_CAMERA = 0x000000;
    public static boolean position = false;
    //Camera cam;
    //Camera.Parameters p;

    @Override
    protected void onCreate(Bundle savedInstanceState) {

        setRequestedOrientation(ActivityInfo
                .SCREEN_ORIENTATION_PORTRAIT);
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        if (ContextCompat.checkSelfPermission(MainActivity
                .this,
                Manifest
                        .permission
                        .CAMERA)
                != PackageManager
                .PERMISSION_GRANTED) {

            // Should we show an explanation?
            if (ActivityCompat.shouldShowRequestPermissionRationale(MainActivity
                    .this,
                    Manifest
                            .permission
                            .CAMERA)) {

                // Show an explanation to the user *asynchronously* -- don't block
                // this thread waiting for the user's response! After the user
                // sees the explanation, try again to request the permission.

            } else {

                // No explanation needed, we can request the permission.

                ActivityCompat.requestPermissions(MainActivity
                        .this,
                        new String[]{Manifest.permission
                                .CAMERA},
                        CAMERA_PERMISSION_CAMERA);

                // CAMERA_PERMISSION_CAMERA is an
                // app-defined int constant. The callback method gets the
                // result of the request.
            }
        }

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

        MainActivity
                .this
                .getPackageManager()
                .hasSystemFeature
                        (PackageManager
                                .FEATURE_CAMERA_FLASH);

        barcodeDetector =
                new BarcodeDetector.Builder(getApplicationContext())
                        .setBarcodeFormats(Barcode.ALL_FORMATS)
                        .build();

        cameraSource = new CameraSource
                .Builder(getApplicationContext(), barcodeDetector)
                .setFacing(CameraSource.CAMERA_FACING_BACK)
                .setRequestedFps(35.0f)
                .setRequestedPreviewSize(960, 960)
                .setAutoFocusEnabled(true)
                .build();

        //setupButtons();


        cameraView.getHolder().addCallback(new SurfaceHolder
                .Callback() {
            @Override
            public void surfaceCreated(SurfaceHolder holder) {
                try {
                    if (ActivityCompat.checkSelfPermission(MainActivity.this,
                            Manifest.permission.CAMERA)
                            != PackageManager.PERMISSION_GRANTED) {
                        //      TODO: CONSIDER CALLING
                        //ActivityCompat#requestPermissions
                        // here to request the missing permissions, and then overriding
                        //   public void onRequestPermissionsResult(int requestCode, String[] permissions,
                        //                                          int[] grantResults)
                        // to handle the case where the user grants the permission. See the documentation
                        // for ActivityCompat#requestPermissions for more details.


                        return;
                    }
                    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();
                database = FirebaseDatabase.getInstance();
                myRef = database
                        .getReference(getTime());
                if (barcodes
                        .size() != 0) {
                    barcodeInfo
                            .post(new Runnable() {    // Use the post method of the TextView
                        public void run() {
                            barcodeInfo.setText(barcodes
                                    .valueAt(0)
                                    .displayValue
                            );
                            myRef.setValue(barcodes
                                    .valueAt(0)
                                    .displayValue
                            );
                        }
                    });
                }
            }
        });
    }
/*
    public void FLASH_ON()
    {
        cam = Camera.open();
        p = cam.getParameters();
        p.setFlashMode(Camera
                .Parameters
                .FLASH_MODE_TORCH);
        cam.setParameters(p);
        cam.startPreview();
    }

    public void FLASH_OFF()
    {cam.stopPreview();
        cam.release();}

    public void setupButtons()
    {
        ImageButton flash = (ImageButton)findViewById(R.id.flash);
        flash.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v)
            {
                if (position == false)
                {
                    FLASH_ON();
                    position = true;
                } if (position == true)
                {
                    FLASH_OFF();
                    position = false;
                }
            }
        });
    }*/

    public String getTime()
    {
        String downToSeconds = DateFormat
                .getDateTimeInstance()
                .format(
                        new Date());
        return downToSeconds;
    }

    @Override
    public void onRequestPermissionsResult(int requestCode,
                                           String permissions[],
                                           int[] grantResults) {
        switch (requestCode) {
            case CAMERA_PERMISSION_CAMERA: {
                // If request is cancelled, the result arrays are empty.
                if (grantResults.length > 0
                        && grantResults[0]
                        == PackageManager
                        .PERMISSION_GRANTED) {

                    Intent startMain = new Intent(MainActivity
                            .this, MainActivity
                            .class);
                    startActivity(startMain);

                } else {
                    if (ContextCompat.checkSelfPermission(MainActivity
                                    .this,
                            Manifest
                                    .permission
                                    .CAMERA)
                            != PackageManager
                            .PERMISSION_GRANTED) {

                        // Should we show an explanation?
                        if (ActivityCompat.shouldShowRequestPermissionRationale(MainActivity
                                        .this,
                                Manifest
                                        .permission
                                        .CAMERA)) {

                            // Show an explanation to the user *asynchronously* -- don't block
                            // this thread waiting for the user's response! After the user
                            // sees the explanation, try again to request the permission.

                        } else {

                            // No explanation needed, we can request the permission.

                            ActivityCompat.requestPermissions(MainActivity
                                            .this,
                                    new String[]{Manifest.permission
                                            .CAMERA},
                                    CAMERA_PERMISSION_CAMERA);

                            // CAMERA_PERMISSION_CAMERA is an
                            // app-defined int constant. The callback method gets the
                            // result of the request.
                        }
                    }
                }
                return;
            }
        }
    }
}

请原谅我的一些服务器代码。我也将结果上传到 firebase 数据库。其余的是相同的。布局有一些缩放比例的小调整,但其余部分是相同的。祝你好运!

关于java - 移动视觉条码扫描器 : Why does SurfaceView not update CameraSource?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41295955/

相关文章:

java - Spring Boot项目中在多个数据库中执行搜索操作

android - 样式化复合 View

android - 新的蓝牙 API 问题

android - 分层 ImageView

java - 在 Optional 中使用 assertJ 断言值

java - Spring 启动 : no String-argument constructor/factory method to deserialize from String value

android - 在 TableLayout 中使用 ScrollView & Horizo​​ntalScrollView

java - 使用回收器 View android studio访问其他 View

Java:如何创建实现抽象接口(interface)的泛型类的实例?

android - 架构组件刷新 LiveData