【问题标题】:Unexpected logcat errors when running android camerax without an ImageCapture use case在没有 ImageCapture 用例的情况下运行 android camerax 时出现意外的 logcat 错误
【发布时间】:2020-08-03 16:40:56
【问题描述】:

完成了codelabs 教程,一切正常,但在删除 ImageCapture 用例后,我每隔 50 毫秒左右就会在 logcat 中再次出现错误。

这里是三行所说的错误:

07-28 18:22:16.225 211-29468/? E/mm-camera: module_faceproc_port_event_func:886] MCT_EVENT_MODULE_BUF_DIVERT 65539, Cannot start FD, active 10002, frameid 432 431, native 1, mapped 1 1
07-28 18:22:16.258 211-29468/? E/mm-camera: module_faceproc_port_event_func:886] MCT_EVENT_MODULE_BUF_DIVERT 65539, Cannot start FD, active 10002, frameid 433 432, native 1, mapped 1 1
07-28 18:22:16.291 211-29468/? E/mm-camera: module_faceproc_port_event_func:886] MCT_EVENT_MODULE_BUF_DIVERT 65539, Cannot start FD, active 10002, frameid 434 433, native 1, mapped 1 1

我在尝试通过 docs 实现 ImageAnalysis 用例时也遇到了同样的错误,其中我也没有包含 ImageCapture 用例。是否还有一些内在要求来创建我在文档中缺少的 ImageCapture 用例?

mm-camera 标记的错误日志来自哪里?我很难在代码、文档或 Google 中找到任何东西来告诉我这个毫米相机是什么。

以下两种情况的代码。我添加////////////////////////////////////////////////////////////////////////////////////////////////

工作 CodeLabs 最终代码:

package jp.oist.cameraxapp

import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.Manifest
import android.content.pm.PackageManager
import android.net.Uri
import android.util.Log
import android.widget.Button
import android.widget.Toast
import androidx.core.app.ActivityCompat
import androidx.core.content.ContextCompat
import java.util.concurrent.Executors
import androidx.camera.core.*
import androidx.camera.lifecycle.ProcessCameraProvider
import androidx.camera.view.PreviewView
import kotlinx.android.synthetic.main.activity_main.*
import java.io.File
import java.nio.ByteBuffer
import java.text.SimpleDateFormat
import java.util.*
import java.util.concurrent.ExecutorService
typealias LumaListener = (luma: Double) -> Unit

class MainActivity : AppCompatActivity() {
    private var preview: Preview? = null
    private var imageCapture: ImageCapture? = null
    private var imageAnalyzer: ImageAnalysis? = null
    private var camera: Camera? = null

    private lateinit var outputDirectory: File
    private lateinit var cameraExecutor: ExecutorService

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        // Request camera permissions
        if (allPermissionsGranted()) {
            startCamera()
        } else {
            ActivityCompat.requestPermissions(
                    this, REQUIRED_PERMISSIONS, REQUEST_CODE_PERMISSIONS)
        }

        // Setup the listener for take photo button
        camera_capture_button.setOnClickListener { takePhoto() }

        outputDirectory = getOutputDirectory()

