java.lang.RuntimeException: takePicture 失败
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/21723557/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
java.lang.RuntimeException: takePicture failed
提问by Sun
when i do continuous click on Capture button (without any break), getting Runtime Exception how can i resolve this issue ?
当我连续单击“捕获”按钮(没有任何中断)时,出现运行时异常如何解决此问题?
if its not possible so how may i handle this Exception ?
如果不可能,那么我该如何处理这个异常?
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);
}
});
Log:
日志:
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.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)
Note:-Like in Pudding Camera, they allow user to do continuous tap on Capture button, but they will never show exception, if you do 50 clicks it will capture 10 or more images, each image after specific time but not showing exception, like i am getting in my code, in a same way how can i handle this exception ?
注意:-就像在布丁相机中一样,它们允许用户连续点击捕获按钮,但它们永远不会显示异常,如果您点击 50 次,它将捕获 10 个或更多图像,特定时间后的每个图像但不显示异常,例如我正在输入我的代码,以同样的方式我该如何处理这个异常?
Complete Code:
完整代码:
@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;
}
}
采纳答案by Melquiades
Firstly, catch your exceptions in onPictureTaken, leaving empty catch sections is not a good practice. Then, I would add a flag that would prevent from calling takePicture() while previous picture is being saved. Later in your button onClick you would check if it's ok to call takePicture().
首先,在 onPictureTaken 中捕获异常,留下空的捕获部分不是一个好习惯。然后,我将添加一个标志,防止在保存上一张图片时调用 takePicture()。稍后在您的按钮 onClick 中,您将检查是否可以调用 takePicture()。
Declare a flag as a member of your Activity:
private boolean safeToTakePicture = false;
In
surfaceChanged()
, just set the flag to true after calling startPreview():camera.startPreview(); safeToTakePicture = true;
In your
onClick()
listener check the flag and take picture if ok to do so:if (safeToTakePicture) { mp.start(); camera.takePicture(null, null, mPicture); safeToTakePicture = false; }
In
onPictureTaken()
, set the flag again to true after picture has been saved (and add exception printing):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; } };
将标志声明为您的 Activity 的成员:
private boolean safeToTakePicture = false;
在 中
surfaceChanged()
,只需在调用 startPreview() 后将标志设置为 true:camera.startPreview(); safeToTakePicture = true;
在您的
onClick()
听众中检查标志并拍照(如果可以):if (safeToTakePicture) { mp.start(); camera.takePicture(null, null, mPicture); safeToTakePicture = false; }
在 中
onPictureTaken()
,在保存图片后再次将标志设置为 true(并添加异常打印):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; } };
NOTES:As the docs say, "Preview must be started before you can take a picture.", so possible enhancement would be to use setPreviewCallback() to register callback that will be called when preview data is available, and set the flag to true when onPreviewFrame is called.
注意:正如文档所说,“必须先开始预览,然后才能拍照。” ,因此可能的改进是使用 setPreviewCallback() 注册将在预览数据可用时调用的回调,并在调用 onPreviewFrame 时将该标志设置为 true。
回答by ThaMe90
回答by Ahmad Arslan
This method will help you in trying to solve the problem.
此方法将帮助您尝试解决问题。
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;
}
}
回答by Make it Simple
I also had the similar issue. later i found startPreview
is very important.
我也有类似的问题。后来我发现startPreview
很重要。
_camera.startPreview()
is very important before the takePicutre checkout the point 5 and 6
in this link.
_camera.startPreview()
在 takePicutre 结帐之前,此链接中的第 5 点和第 6 点非常重要
。
回答by Tabish
There can be many reasons for this in my case i was trying to take photo without preview (hidden photo) and i was using SurfaceView
, So i replaced it with SurfaceTexture
在我的情况下,这可能有很多原因,我试图在没有预览的情况下拍照(隐藏照片)并且我正在使用SurfaceView
,所以我将其替换为SurfaceTexture
SurfaceTexture surfaceTexture = new SurfaceTexture(10);
camera.setPreviewTexture(surfaceTexture);
and the problem was solved... P.S I was getting this error only on Above 6.0 devices
问题解决了... PS 我只在 6.0 以上的设备上收到这个错误