¿Cómo mostrar la vista previa de la cámara en un SurfaceView?

Estoy tratando de abrir el hardware de la cámara en un SurfaceView. En el diseño, creé un SurfaceView y abro la cámara como se muestra en el código de abajo. Cuando ejecuto el código, el brindis en el CameraAvailableCB aparece y dice "onCameraAvailable", pero nada aparece en el SurfaceView.

¿Cómo se muestra la pantalla de la cámara en el SurfaceView?

Código

@Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); this.mBtnCapture = (Button) findViewById(R.id.actMain_btn_capture); this.mSurfaceView = (SurfaceView) findViewById(R.id.actMain_surfaceView); this.mSurfaceHolder = this.mSurfaceView.getHolder(); this.mSurfaceHolder.addCallback(this); this.mCameraManager = (CameraManager) this.getSystemService(Context.CAMERA_SERVICE); try { cameraIDsList = this.mCameraManager.getCameraIdList(); for (String id : cameraIDsList) { Log.v(TAG, "CameraID: " + id); } } catch (CameraAccessException e) { e.printStackTrace(); } cameraStateCB = new CameraDevice.StateCallback() { @Override public void onOpened(CameraDevice camera) { Toast.makeText(getApplicationContext(), "onOpened", Toast.LENGTH_SHORT).show(); //requesting permission int permissionCheck = ContextCompat.checkSelfPermission(activity, Manifest.permission.CAMERA); if (permissionCheck != PackageManager.PERMISSION_GRANTED) { if (ActivityCompat.shouldShowRequestPermissionRationale(activity, Manifest.permission.CAMERA)) { } else { ActivityCompat.requestPermissions(activity, new String[]{Manifest.permission.CAMERA}, MY_PERMISSIONS_REQUEST_CAMERA); Toast.makeText(getApplicationContext(), "request permission", Toast.LENGTH_SHORT).show(); } } else { Toast.makeText(getApplicationContext(), "PERMISSION_ALREADY_GRANTED", Toast.LENGTH_SHORT).show(); } //opening the camera try { mCameraManager.openCamera(cameraIDsList[1], cameraStateCB, new Handler()); } catch (CameraAccessException e) { e.printStackTrace(); } } @Override public void onDisconnected(CameraDevice camera) { Toast.makeText(getApplicationContext(), "onDisconnected", Toast.LENGTH_SHORT).show(); } @Override public void onError(CameraDevice camera, int error) { Toast.makeText(getApplicationContext(), "onError", Toast.LENGTH_SHORT).show(); } }; CameraManager.AvailabilityCallback cameraAvailableCB = new CameraManager.AvailabilityCallback() { @Override public void onCameraAvailable(String cameraId) { super.onCameraAvailable(cameraId); Toast.makeText(getApplicationContext(), "onCameraAvailable", Toast.LENGTH_SHORT).show(); } @Override public void onCameraUnavailable(String cameraId) { super.onCameraUnavailable(cameraId); Toast.makeText(getApplicationContext(), "onCameraUnavailable", Toast.LENGTH_SHORT).show(); } }; this.mCameraManager.registerAvailabilityCallback(cameraAvailableCB, new Handler()); } @Override public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) { super.onRequestPermissionsResult(requestCode, permissions, grantResults); switch (requestCode) { case MY_PERMISSIONS_REQUEST_CAMERA: if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) // Open Camera break; } } @Override public void surfaceCreated(SurfaceHolder holder) { Log.w(TAG, "surfaceCreated"); } @Override public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) { Log.w(TAG, "surfaceChanged"); } @Override public void surfaceDestroyed(SurfaceHolder holder) { Log.w(TAG, "surfaceDestroyed"); } 

Para mostrar la vista previa desde la cámara utilizando la API de Camera2, debe realizar los siguientes pasos:

  1. Obtener permiso para usar un dispositivo de cámara
  2. Uso de CameraManager Conexión abierta a una cámara
  3. Haber preparado Surface para previsualizar
  4. Utilizando el dispositivo de cámara abierto y las superficies deseadas (puede incluir no sólo la superficie de vista previa) crear CaptureSession
  5. Después de CaptureSession creado, necesita crear y configurar CaptureRequest y enviarlo a CaptureSession

Tenga en cuenta que la preparación de superficies y la apertura de conexión a la cámara son procesos independientes, por lo que debe estar seguro de que ambos se completan antes de crear CaptureSession.

Aquí está el ejemplo de actividad para mostrar la vista previa de la cámara en la pantalla:

 public class MainActivity extends AppCompatActivity implements SurfaceHolder.Callback, Handler.Callback { static final String TAG = "CamTest"; static final int MY_PERMISSIONS_REQUEST_CAMERA = 1242; private static final int MSG_CAMERA_OPENED = 1; private static final int MSG_SURFACE_READY = 2; private final Handler mHandler = new Handler(this); SurfaceView mSurfaceView; SurfaceHolder mSurfaceHolder; CameraManager mCameraManager; String[] mCameraIDsList; CameraDevice.StateCallback mCameraStateCB; CameraDevice mCameraDevice; CameraCaptureSession mCaptureSession; boolean mSurfaceCreated = true; boolean mIsCameraConfigured = false; private Surface mCameraSurface = null; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); this.mSurfaceView = (SurfaceView) findViewById(R.id.SurfaceViewPreview); this.mSurfaceHolder = this.mSurfaceView.getHolder(); this.mSurfaceHolder.addCallback(this); this.mCameraManager = (CameraManager) this.getSystemService(Context.CAMERA_SERVICE); try { mCameraIDsList = this.mCameraManager.getCameraIdList(); for (String id : mCameraIDsList) { Log.v(TAG, "CameraID: " + id); } } catch (CameraAccessException e) { e.printStackTrace(); } mCameraStateCB = new CameraDevice.StateCallback() { @Override public void onOpened(CameraDevice camera) { Toast.makeText(getApplicationContext(), "onOpened", Toast.LENGTH_SHORT).show(); mCameraDevice = camera; mHandler.sendEmptyMessage(MSG_CAMERA_OPENED); } @Override public void onDisconnected(CameraDevice camera) { Toast.makeText(getApplicationContext(), "onDisconnected", Toast.LENGTH_SHORT).show(); } @Override public void onError(CameraDevice camera, int error) { Toast.makeText(getApplicationContext(), "onError", Toast.LENGTH_SHORT).show(); } }; } @Override protected void onStart() { super.onStart(); //requesting permission int permissionCheck = ContextCompat.checkSelfPermission(this, Manifest.permission.CAMERA); if (permissionCheck != PackageManager.PERMISSION_GRANTED) { if (ActivityCompat.shouldShowRequestPermissionRationale(this, Manifest.permission.CAMERA)) { } else { ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.CAMERA}, MY_PERMISSIONS_REQUEST_CAMERA); Toast.makeText(getApplicationContext(), "request permission", Toast.LENGTH_SHORT).show(); } } else { Toast.makeText(getApplicationContext(), "PERMISSION_ALREADY_GRANTED", Toast.LENGTH_SHORT).show(); try { mCameraManager.openCamera(mCameraIDsList[1], mCameraStateCB, new Handler()); } catch (CameraAccessException e) { e.printStackTrace(); } } } @Override protected void onStop() { super.onStop(); try { if (mCaptureSession != null) { mCaptureSession.stopRepeating(); mCaptureSession.close(); mCaptureSession = null; } mIsCameraConfigured = false; } catch (final CameraAccessException e) { // Doesn't matter, cloising device anyway e.printStackTrace(); } catch (final IllegalStateException e2) { // Doesn't matter, cloising device anyway e2.printStackTrace(); } finally { if (mCameraDevice != null) { mCameraDevice.close(); mCameraDevice = null; mCaptureSession = null; } } } @Override public boolean handleMessage(Message msg) { switch (msg.what) { case MSG_CAMERA_OPENED: case MSG_SURFACE_READY: // if both surface is created and camera device is opened // - ready to set up preview and other things if (mSurfaceCreated && (mCameraDevice != null) && !mIsCameraConfigured) { configureCamera(); } break; } return true; } private void configureCamera() { // prepare list of surfaces to be used in capture requests List<Surface> sfl = new ArrayList<Surface>(); sfl.add(mCameraSurface); // surface for viewfinder preview // configure camera with all the surfaces to be ever used try { mCameraDevice.createCaptureSession(sfl, new CaptureSessionListener(), null); } catch (CameraAccessException e) { e.printStackTrace(); } mIsCameraConfigured = true; } @Override public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) { super.onRequestPermissionsResult(requestCode, permissions, grantResults); switch (requestCode) { case MY_PERMISSIONS_REQUEST_CAMERA: if (ActivityCompat.checkSelfPermission(this, Manifest.permission.CAMERA) == PackageManager.PERMISSION_GRANTED) try { mCameraManager.openCamera(mCameraIDsList[1], mCameraStateCB, new Handler()); } catch (CameraAccessException e) { e.printStackTrace(); } break; } } @Override public void surfaceCreated(SurfaceHolder holder) { mCameraSurface = holder.getSurface(); } @Override public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) { mCameraSurface = holder.getSurface(); mSurfaceCreated = true; mHandler.sendEmptyMessage(MSG_SURFACE_READY); } @Override public void surfaceDestroyed(SurfaceHolder holder) { mSurfaceCreated = false; } private class CaptureSessionListener extends CameraCaptureSession.StateCallback { @Override public void onConfigureFailed(final CameraCaptureSession session) { Log.d(TAG, "CaptureSessionConfigure failed"); } @Override public void onConfigured(final CameraCaptureSession session) { Log.d(TAG, "CaptureSessionConfigure onConfigured"); mCaptureSession = session; try { CaptureRequest.Builder previewRequestBuilder = mCameraDevice .createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW); previewRequestBuilder.addTarget(mCameraSurface); mCaptureSession.setRepeatingRequest(previewRequestBuilder.build(), null, null); } catch (CameraAccessException e) { Log.d(TAG, "setting up preview failed"); e.printStackTrace(); } } } } 
  • ¿Mejora el rendimiento de la vista personalizada SurfaceView-dervied?
  • ¿Es esto posible tener la opinión de la textura para la cámara en forma circular para el androide?
  • Ocultar una vista de superficie que se superpone a otra
  • Android SurfaceView causando parpadeo de la pantalla
  • Extraño problema de rendimiento con Galaxy Tab
  • Android Surfaceview Crash sin salida de error
  • Android SurfaceView onDraw Pregunta
  • Programación con SurfaceView y estrategia de hilos para el desarrollo de juegos
  • "La superficie ha sido liberada" dentro de "surfaceCreated"
  • ¿Puedo usar lockCanvas () en onPreviewFrame callback?
  • Cambiar tamaño de Android personalizado SurfaceView
  • FlipAndroid es un fan de Google para Android, Todo sobre Android Phones, Android Wear, Android Dev y Aplicaciones para Android Aplicaciones.