        cameraExecutor = Executors.newSingleThreadExecutor()
    }

    private fun startCamera() {
        val cameraProviderFuture = ProcessCameraProvider.getInstance(this)

        cameraProviderFuture.addListener(Runnable {
            // Used to bind the lifecycle of cameras to the lifecycle owner
            val cameraProvider: ProcessCameraProvider = cameraProviderFuture.get()

            // Preview
            preview = Preview.Builder()
                    .build()

            imageCapture = ImageCapture.Builder()
                    .build()

            imageAnalyzer = ImageAnalysis.Builder()
                    .build()
                    .also {
                        it.setAnalyzer(cameraExecutor, LuminosityAnalyzer { luma ->
                            Log.d(TAG, "Average luminosity: $luma")
                        })
                    }

            // Select back camera
            val cameraSelector = CameraSelector.Builder().requireLensFacing(CameraSelector.LENS_FACING_BACK).build()

            try {
                // Unbind use cases before rebinding
                cameraProvider.unbindAll()

                // Bind use cases to camera
                camera = cameraProvider.bindToLifecycle(
                        this, cameraSelector, preview, imageCapture, imageAnalyzer)
                preview?.setSurfaceProvider(viewFinder.createSurfaceProvider(camera?.cameraInfo))
            } catch(exc: Exception) {
                Log.e(TAG, "Use case binding failed", exc)
            }

        }, ContextCompat.getMainExecutor(this))
    }

    private fun takePhoto() {
        // Get a stable reference of the modifiable image capture use case
        val imageCapture = imageCapture ?: return

        // Create timestamped output file to hold the image
        val photoFile = File(
                outputDirectory,
                SimpleDateFormat(FILENAME_FORMAT, Locale.US
                ).format(System.currentTimeMillis()) + ".jpg")

        // Create output options object which contains file + metadata
        val outputOptions = ImageCapture.OutputFileOptions.Builder(photoFile).build()

        // Setup image capture listener which is triggered after photo has
        // been taken
        imageCapture.takePicture(
                outputOptions, ContextCompat.getMainExecutor(this), object : ImageCapture.OnImageSavedCallback {
            override fun onError(exc: ImageCaptureException) {
                Log.e(TAG, "Photo capture failed: ${exc.message}", exc)
            }

            override fun onImageSaved(output: ImageCapture.OutputFileResults) {
                val savedUri = Uri.fromFile(photoFile)
                val msg = "Photo capture succeeded: $savedUri"
                Toast.makeText(baseContext, msg, Toast.LENGTH_SHORT).show()
                Log.d(TAG, msg)
            }
        })
    }
    private fun allPermissionsGranted() = REQUIRED_PERMISSIONS.all {
        ContextCompat.checkSelfPermission(
                baseContext, it) == PackageManager.PERMISSION_GRANTED
    }

    fun getOutputDirectory(): File {
        val mediaDir = externalMediaDirs.firstOrNull()?.let {
            File(it, resources.getString(R.string.app_name)).apply { mkdirs() } }
        return if (mediaDir != null && mediaDir.exists())
            mediaDir else filesDir
    }

    companion object {
        private const val TAG = "CameraXBasic"
        private const val FILENAME_FORMAT = "yyyy-MM-dd-HH-mm-ss-SSS"
        private const val REQUEST_CODE_PERMISSIONS = 10
        private val REQUIRED_PERMISSIONS = arrayOf(Manifest.permission.CAMERA)
    }

    override fun onRequestPermissionsResult(
            requestCode: Int, permissions: Array<String>, grantResults:
            IntArray) {
        if (requestCode == REQUEST_CODE_PERMISSIONS) {
            if (allPermissionsGranted()) {
                startCamera()
            } else {
                Toast.makeText(this,
                        "Permissions not granted by the user.",
                        Toast.LENGTH_SHORT).show()
                finish()
            }
        }
    }

    private class LuminosityAnalyzer(private val listener: LumaListener) : ImageAnalysis.Analyzer {

        private fun ByteBuffer.toByteArray(): ByteArray {
            rewind()    // Rewind the buffer to zero
            val data = ByteArray(remaining())
            get(data)   // Copy the buffer into a byte array
            return data // Return the byte array
        }

        override fun analyze(image: ImageProxy) {

            val buffer = image.planes[0].buffer
            val data = buffer.toByteArray()
            val pixels = data.map { it.toInt() and 0xFF }
            val luma = pixels.average()

            listener(luma)

            image.close()
        }
    }
}

编辑代码以删除 ImageCapture 用例:

package jp.oist.cameraxapp

import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.Manifest
import android.content.pm.PackageManager
import android.net.Uri
import android.util.Log
import android.widget.Button
import android.widget.Toast
import androidx.core.app.ActivityCompat
import androidx.core.content.ContextCompat
import java.util.concurrent.Executors
import androidx.camera.core.*
import androidx.camera.lifecycle.ProcessCameraProvider
import androidx.camera.view.PreviewView
import kotlinx.android.synthetic.main.activity_main.*
import java.io.File
import java.nio.ByteBuffer
import java.text.SimpleDateFormat
import java.util.*
import java.util.concurrent.ExecutorService
typealias LumaListener = (luma: Double) -> Unit

