【问题标题】:Mobile Vision barcodeScanner: Why does SurfaceView not update CameraSource?Mobile VisionbarcodeScanner:SurfaceView为什么不更新CameraSource?
【发布时间】:2017-05-08 20:02:58
【问题描述】:

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

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

MainActivity.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>

manifest.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>

【问题讨论】:

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


    【解决方案1】:

    没关系,我自己解决了这个问题,虽然我认为其他人在教程结束后可能会问同样的问题,所以我会告诉你哪里出了问题。您看,虽然我在 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 数据库。其余的都是相同的。布局对缩放有一些小的调整,但其余部分是相同的。祝你好运!

    【讨论】:

    • 当用户允许权限时,您是否重新启动全部活动?
    • @androidnoobdev 是的,activity重启了。
    • 需要重启activity才能触发surfaceCreated(SurfaceHolder holder)。
    猜你喜欢
    • 2016-03-11
    • 1970-01-01
    • 1970-01-01
    • 2019-05-13
    • 2017-10-10
    • 2019-08-10
    • 2019-07-16
    • 1970-01-01
    • 2021-02-17
    相关资源
    最近更新 更多