Creación de mi propia aplicación de cámara + Captura automática de la imagen
He creado mi propia aplicación de cámara. Y cuando hago clic en el botón toma la foto y la salva en la galera. Lo que quiero hacer es tomar la foto sin una vista previa y sin hacer clic en ningún botón.
Mi clase de actividad principal.
- Lectura de imágenes RGB con un ImageReader
- Graves bloqueos de cámara y RuntimeException en Android
- Cómo obtener id de la cámara frente a frente con Camera2?
- Problema de tamaño de vista previa de la cámara Android
- Android: orientación de la vista previa de la cámara en modo vertical
package themiya.camera.android; import java.io.File; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; import java.text.SimpleDateFormat; import java.util.Calendar; import java.util.Date; import android.app.Activity; import android.content.Context; import android.content.pm.PackageManager; import android.hardware.Camera; import android.hardware.Camera.PictureCallback; import android.net.Uri; import android.os.Bundle; import android.os.Environment; import android.provider.MediaStore; import android.view.View; import android.widget.Button; import android.widget.FrameLayout; import android.widget.Toast; public class CameraActivity extends Activity { private Camera mCamera; private CameraPreview mPreview; public static final int MEDIA_TYPE_IMAGE = 1; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); Button captureButton = (Button) findViewById(R.id.button_capture); System.out.println("Starting!"); // Create an instance of Camera mCamera = getCameraInstance(); // Create our Preview view and set it as the content of our activity. mPreview = new CameraPreview(this, mCamera); FrameLayout preview = (FrameLayout) findViewById(R.id.camera_preview); preview.addView(mPreview); final PictureCallback mPicture = new PictureCallback() { public void onPictureTaken(byte[] data, Camera camera) { File pictureFile = getOutputMediaFile(MEDIA_TYPE_IMAGE); if (pictureFile == null){ return; } try { FileOutputStream fos = new FileOutputStream(pictureFile); fos.write(data); fos.close(); MediaStore.Images.Media.insertImage(getContentResolver(), pictureFile.getAbsolutePath(), pictureFile.getName(), pictureFile.getName()); } catch (FileNotFoundException e) { } catch (IOException e) { } } }; // Add a listener to the Capture button captureButton.setOnClickListener( new View.OnClickListener() { public void onClick(View v) { // get an image from the camera System.out.println("Photo Taking!"); mCamera.takePicture(null, null, mPicture); } } ); } /** A safe way to get an instance of the Camera object. */ public static Camera getCameraInstance(){ Camera c = null; try { c = Camera.open(); // attempt to get a Camera instance } catch (Exception e){ // Camera is not available (in use or does not exist) } return c; // returns null if camera is unavailable } @Override protected void onPause() { super.onPause(); releaseCamera(); // release the camera immediately on pause event } private void releaseCamera(){ if (mCamera != null){ mCamera.release(); // release the camera for other applications mCamera = null; } } /** Create a File for saving an image or video */ private File getOutputMediaFile(int type){ // To be safe, you should check that the SDCard is mounted // using Environment.getExternalStorageState() before doing this. File mediaStorageDir = new File(Environment.getExternalStoragePublicDirectory( Environment.DIRECTORY_PICTURES), "MyCameraApp"); // This location works best if you want the created images to be shared // between applications and persist after your app has been uninstalled. // Create the storage directory if it does not exist if (! mediaStorageDir.exists()){ if (! mediaStorageDir.mkdirs()){ return null; } } // Create a media file name String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date()); File mediaFile; if (type == MEDIA_TYPE_IMAGE){ mediaFile = new File(mediaStorageDir.getPath() + File.separator + "IMG_"+ timeStamp + ".jpg"); } else { return null; } return mediaFile; } }
Y la clase de vista previa.
package themiya.camera.android; import android.content.Context; import android.hardware.Camera; import android.view.SurfaceHolder; import android.view.SurfaceView; public class CameraPreview extends SurfaceView implements SurfaceHolder.Callback{ private SurfaceHolder mHolder; private Camera mCamera; public CameraPreview(Context context,Camera camera) { super(context); mCamera = camera; /*SurfaceView view = new SurfaceView(this); c.setPreviewDisplay(view.getHolder()); c.startPreview(); c.takePicture(shutterCallback, rawPictureCallback, jpegPictureCallback); * */ // Install a SurfaceHolder.Callback so we get notified when the // underlying surface is created and destroyed. mHolder = getHolder(); mHolder.addCallback(this); // deprecated setting, but required on Android versions prior to 3.0 mHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS); } public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) { // TODO Auto-generated method stub if (mHolder.getSurface() == null){ // preview surface does not exist return; } // stop preview before making changes try { mCamera.stopPreview(); } catch (Exception e){ // ignore: tried to stop a non-existent preview } // set preview size and make any resize, rotate or // reformatting changes here // start preview with new settings try { mCamera.setPreviewDisplay(mHolder); mCamera.startPreview(); } catch (Exception e){ } } public void surfaceCreated(SurfaceHolder holder) { // TODO Auto-generated method stub } public void surfaceDestroyed(SurfaceHolder holder) { // TODO Auto-generated method stub } }
En la clase de actividad, el método click es así.
captureButton.setOnClickListener( new View.OnClickListener() { public void onClick(View v) { // get an image from the camera System.out.println("Photo Taking!"); mCamera.takePicture(null, null, mPicture); } } );
Y cuando retiro esa parte del oyente y pongo solamente el
mCamera.takePicture(null, null, mPicture);
La aplicación de parte se bloquea. Creo que puede ser debido al retraso que tarda la aplicación para abrir la cámara. Así que el código intenta obtener la foto antes de abrir la cámara. También espera (10000); No funcionó para mí.
Y también quiero tomar la foto sin la vista previa. Según mi conocimiento tengo que cambiar la clase de vista previa para hacer eso. Pero no sé la forma correcta de hacerlo.
¿Puede alguien ayudarme con esta asp.
- Hermosa forma de superar el error con ACTION_IMAGE_CAPTURE
- Cómo acceder a la cámara específica en el teléfono móvil a través de html5
- ¿Cómo puedo configurar la función de cámara anti-shake (estabilizador de imagen) en android
- Objetivo de la cámara no funciona con Samsung Galaxy S3
- MediaServer Remote Binder Objeto de cámara muerto - sólo en KITKAT
- ¿Cómo utilizar la cámara web en el emulador de Android para capturar una imagen en vivo?
- Cargar una foto de la biblioteca con el navegador web de Android
- ¿Cómo obtener datos de vista previa sin procesar de un objeto de cámara al menos 15 cuadros por segundo en Android?
El truco es dar a la clase de cámara un SurfaceView que no es parte de la jerarquía de vista. El siguiente código es de una de mis aplicaciones donde utilicé esta técnica para mostrar mi propio
@Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); } @Override protected void onPause() { super.onPause(); if (mCamera != null) { mCamera.stopPreview(); mCamera.release(); mCamera = null; } } @Override protected void onResume() { super.onResume(); mCamera = Camera.open(); startPreview(); } private void startPreview() { if (mCamera != null) { mCamera.stopPreview(); try { mCamera.setPreviewDisplay(new SurfaceView(this).getHolder()); } catch (IOException e) { e.printStackTrace(); } mCamera.setPreviewCallbackWithBuffer(this); Camera.Parameters parameters = mCamera.getParameters(); parameters.setPreviewSize(IMAGE_W, IMAGE_H); mCamera.setParameters(parameters); PixelFormat p = new PixelFormat(); PixelFormat.getPixelFormatInfo(parameters.getPreviewFormat(), p); int bufSize = (IMAGE_W * IMAGE_H * p.bitsPerPixel) / 8; mCamera.addCallbackBuffer(new byte[bufSize]); mCamera.startPreview(); } } public void onPreviewFrame(final byte[] data, Camera camera) { if (mCamera == null) { return; } mCamera.addCallbackBuffer(data); } }
Ok encontré una respuesta para tomar la foto automáticamente. Agregar como un comentario para el uso de otros.
final Timer t = new Timer(); t.schedule(new TimerTask() { @Override public void run() { mCamera.takePicture(null, null, mPicture); t.cancel(); } },5000);
Su simple crear otro método con una variable de temporizador con 10000 retraso que termina la actividad de vista previa, entonces se hará. La lógica es que este método se ejecutará 5secs después de la actividad del temporizador 1 se realiza.