class MainActivity : AppCompatActivity() {
    private var preview: Preview? = null
    private var imageCapture: ImageCapture? = null
    private var imageAnalyzer: ImageAnalysis? = null
    private var camera: Camera? = null

    private lateinit var outputDirectory: File
    private lateinit var cameraExecutor: ExecutorService

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        // Request camera permissions
        if (allPermissionsGranted()) {
            startCamera()
        } else {
            ActivityCompat.requestPermissions(
                    this, REQUIRED_PERMISSIONS, REQUEST_CODE_PERMISSIONS)
        }

        // Setup the listener for take photo button
        camera_capture_button.setOnClickListener { takePhoto() }

        outputDirectory = getOutputDirectory()

        cameraExecutor = Executors.newSingleThreadExecutor()
    }

    private fun startCamera() {
        val cameraProviderFuture = ProcessCameraProvider.getInstance(this)

        cameraProviderFuture.addListener(Runnable {
            // Used to bind the lifecycle of cameras to the lifecycle owner
            val cameraProvider: ProcessCameraProvider = cameraProviderFuture.get()

            // Preview
            preview = Preview.Builder()
                    .build()

            ////////////////////////////////////////// Removed imageCapture object

            imageAnalyzer = ImageAnalysis.Builder()
                    .build()
                    .also {
                        it.setAnalyzer(cameraExecutor, LuminosityAnalyzer { luma ->
                            Log.d(TAG, "Average luminosity: $luma")
                        })
                    }

            // Select back camera
            val cameraSelector = CameraSelector.Builder().requireLensFacing(CameraSelector.LENS_FACING_BACK).build()

            try {
                // Unbind use cases before rebinding
                cameraProvider.unbindAll()

                // Bind use cases to camera
                ////////////////////////////////////////// Removed imageCapture from bindToLifecycle
                camera = cameraProvider.bindToLifecycle(
                        this, cameraSelector, preview, imageAnalyzer)
                preview?.setSurfaceProvider(viewFinder.createSurfaceProvider(camera?.cameraInfo))
            } catch(exc: Exception) {
                Log.e(TAG, "Use case binding failed", exc)
            }

        }, ContextCompat.getMainExecutor(this))
    }

    private fun takePhoto() {
        // Get a stable reference of the modifiable image capture use case
        val imageCapture = imageCapture ?: return

        // Create timestamped output file to hold the image
        val photoFile = File(
                outputDirectory,
                SimpleDateFormat(FILENAME_FORMAT, Locale.US
                ).format(System.currentTimeMillis()) + ".jpg")

        // Create output options object which contains file + metadata
        val outputOptions = ImageCapture.OutputFileOptions.Builder(photoFile).build()

        // Setup image capture listener which is triggered after photo has
        // been taken
        imageCapture.takePicture(
                outputOptions, ContextCompat.getMainExecutor(this), object : ImageCapture.OnImageSavedCallback {
            override fun onError(exc: ImageCaptureException) {
                Log.e(TAG, "Photo capture failed: ${exc.message}", exc)
            }

            override fun onImageSaved(output: ImageCapture.OutputFileResults) {
                val savedUri = Uri.fromFile(photoFile)
                val msg = "Photo capture succeeded: $savedUri"
                Toast.makeText(baseContext, msg, Toast.LENGTH_SHORT).show()
                Log.d(TAG, msg)
            }
        })
    }
    private fun allPermissionsGranted() = REQUIRED_PERMISSIONS.all {
        ContextCompat.checkSelfPermission(
                baseContext, it) == PackageManager.PERMISSION_GRANTED
    }

    fun getOutputDirectory(): File {
        val mediaDir = externalMediaDirs.firstOrNull()?.let {
            File(it, resources.getString(R.string.app_name)).apply { mkdirs() } }
        return if (mediaDir != null && mediaDir.exists())
            mediaDir else filesDir
    }

    companion object {
        private const val TAG = "CameraXBasic"
        private const val FILENAME_FORMAT = "yyyy-MM-dd-HH-mm-ss-SSS"
        private const val REQUEST_CODE_PERMISSIONS = 10
        private val REQUIRED_PERMISSIONS = arrayOf(Manifest.permission.CAMERA)
    }

    override fun onRequestPermissionsResult(
            requestCode: Int, permissions: Array<String>, grantResults:
            IntArray) {
        if (requestCode == REQUEST_CODE_PERMISSIONS) {
            if (allPermissionsGranted()) {
                startCamera()
            } else {
                Toast.makeText(this,
                        "Permissions not granted by the user.",
                        Toast.LENGTH_SHORT).show()
                finish()
            }
        }
    }

    private class LuminosityAnalyzer(private val listener: LumaListener) : ImageAnalysis.Analyzer {

        private fun ByteBuffer.toByteArray(): ByteArray {
            rewind()    // Rewind the buffer to zero
            val data = ByteArray(remaining())
            get(data)   // Copy the buffer into a byte array
            return data // Return the byte array
        }

        override fun analyze(image: ImageProxy) {

            val buffer = image.planes[0].buffer
            val data = buffer.toByteArray()
            val pixels = data.map { it.toInt() and 0xFF }
            val luma = pixels.average()

            listener(luma)

            image.close()
        }
    }
}

