ejemplo - java.lang.RuntimeException: takePicture failed
surfaceview android camera (5)
cuando lo hago continuamente, haga clic en el botón Capturar (sin interrupción), obteniendo Excepción de tiempo de ejecución ¿cómo puedo resolver este problema?
si no es posible, ¿cómo puedo manejar esta excepción?
btnCapture = (ImageButton) findViewById(R.id.btnCapture);
final MediaPlayer mp = MediaPlayer.create(CameraLauncherActivity.this, R.raw.button);
btnCapture.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
// line where getting RuntimeException
camera.takePicture(null, null, mPicture);
}
});
Iniciar sesión:
02-12 14:48:41.580: E/AndroidRuntime(6997): FATAL EXCEPTION: main
02-12 14:48:41.580: E/AndroidRuntime(6997): java.lang.RuntimeException: takePicture failed
02-12 14:48:41.580: E/AndroidRuntime(6997): at android.hardware.Camera.native_takePicture(Native Method)
02-12 14:48:41.580: E/AndroidRuntime(6997): at android.hardware.Camera.takePicture(Camera.java:1126)
02-12 14:48:41.580: E/AndroidRuntime(6997): at android.hardware.Camera.takePicture(Camera.java:1071)
02-12 14:48:41.580: E/AndroidRuntime(6997): at app.cam.shane.CameraLauncherActivity$3.onClick(CameraLauncherActivity.java:116)
02-12 14:48:41.580: E/AndroidRuntime(6997): at android.view.View.performClick(View.java:4223)
02-12 14:48:41.580: E/AndroidRuntime(6997): at android.view.View$PerformClick.run(View.java:17275)
02-12 14:48:41.580: E/AndroidRuntime(6997): at android.os.Handler.handleCallback(Handler.java:615)
02-12 14:48:41.580: E/AndroidRuntime(6997): at android.os.Handler.dispatchMessage(Handler.java:92)
02-12 14:48:41.580: E/AndroidRuntime(6997): at android.os.Looper.loop(Looper.java:137)
02-12 14:48:41.580: E/AndroidRuntime(6997): at android.app.ActivityThread.main(ActivityThread.java:4921)
02-12 14:48:41.580: E/AndroidRuntime(6997): at java.lang.reflect.Method.invokeNative(Native Method)
02-12 14:48:41.580: E/AndroidRuntime(6997): at java.lang.reflect.Method.invoke(Method.java:511)
02-12 14:48:41.580: E/AndroidRuntime(6997): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1036)
02-12 14:48:41.580: E/AndroidRuntime(6997): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:803)
02-12 14:48:41.580: E/AndroidRuntime(6997): at dalvik.system.NativeStart.main(Native Method)
Nota: - Al igual que en Pudding Camera , permiten al usuario hacer un toque continuo en el botón Capturar, pero nunca mostrarán excepción, si haces 50 clics capturará 10 o más imágenes, cada imagen después de un tiempo específico pero sin mostrar excepción, como Estoy ingresando mi código, de la misma manera, ¿cómo puedo manejar esta excepción?
Código completo:
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_camera);
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
preview=(SurfaceView)findViewById(R.id.surface);
previewHolder=preview.getHolder();
previewHolder.addCallback(surfaceCallback);
previewHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
btnCapture = (ImageButton) findViewById(R.id.btnCapture);
final MediaPlayer mp = MediaPlayer.create(CameraLauncherActivity.this, R.raw.button);
btnCapture.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
mp.start();
camera.takePicture(null, null, mPicture);
}
});
@Override
public void onResume() {
super.onResume();
camera=Camera.open();
}
@Override
public void onPause() {
super.onPause();
if (inPreview) {
camera.stopPreview();
}
camera.release();
camera=null;
inPreview=false;
}
private Camera.Size getBestPreviewSize(int width, int height,
Camera.Parameters parameters) {
Camera.Size result=null;
for (Camera.Size size : parameters.getSupportedPreviewSizes()) {
if (size.width <= width && size.height <= height) {
if (result == null) {
result=size;
}
else {
int resultArea=result.width * result.height;
int newArea=size.width * size.height;
if (newArea > resultArea) {
result=size;
}
}
}
}
return(result);
}
private Camera.Size getSmallestPictureSize(Camera.Parameters parameters) {
Camera.Size result=null;
for (Camera.Size size : parameters.getSupportedPictureSizes()) {
if (result == null) {
result=size;
}
else {
int resultArea=result.width * result.height;
int newArea=size.width * size.height;
if (newArea < resultArea) {
result=size;
}
}
}
return(result);
}
SurfaceHolder.Callback surfaceCallback=new SurfaceHolder.Callback(){
public void surfaceCreated(SurfaceHolder holder) {
try {
camera.setPreviewDisplay(previewHolder);
} catch (Throwable t) {
Log.e("PreviewDemo-surfaceCallback",
"Exception in setPreviewDisplay()", t);
Toast.makeText(CameraLauncherActivity.this, t.getMessage(), Toast.LENGTH_LONG).show();
}
}
public void surfaceChanged(SurfaceHolder holder,int format, int width,int height) {
params = camera.getParameters();
params.setFlashMode(Camera.Parameters.FLASH_MODE_ON);
Camera.Size size = getBestPreviewSize(width, height, params);
Camera.Size pictureSize=getSmallestPictureSize(params);
if (size != null && pictureSize != null) {
params.setPreviewSize(size.width, size.height);
params.setPictureSize(pictureSize.width,
pictureSize.height);
camera.setParameters(params);
camera.startPreview();
inPreview=true;
}
}
public void surfaceDestroyed(SurfaceHolder holder) {
}
};
PictureCallback mPicture = new PictureCallback() {
@Override
public void onPictureTaken(byte[] data, Camera camera) {
pictureFile = getOutputMediaFile();
camera.startPreview();
if (pictureFile == null) {
return;
}
try {
FileOutputStream fos = new FileOutputStream(pictureFile);
fos.write(data);
fos.close();
} catch (FileNotFoundException e) {
} catch (IOException e) {
}
}
};
static File getOutputMediaFile() {
/* yyyy-MM-dd''T''HH:mm:ss.SSSZ */
timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss")
.format(new Date());
// file name
mediaFile = new File(LoginActivity.mediaStorageDir.getPath() + File.separator
+ "IMG_" + timeStamp + ".jpg");
return mediaFile;
}
}
¿ startPreview()
llamar a startPreview()
en la cámara?
Mira aquí para más información.
En primer lugar, capte sus excepciones en onPictureTaken, dejando secciones de catch vacías no es una buena práctica. Luego, agregaría una bandera que evitaría que se llame a tomar imagen () mientras se guarda la imagen anterior. Más tarde, en el botón de clic, verificaría si está bien para llamar a tomar imagen ().
Declara una bandera como miembro de tu actividad:
private boolean safeToTakePicture = false;
En
surfaceChanged()
, simplemente establece el indicador en true después de llamar a startPreview ():camera.startPreview(); safeToTakePicture = true;
En su oyente
onClick()
marque la bandera y tome una foto si está bien para hacerlo:if (safeToTakePicture) { mp.start(); camera.takePicture(null, null, mPicture); safeToTakePicture = false; }
En
onPictureTaken()
, establezca el indicador nuevamente en verdadero después de que se haya guardado la imagen (y añada impresión de excepción):PictureCallback mPicture = new PictureCallback() { @Override public void onPictureTaken(byte[] data, Camera camera) { pictureFile = getOutputMediaFile(); camera.startPreview(); if (pictureFile == null) { //no path to picture, return safeToTakePicture = true; return; } try { FileOutputStream fos = new FileOutputStream(pictureFile); fos.write(data); fos.close(); } catch (FileNotFoundException e) { e.printStackTrace(); //<-------- show exception } catch (IOException e) { e.printStackTrace(); //<-------- show exception } //finished saving picture safeToTakePicture = true; } };
NOTAS: Como dicen los documentos, "La vista previa debe iniciarse antes de poder tomar una foto". , por lo que una posible mejora sería usar setPreviewCallback () para registrar la devolución de llamada que se invocará cuando los datos de vista previa estén disponibles, y establecer el indicador como verdadero cuando se llame a onPreviewFrame.
Este método te ayudará a tratar de resolver el problema.
private void safeCameraOpen(int id) {
try {
releaseCameraAndPreview();
mCamera = Camera.open(id);
} catch (Exception e) {
Log.e(getString(R.string.app_name), "failed to open Camera");
e.printStackTrace();
}
}
private void releaseCameraAndPreview() {
if (mCamera != null) {
mCamera.release();
mCamera = null;
}
}
Puede haber muchas razones para esto en mi caso yo estaba tratando de tomar una foto sin vista previa (foto oculta) y estaba usando SurfaceView
, así que lo SurfaceTexture
con SurfaceTexture
SurfaceTexture surfaceTexture = new SurfaceTexture(10);
camera.setPreviewTexture(surfaceTexture);
y el problema se resolvió ... PD. Recibí este error solo en dispositivos anteriores a 6.0.
También tuve el problema similar. más tarde descubrí que startPreview
es muy importante.
_camera.startPreview()
es muy importante antes de que takePicutre obtenga el punto 5 y 6 en este enlace .