卧式纯绿 2024-05-02 17:28 采纳率: 62.1%
浏览 29
已结题

安卓开发摄像头预览出现问题

安卓开发摄像头预览时出现问题
在gpt上询问调用textureView类实现摄像头预览在界面上,结果代码显示不全,不知道后面该怎么写

img


这是oncreate的主函数

img


textureView的监听方法

img


打开相机的方法

img


获取前置相机ID以及状态返回函数

  • 写回答

3条回答 默认 最新

  • 专家-赤兔[在线] 优质创作者: 编程框架技术领域 2024-05-02 17:28
    关注

    引自免费微信小程序:皆我百晓生

    在Android开发中,使用TextureView显示摄像头预览是一个常见的需求。根据您提供的部分代码,我可以帮您补全并解释整个流程。这里有一个完整的示例,包括了打开相机、获取前后摄像头ID、创建预览会话和关闭相机等功能。

    首先,在您的activity_camera.xml布局文件中添加一个TextureView组件:

    <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">
    
        <TextureView
            android:id="@+id/textureView"
            android:layout_width="match_parent"
            android:layout_height="match_parent" />
    
    </androidx.constraintlayout.widget.ConstraintLayout>
    

    然后,在您的Activity中(例如MainActivity.java)实现以下代码:

    import android.Manifest;
    import android.content.pm.PackageManager;
    import android.hardware.camera2.CameraAccessException;
    import android.hardware.camera2.CameraCaptureSession;
    import android.hardware.camera2.CameraDevice;
    import android.hardware.camera2.CameraManager;
    import android.hardware.camera2.CaptureRequest;
    import android.hardware.camera2.params.StreamConfigurationMap;
    import android.os.Bundle;
    import android.os.Handler;
    import android.os.HandlerThread;
    import android.util.Log;
    import android.view.Surface;
    import android.widget.Toast;
    
    import androidx.annotation.NonNull;
    import androidx.appcompat.app.AppCompatActivity;
    import androidx.core.app.ActivityCompat;
    import androidx.core.content.ContextCompat;
    
    import java.io.IOException;
    import java.util.ArrayList;
    import java.util.List;
    import java.util.concurrent.ExecutorService;
    import java.util.concurrent.Executors;
    
    public class MainActivity extends AppCompatActivity {
    
        private static final String TAG = "MainActivity";
        private TextureView textureView;
        private Handler backgroundHandler;
        private HandlerThread backgroundThread;
        private CameraDevice cameraDevice;
        private CameraCaptureSession cameraCaptureSession;
        private Surface previewSurface;
        private String cameraId;
        private ExecutorService executorService;
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_camera);
    
            textureView = findViewById(R.id.textureView);
            textureView.setSurfaceTextureListener(textureListener);
    
            if (ContextCompat.checkSelfPermission(this, Manifest.permission.CAMERA)
                    != PackageManager.PERMISSION_GRANTED) {
                // Request camera permission
                ActivityCompat.requestPermissions(this,
                        new String[]{Manifest.permission.CAMERA},
                        REQUEST_CAMERA_PERMISSION);
            } else {
                openCamera();
            }
        }
    
        private final TextureView.SurfaceTextureListener textureListener = new TextureView.SurfaceTextureListener() {
            @Override
            public void onSurfaceTextureAvailable(SurfaceTexture surface, int width, int height) {
                createCameraPreviewSession(surface);
            }
    
            @Override
            public void onSurfaceTextureSizeChanged(SurfaceTexture surface, int width, int height) {
                // Ignored since size changing is handled by onSurfaceTextureAvailable()
            }
    
            @Override
            public boolean onSurfaceTextureDestroyed(SurfaceTexture surface) {
                return true;
            }
    
            @Override
            public void onSurfaceTextureUpdated(SurfaceTexture surface) {
                // Ignored
            }
        };
    
        private void openCamera() {
            CameraManager cameraManager = (CameraManager) getSystemService(Context.CAMERA_SERVICE);
            try {
                cameraId = getFrontCameraId();
                if (cameraId == null) {
                    Toast.makeText(this, "No front camera found", Toast.LENGTH_SHORT).show();
                    finish();
                    return;
                }
                cameraManager.openCamera(cameraId, stateCallback, backgroundHandler);
            } catch (CameraAccessException e) {
                Log.e(TAG, "Error opening camera", e);
            }
        }
    
        private String getFrontCameraId() {
            CameraManager cameraManager = (CameraManager) getSystemService(Context.CAMERA_SERVICE);
            try {
                String[] cameraIds = cameraManager.getCameraIdList();
                for (String id : cameraIds) {
                    CameraCharacteristics characteristics = cameraManager.getCameraCharacteristics(id);
                    int lensFacing = characteristics.get(CameraCharacteristics.LENS_FACING);
                    if (lensFacing == CameraCharacteristics.LENS_FACING_FRONT) {
                        return id;
                    }
                }
            } catch (CameraAccessException e) {
                Log.e(TAG, "Error getting camera characteristics", e);
            }
            return null;
        }
    
        private void closeCamera() {
            if (cameraDevice != null) {
                cameraDevice.close();
                cameraDevice = null;
            }
            if (executorService != null) {
                executorService.shutdown();
                executorService = null;
            }
        }
    
        private void createCameraPreviewSession(Surface surface) {
            if (null == cameraDevice || null == surface) {
                return;
            }
    
            try {
                SurfaceTexture texture = textureView.getSurfaceTexture();
                assert texture != null;
    
                texture.setDefaultBufferSize(previewSize.getWidth(), previewSize.getHeight());
                previewSurface = new Surface(texture);
    
                List<Surface> surfaces = new ArrayList<>();
                surfaces.add(previewSurface);
                surfaces.add(new Surface(textureView.getSurface()));
    
                cameraDevice.createCaptureSession(surfaces, new CameraCaptureSession.StateCallback() {
                    @Override
                    public void onConfigured(@NonNull CameraCaptureSession session) {
                        cameraCaptureSession = session;
                        updatePreview();
                    }
    
                    @Override
                    public void onConfigureFailed(@NonNull CameraCaptureSession session) {
                        Log.e(TAG, "Failed to configure camera");
                    }
                }, backgroundHandler);
            } catch (CameraAccessException e) {
                Log.e(TAG, "Cannot create camera preview session", e);
            }
        }
    
        private void updatePreview() {
            if (null == cameraDevice) {
                return;
            }
            CaptureRequest.Builder captureBuilder = cameraDevice.createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW);
            captureBuilder.addTarget(previewSurface);
    
            cameraCaptureSession.setRepeatingRequest(captureBuilder.build(), null, backgroundHandler);
        }
    
        private final CameraDevice.StateCallback stateCallback = new CameraDevice.StateCallback() {
            @Override
            public void onOpened(@NonNull CameraDevice camera) {
                cameraDevice = camera;
                startBackgroundThread();
                createCameraPreviewSession(textureView.getSurface());
            }
    
            @Override
            public void onDisconnected(@NonNull CameraDevice camera) {
                cameraDevice.close();
                cameraDevice = null;
            }
    
            @Override
            public void onError(@NonNull CameraDevice camera, int error) {
                cameraDevice.close();
                cameraDevice = null;
            }
        };
    
        private void startBackgroundThread() {
            backgroundThread = new HandlerThread("CameraBackground");
            backgroundThread.start();
            backgroundHandler = new Handler(backgroundThread.getLooper());
            executorService = Executors.newSingleThreadExecutor();
        }
    
        @Override
        protected void onDestroy() {
            super.onDestroy();
            closeCamera();
            stopBackgroundThread();
        }
    
        private void stopBackgroundThread() {
            if (backgroundThread != null) {
                backgroundThread.quitSafely();
                try {
                    backgroundThread.join();
                    backgroundThread = null;
                } catch (InterruptedException e) {
                    Log.d(TAG, "Interrupted while waiting for background thread to terminate.");
                }
            }
            backgroundHandler = null;
        }
    
        @Override
        public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
            if (requestCode == REQUEST_CAMERA_PERMISSION) {
                if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
                    openCamera();
                } else {
                    Toast.makeText(this, "Permission denied for camera", Toast.LENGTH_SHORT).show();
                    finish();
                }
            }
        }
    }
    

    在这个例子中,我们实现了以下几个关键功能:

    1. onCreate()中初始化TextureView并检查权限。
    2. 使用textureListener处理Surface的变化。
    3. getFrontCameraId()方法用于获取可用的前置摄像头ID。
    4. openCamera()closeCamera()方法分别用于打开和关闭相机设备。
    5. createCameraPreviewSession()用于设置预览会话,并将Surface绑定到预览和TextureView。
    6. updatePreview()用于更新预览请求。
    7. stateCallback处理相机设备的状态变化,如打开、断开连接和错误。
    8. startBackgroundThread()stopBackgroundThread()用于管理后台线程,确保操作在正确的线程上执行。

    注意:这个示例仅展示了前置摄像头的预览。如果您想切换到后置摄像头,只需在openCamera()方法中替换getFrontCameraId()getBackCameraId()即可。

    另外,别忘了在AndroidManifest.xml中添加以下权限:

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

    确保运行此应用的设备具有合适的权限才能访问摄像头。

    评论 编辑记录

报告相同问题?

问题事件

  • 已结题 (查看结题原因) 5月3日
  • 创建了问题 5月2日