版本和电话详细信息:

Nexus 5,Android 6.0.1

Android Studio 4.0 构建 #AI-193.6911.18.40.6514223,构建于 2020 年 5 月 21 日 运行时版本:1.8.0_242-release-1644-b3-6222593 amd64 虚拟机:JetBrains s.r.o 的 OpenJDK 64 位服务器虚拟机 Linux 5.3.0-46-通用 GC:ParNew、ConcurrentMarkSweep 内存:1981M 核心:8 注册表:ide.new.welcome.screen.force=true 非捆绑插件:PlantUML 集成、SequenceDiagram、org.jetbrains.kotlin、com.google.services.firebase、com.intellij.marketplace、com.thoughtworks.gauge、org.intellij.plugins.markdown、org.pmesmeur.sketchit、 ru.leoklo.stackuml, simpleUML

Edit1(添加表现出相同行为的 Java 示例代码):

我想添加另一个导致相同 logcat 错误的示例。按照示例代码 sn-ps 并填补 docs 的空白,在完成文档的 Preview 部分后,可以得到以下代码,并带有一个有效的预览用例:

package jp.oist.cameraxapp;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.appcompat.app.AppCompatActivity;
import androidx.camera.core.Camera;
import androidx.camera.core.CameraSelector;
import androidx.camera.core.ImageAnalysis;
import androidx.camera.core.ImageCapture;
import androidx.camera.core.ImageProxy;
import androidx.camera.core.Preview;
import androidx.camera.lifecycle.ProcessCameraProvider;
import androidx.camera.view.PreviewView;
import androidx.core.content.ContextCompat;
import androidx.lifecycle.LifecycleOwner;

import android.os.Bundle;
import android.util.Log;
import android.util.Size;

import com.google.common.util.concurrent.ListenableFuture;

import java.util.concurrent.ExecutionException;
import java.util.concurrent.Executor;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class MainActivity extends AppCompatActivity {

    private ImageCapture imageCapture;
    private ListenableFuture<ProcessCameraProvider> cameraProviderFuture;
//    private ExecutorService executor;

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

//        executor = Executors.newSingleThreadExecutor();

        PreviewView previewView = findViewById(R.id.previewView);

        cameraProviderFuture = ProcessCameraProvider.getInstance(this);

        cameraProviderFuture.addListener(() -> {
            try {
                // Camera provider is now guaranteed to be available
                ProcessCameraProvider cameraProvider = cameraProviderFuture.get();

                // Set up the view finder use case to display camera preview
                Preview preview = new Preview.Builder().build();

                // Choose the camera by requiring a lens facing
                CameraSelector cameraSelector = new CameraSelector.Builder()
                        .requireLensFacing(CameraSelector.LENS_FACING_FRONT)
                        .build();

                // Connect the preview use case to the previewView
                preview.setSurfaceProvider(
                        previewView.createSurfaceProvider());

                // Set up the capture use case to allow users to take photos
//                imageCapture = new ImageCapture.Builder()
//                        .setCaptureMode(ImageCapture.CAPTURE_MODE_MINIMIZE_LATENCY)
//                        .build();

//                ImageAnalysis imageAnalysis =
//                        new ImageAnalysis.Builder()
//                                .setTargetResolution(new Size(1280, 720))
//                                .setBackpressureStrategy(ImageAnalysis.STRATEGY_KEEP_ONLY_LATEST)
//                                .build();
//
//                imageAnalysis.setAnalyzer(executor, new ImageAnalysis.Analyzer() {
//                    @Override
//                    public void analyze(@NonNull ImageProxy image) {
//                        int rotationDegrees = image.getImageInfo().getRotationDegrees();
//                        Log.i("CameraXApp3", "Image Analyzed");
//                    }
//                });

                // Attach use cases to the camera with the same lifecycle owner
                Camera camera = cameraProvider.bindToLifecycle(
                        ((LifecycleOwner) this),
                        cameraSelector,
                        preview);

            } catch (InterruptedException | ExecutionException e) {
                // Currently no exceptions thrown. cameraProviderFuture.get() should
                // not block since the listener is being called, so no need to
                // handle InterruptedException.
            }
        }, ContextCompat.getMainExecutor(this));
    }

}

