如何使用CameraX来构建我的自定义相机?

问题描述 投票:0回答:1

我想在不使用隐式意图的情况下创建相机屏幕。因此,我正在使用CameraX实现这一目标。

我从Github获得了一个代码。我正在尝试解决此问题

错误:不兼容的类型:无法将文件转换为Executor imgCap.takePicture(file,new ImageCapture.OnImageCapturedListener()

请帮助我简化此代码。

MainActivity.java

package com.example.camerax;

import android.annotation.SuppressLint;
import android.content.pm.PackageManager;
import android.graphics.Matrix;
import android.graphics.SurfaceTexture;
import android.os.Bundle;
import android.os.Environment;
import android.util.Rational;
import android.util.Size;
import android.view.Surface;
import android.view.TextureView;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Toast;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.appcompat.app.AppCompatActivity;
import androidx.camera.core.AspectRatio;
import androidx.camera.core.CameraX;
import androidx.camera.core.ImageAnalysis;
import androidx.camera.core.ImageAnalysisConfig;
import androidx.camera.core.ImageCapture;
import androidx.camera.core.ImageCaptureConfig;
import androidx.camera.core.ImageProxy;
import androidx.camera.core.Preview;
import androidx.camera.core.PreviewConfig;
import androidx.core.app.ActivityCompat;
import androidx.core.content.ContextCompat;
import androidx.lifecycle.LifecycleOwner;

import java.io.File;
import java.util.concurrent.Executor;


//saus: https://codelabs.developers.google.com/codelabs/camerax-getting-started/
public class MainActivity extends AppCompatActivity implements TextureView.SurfaceTextureListener{

private int REQUEST_CODE_PERMISSIONS = 10; //arbitrary number, can be changed accordingly
private final String[] REQUIRED_PERMISSIONS = new String[]{"android.permission.CAMERA","android.permission.WRITE_EXTERNAL_STORAGE"};


TextureView txView;

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

    txView = findViewById(R.id.view_finder);

    if(allPermissionsGranted()){
        startCamera(); //start camera if permission has been granted by user
    } else{
        ActivityCompat.requestPermissions(this, REQUIRED_PERMISSIONS, REQUEST_CODE_PERMISSIONS);
    }
}

private void startCamera() {
    //make sure there isn't another camera instance running before starting
    CameraX.unbindAll();

    /* start preview */
    int aspRatioW = txView.getWidth(); //get width of screen
    int aspRatioH = txView.getHeight(); //get height
    Rational rational = new Rational(aspRatioW,aspRatioH); //aspect ratio
    Size screen = new Size(aspRatioW, aspRatioH); //size of the screen

    //config obj for preview/viewfinder thingy.
    @SuppressLint("RestrictedApi") PreviewConfig pConfig = new PreviewConfig.Builder().setTargetAspectRatioCustom(rational).setTargetResolution(screen).build();
    Preview preview = new Preview(pConfig); //lets build it

    preview.setOnPreviewOutputUpdateListener(
            new Preview.OnPreviewOutputUpdateListener() {
                //to update the surface texture we have to destroy it first, then re-add it
                @Override
                public void onUpdated(Preview.PreviewOutput output){
                    ViewGroup parent = (ViewGroup) txView.getParent();
                    parent.removeView(txView);
                    parent.addView(txView, 0);

                    txView.setSurfaceTexture(output.getSurfaceTexture());
                    updateTransform();
                }
            });

    /* image capture */

    //config obj, selected capture mode
    ImageCaptureConfig imgCapConfig = new ImageCaptureConfig.Builder().setCaptureMode(ImageCapture.CaptureMode.MIN_LATENCY)
            .setTargetRotation(getWindowManager().getDefaultDisplay().getRotation()).build();
    final ImageCapture imgCap = new ImageCapture(imgCapConfig);

    findViewById(R.id.capture_button).setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            File file = new File(Environment.getExternalStorageDirectory() + "/" + System.currentTimeMillis() + ".jpg");

            imgCap.takePicture(file,new ImageCapture.OnImageCapturedListener() {

                @Override
                public void onCaptureSuccess(ImageProxy image, int rotationDegrees) {
                    super.onCaptureSuccess(image, rotationDegrees);
                    String msg = "Photo capture succeeded: " + file.getAbsolutePath();
                    Toast.makeText(getBaseContext(), msg,Toast.LENGTH_LONG).show();
                }

                @Override
                public void onError(@NonNull ImageCapture.ImageCaptureError imageCaptureError, @NonNull String message, @Nullable Throwable cause) {
                    super.onError(imageCaptureError, message, cause);
                    String msg = "Photo capture failed: " + message;
                    Toast.makeText(getBaseContext(), msg,Toast.LENGTH_LONG).show();
                    if(cause != null){
                        cause.printStackTrace();
                    }
                }
            });

        }
    });

    /* image analyser */

    ImageAnalysisConfig imgAConfig = new ImageAnalysisConfig.Builder().setImageReaderMode(ImageAnalysis.ImageReaderMode.ACQUIRE_LATEST_IMAGE).build();
    ImageAnalysis analysis = new ImageAnalysis(imgAConfig);


    //bind to lifecycle:
    CameraX.bindToLifecycle((LifecycleOwner)this, analysis, imgCap, preview);
}