这工作正常,没有 logcat 错误。我将在最后添加清单和布局 XML,因为它是相同的,但将此代码与下面的代码进行比较,它只是取消注释几行以添加一个空的 ImageAnalyzer 和所需的执行程序:

package jp.oist.cameraxapp;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.appcompat.app.AppCompatActivity;
import androidx.camera.core.Camera;
import androidx.camera.core.CameraSelector;
import androidx.camera.core.ImageAnalysis;
import androidx.camera.core.ImageCapture;
import androidx.camera.core.ImageProxy;
import androidx.camera.core.Preview;
import androidx.camera.lifecycle.ProcessCameraProvider;
import androidx.camera.view.PreviewView;
import androidx.core.content.ContextCompat;
import androidx.lifecycle.LifecycleOwner;

import android.os.Bundle;
import android.util.Log;
import android.util.Size;

import com.google.common.util.concurrent.ListenableFuture;

import java.util.concurrent.ExecutionException;
import java.util.concurrent.Executor;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class MainActivity extends AppCompatActivity {

    private ImageCapture imageCapture;
    private ListenableFuture<ProcessCameraProvider> cameraProviderFuture;
    private ExecutorService executor;

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

        executor = Executors.newSingleThreadExecutor();

        PreviewView previewView = findViewById(R.id.previewView);

        cameraProviderFuture = ProcessCameraProvider.getInstance(this);

        cameraProviderFuture.addListener(() -> {
            try {
                // Camera provider is now guaranteed to be available
                ProcessCameraProvider cameraProvider = cameraProviderFuture.get();

                // Set up the view finder use case to display camera preview
                Preview preview = new Preview.Builder().build();

                // Choose the camera by requiring a lens facing
                CameraSelector cameraSelector = new CameraSelector.Builder()
                        .requireLensFacing(CameraSelector.LENS_FACING_FRONT)
                        .build();

                // Connect the preview use case to the previewView
                preview.setSurfaceProvider(
                        previewView.createSurfaceProvider());

                // Set up the capture use case to allow users to take photos
//                imageCapture = new ImageCapture.Builder()
//                        .setCaptureMode(ImageCapture.CAPTURE_MODE_MINIMIZE_LATENCY)
//                        .build();

                ImageAnalysis imageAnalysis =
                        new ImageAnalysis.Builder()
                                .setTargetResolution(new Size(1280, 720))
                                .setBackpressureStrategy(ImageAnalysis.STRATEGY_KEEP_ONLY_LATEST)
                                .build();

                imageAnalysis.setAnalyzer(executor, new ImageAnalysis.Analyzer() {
                    @Override
                    public void analyze(@NonNull ImageProxy image) {
                        int rotationDegrees = image.getImageInfo().getRotationDegrees();
                        Log.i("CameraXApp3", "Image Analyzed");
                    }
                });

                // Attach use cases to the camera with the same lifecycle owner
                Camera camera = cameraProvider.bindToLifecycle(
                        ((LifecycleOwner) this),
                        cameraSelector,
                        preview,
                        imageAnalysis);

            } catch (InterruptedException | ExecutionException e) {
                // Currently no exceptions thrown. cameraProviderFuture.get() should
                // not block since the listener is being called, so no need to
                // handle InterruptedException.
            }
        }, ContextCompat.getMainExecutor(this));
    }

}