private void updateTransform(){
    /*
    * compensates the changes in orientation for the viewfinder, bc the rest of the layout stays in portrait mode.
    * methinks :thonk:
    * imgCap does this already, this class can be commented out or be used to optimise the preview
    */
    Matrix mx = new Matrix();
    float w = txView.getMeasuredWidth();
    float h = txView.getMeasuredHeight();

    float centreX = w / 2f; //calc centre of the viewfinder
    float centreY = h / 2f;

    int rotationDgr;
    int rotation = (int)txView.getRotation(); //cast to int bc switches don't like floats

    switch(rotation){ //correct output to account for display rotation
        case Surface.ROTATION_0:
            rotationDgr = 0;
            break;
        case Surface.ROTATION_90:
            rotationDgr = 90;
            break;
        case Surface.ROTATION_180:
            rotationDgr = 180;
            break;
        case Surface.ROTATION_270:
            rotationDgr = 270;
            break;
        default:
            return;
    }

    mx.postRotate((float)rotationDgr, centreX, centreY);
    txView.setTransform(mx); //apply transformations to textureview
}

@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
    //start camera when permissions have been granted otherwise exit app
    if(requestCode == REQUEST_CODE_PERMISSIONS){
        if(allPermissionsGranted()){
            startCamera();
        } else{
            Toast.makeText(this, "Permissions not granted by the user.", Toast.LENGTH_SHORT).show();
            finish();
        }
    }
}

private boolean allPermissionsGranted(){
    //check if req permissions have been granted
    for(String permission : REQUIRED_PERMISSIONS){
        if(ContextCompat.checkSelfPermission(this, permission) != PackageManager.PERMISSION_GRANTED){
            return false;
        }
    }
    return true;
}

@Override
public void onSurfaceTextureAvailable(SurfaceTexture surface, int width, int height) {

}

@Override
public void onSurfaceTextureSizeChanged(SurfaceTexture surface, int width, int height) {

}

@Override
public boolean onSurfaceTextureDestroyed(SurfaceTexture surface) {
    return false;
}

@Override
public void onSurfaceTextureUpdated(SurfaceTexture surface) {

}
//array w/ permissions from manifest

}

* build.gradle **

apply plugin: 'com.android.application'

android {
    compileSdkVersion 28
    defaultConfig {
        applicationId "com.example.camerax"
        minSdkVersion 22
        targetSdkVersion 28
        versionCode 1
        versionName "1.0"
        testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
    }
    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
        }
    }
    compileOptions {
        sourceCompatibility JavaVersion.VERSION_1_8
        targetCompatibility JavaVersion.VERSION_1_8
    }
}

dependencies {
    implementation fileTree(dir: 'libs', include: ['*.jar'])
    implementation 'androidx.appcompat:appcompat:1.2.0-beta01'
    implementation 'androidx.constraintlayout:constraintlayout:1.1.3'
    def camerax_version = '1.0.0-alpha06'
    //noinspection GradleDependency
    implementation "androidx.camera:camera-core:${camerax_version}"
    //noinspection GradleDependency
    implementation "androidx.camera:camera-camera2:${camerax_version}"
    testImplementation 'junit:junit:4.12'
    androidTestImplementation 'androidx.test:runner:1.2.0'
    androidTestImplementation 'androidx.test.espresso:espresso-core:3.2.0'
}
java android android-camera android-camerax
1个回答
1
投票

尝试一下在Activity]中定义执行器

private val executor = Executors.newSingleThreadExecutor()

takePicture方法内传递执行程序。

findViewById(R.id.capture_button).setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            File file = new File(Environment.getExternalStorageDirectory() + "/" + System.currentTimeMillis() + ".jpg");

            imgCap.takePicture(file, executor, new ImageCapture.OnImageCapturedListener() {

                @Override
                public void onCaptureSuccess(ImageProxy image, int rotationDegrees) {
                    super.onCaptureSuccess(image, rotationDegrees);
                    String msg = "Photo capture succeeded: " + file.getAbsolutePath();
                    Toast.makeText(getBaseContext(), msg,Toast.LENGTH_LONG).show();
                }

                @Override
                public void onError(@NonNull ImageCapture.ImageCaptureError imageCaptureError, @NonNull String message, @Nullable Throwable cause) {
                    super.onError(imageCaptureError, message, cause);
                    String msg = "Photo capture failed: " + message;
                    Toast.makeText(getBaseContext(), msg,Toast.LENGTH_LONG).show();
                    if(cause != null){
                        cause.printStackTrace();
                    }
                }
            });

        }
    });
    
© www.soinside.com 2019 - 2024. All rights reserved.