这会产生与 codelabs 示例代码中相同的 logcat 错误:

07-28 18:22:16.225 211-29468/? E/mm-camera: module_faceproc_port_event_func:886] MCT_EVENT_MODULE_BUF_DIVERT 65539, Cannot start FD, active 10002, frameid 432 431, native 1, mapped 1 1
07-28 18:22:16.258 211-29468/? E/mm-camera: module_faceproc_port_event_func:886] MCT_EVENT_MODULE_BUF_DIVERT 65539, Cannot start FD, active 10002, frameid 433 432, native 1, mapped 1 1
07-28 18:22:16.291 211-29468/? E/mm-camera: module_faceproc_port_event_func:886] MCT_EVENT_MODULE_BUF_DIVERT 65539, Cannot start FD, active 10002, frameid 434 433, native 1, mapped 1 1

看起来 imageAnalysis 对象的创建本身并没有创建它,因为我可以保留此代码,但只需从 bindToLifecycle() 调用中删除 imageAnalysis 对象,此错误就会消失。我的猜测是我在绑定到 imageAnalysis 对象的执行程序和 cameraProvider 的生命周期之间设置了错误。我对这两个概念都很陌生,所以我在这方面的无知是我怀疑这个问题的唯一原因(因为我没有正确理解它)。我可以在这里犯一些明显的禁忌吗?

布局 XML 和清单如下:

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity">

    <FrameLayout
        android:id="@+id/container"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toTopOf="parent">
        <androidx.camera.view.PreviewView
            android:id="@+id/previewView"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintLeft_toLeftOf="parent"
            app:layout_constraintRight_toRightOf="parent"
            app:layout_constraintTop_toTopOf="parent"/>
    </FrameLayout>


</androidx.constraintlayout.widget.ConstraintLayout>
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="jp.oist.cameraxapp">

    <uses-feature android:name="android.hardware.camera.any" />
    <uses-permission android:name="android.permission.CAMERA" />

    <application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:roundIcon="@mipmap/ic_launcher_round"
        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>

【问题讨论】:

    标签: android android-studio kotlin android-camerax


    【解决方案1】:

    TLDR

    看起来像是与任何

        // implementation 'com.google.mlkit:object-detection:16.1.0'
        // implementation 'com.google.mlkit:object-detection:16.2.0'
    

    详尽的解释

    在我的应用级 gradle 文件中将 com.google.mlkit:object-detection:16.1.0 包更新为 com.google.mlkit:object-detection:16.2.0 可以使错误可靠地消失。

    突出显示问题中的代码:

    // ------------------Error Start------------------ 
        implementation 'com.google.mlkit:object-detection:16.2.0'
    // ------------------Error End------------------ 
    

    生成 Gradle 文件完全错误

    apply plugin: 'com.android.application'
    
    android {
        compileSdkVersion 29
        buildToolsVersion "30.0.0"
    
        defaultConfig {
            applicationId "jp.oist.cameraxapp"
            minSdkVersion 21
            targetSdkVersion 29
            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.1.0'
        implementation 'androidx.constraintlayout:constraintlayout:1.1.3'
        implementation 'androidx.camera:camera-camera2:1.0.0-beta07'
        testImplementation 'junit:junit:4.12'
        androidTestImplementation 'androidx.test.ext:junit:1.1.1'
        androidTestImplementation 'androidx.test.espresso:espresso-core:3.2.0'
        // CameraX core library using the camera2 implementation
        def camerax_version = "1.0.0-beta07"
        // The following line is optional, as the core library is included indirectly by camera-camera2
        implementation "androidx.camera:camera-core:${camerax_version}"
        implementation "androidx.camera:camera-camera2:${camerax_version}"
        // If you want to additionally use the CameraX Lifecycle library
        implementation "androidx.camera:camera-lifecycle:${camerax_version}"
        // If you want to additionally use the CameraX View class
        implementation "androidx.camera:camera-view:1.0.0-alpha14"
        // If you want to additionally use the CameraX Extensions library
    //    implementation "androidx.camera:camera-extensions:1.0.0-alpha14"
    // ------------------Error Start------------------ 
        implementation 'com.google.mlkit:object-detection:16.1.0'
    // ------------------Error End------------------ 
    //    implementation 'com.google.mlkit:face-detection:16.0.1'
    //    implementation 'com.google.mlkit:barcode-scanning:16.0.1'
    
    
    }
    

    完整的无错误 Gradle 文件

    apply plugin: 'com.android.application'
    
    android {
        compileSdkVersion 29
        buildToolsVersion "30.0.0"
    
        defaultConfig {
            applicationId "jp.oist.cameraxapp"
            minSdkVersion 21
            targetSdkVersion 29
            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.1.0'
        implementation 'androidx.constraintlayout:constraintlayout:1.1.3'
        implementation 'androidx.camera:camera-camera2:1.0.0-beta07'
        testImplementation 'junit:junit:4.12'
        androidTestImplementation 'androidx.test.ext:junit:1.1.1'
        androidTestImplementation 'androidx.test.espresso:espresso-core:3.2.0'
        // CameraX core library using the camera2 implementation
        def camerax_version = "1.0.0-beta07"
        // The following line is optional, as the core library is included indirectly by camera-camera2
        implementation "androidx.camera:camera-core:${camerax_version}"
        implementation "androidx.camera:camera-camera2:${camerax_version}"
        // If you want to additionally use the CameraX Lifecycle library
        implementation "androidx.camera:camera-lifecycle:${camerax_version}"
        // If you want to additionally use the CameraX View class
        implementation "androidx.camera:camera-view:1.0.0-alpha14"
        // If you want to additionally use the CameraX Extensions library
    //    implementation "androidx.camera:camera-extensions:1.0.0-alpha14"
    // ------------------Error Start------------------ 
        implementation 'com.google.mlkit:object-detection:16.2.0'
    // ------------------Error End------------------ 
    //    implementation 'com.google.mlkit:face-detection:16.0.1'
    //    implementation 'com.google.mlkit:barcode-scanning:16.0.1'
    
    
    }
    

    令人惊讶的是,我的 MainActivity.java 文件中的任何 mlkit 包都没有直接依赖关系,项目中也没有其他 java 文件。实现只是为了稍后在代码的 ImageAnalysis 部分中使用它们,但尚未实现。

    这可能与here 中提到的自定义执行器有关。

    在 Android 上,增加了对指定您自己的自定义执行程序的支持,以运行昂贵的任务,例如模型加载和推断图像标签以及对象检测和跟踪。在此版本中,所有 ML Kit API 现在都支持自定义执行程序。

    默认情况下,ML Kit 使用高度优化的内部管理线程池来运行后台任务。此 API 可以帮助开发人员希望完全控制其应用程序中的线程的特殊用例。

    因为我正在使用这样的执行器,但我不确定如何使用提到的“内部管理的线程池”。此外,由于我对当前代码中的任何 mlkit 包没有直接依赖关系,因此我对 mlkit 包如何首先生成这些 logcat 错误感到茫然,但你已经有了。请添加更好的答案,或者如果您有任何见解,请提供见解!

    【讨论】:

      【解决方案2】:

      创建 ImageCapture 使用是否有一些内在要求 我在文档中遗漏的情况?

      不,没有。您可以在没有图像捕获用例的情况下自行使用预览和图像分析。您可以查看文档中this section 末尾的表格中支持的用例组合。

      mm-camera 标记的错误日志来自哪里?

      这不是 CameraX 日志,它很可能是来自相机框架/HAL 的日志。您可以在 code search 中找到对它的引用。

      【讨论】:

      • 是的,我通读了这些文档,包括引用的表格。我还在您提到的链接中使用了组合用例的示例代码。此代码在 logcats 中产生了相同的错误。如果我添加一个 ImageCapture 对象并绑定到生命周期,这些错误就会消失。我以为这是我做错了什么,但是当我在运行codelabs代码时看到同样的错误时,我认为值得在这里问一下。
      • 我在问题中添加了一个新部分,该部分直接使用 Android Docs 中的示例代码(而不是 codelabs)。此示例使用 Java 并显示相同的 logcat 错误。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2011-05-25
      • 1970-01-01
      • 2018-07-19
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多