安卓:java.lang.RuntimeException:拍照失败
Posted
技术标签:
【中文标题】安卓:java.lang.RuntimeException:拍照失败【英文标题】:Android: java.lang.RuntimeException: takePicture failed 【发布时间】:2014-01-23 04:22:57 【问题描述】:我正在尝试在surfaceview 的ontouchevent 中捕获图像。但是,每次触摸屏幕时,应用程序都会崩溃,并出现以下异常:
01-05 21:03:18.500: ERROR/androidRuntime(10367): FATAL EXCEPTION: main
java.lang.RuntimeException: takePicture failed
at android.hardware.Camera.native_takePicture(Native Method)
at android.hardware.Camera.takePicture(Camera.java:1126)
at android.hardware.Camera.takePicture(Camera.java:1071)
at com.test.MotionDetector.CameraSurfaceView.onTouchEvent(CameraSurfaceView.java:107)
at android.view.View.dispatchTouchEvent(View.java:7350)
at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2470)
at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2212)
at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2470)
at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2212)
at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2470)
at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2212)
at com.android.internal.policy.impl.PhoneWindow$DecorView.superDispatchTouchEvent(PhoneWindow.java:2151)
at com.android.internal.policy.impl.PhoneWindow.superDispatchTouchEvent(PhoneWindow.java:1480)
at android.app.Activity.dispatchTouchEvent(Activity.java:2469)
at com.android.internal.policy.impl.PhoneWindow$DecorView.dispatchTouchEvent(PhoneWindow.java:2099)
at android.view.View.dispatchPointerEvent(View.java:7535)
at android.view.ViewRootImpl.deliverPointerEvent(ViewRootImpl.java:3492)
at android.view.ViewRootImpl.deliverInputEvent(ViewRootImpl.java:3424)
at android.view.ViewRootImpl.doProcessInputEvents(ViewRootImpl.java:4534)
at android.view.ViewRootImpl.enqueueInputEvent(ViewRootImpl.java:4512)
at android.view.ViewRootImpl$WindowInputEventReceiver.onInputEvent(ViewRootImpl.java:4616)
at android.view.InputEventReceiver.dispatchInputEvent(InputEventReceiver.java:171)
at android.os.MessageQueue.nativePollOnce(Native Method)
at android.os.MessageQueue.next(MessageQueue.java:125)
at android.os.Looper.loop(Looper.java:124)
at android.app.ActivityThread.main(ActivityThread.java:4921)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:511)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1038)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:805)
at dalvik.system.NativeStart.main(Native Method)
我的代码:
package com.nadim.MotionDetector;
import android.content.Context;
import android.hardware.Camera;
import android.os.Environment;
import android.util.Log;
import android.view.MotionEvent;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.widget.Toast;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.Date;
public class CameraSurfaceView extends SurfaceView implements SurfaceHolder.Callback
private SurfaceHolder mHolder;
private Camera mCamera;
private Context context;
public CameraSurfaceView(Context context, Camera camera)
super(context);
this.context = context;
mCamera = camera;
// 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 surfaceCreated(SurfaceHolder holder)
// The Surface has been created, now tell the camera where to draw the preview.
try
mCamera.setPreviewDisplay(holder);
mCamera.startPreview();
catch (IOException e)
Log.d("MotionDetector", "Error setting camera preview: " + e.getMessage());
public void surfaceDestroyed(SurfaceHolder holder)
// empty. Take care of releasing the Camera preview in your activity.
public void surfaceChanged(SurfaceHolder holder, int format, int w, int h)
// If your preview can change or rotate, take care of those events here.
// Make sure to stop the preview before resizing or reformatting it.
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)
Log.d("MotionDetector", "Error starting camera preview: " + e.getMessage());
@Override
public boolean onTouchEvent(MotionEvent event)
Toast.makeText(context, "Picture taken", Toast.LENGTH_SHORT).show();
//System.gc(); tried this because it was suggested in a *** question but it didn't help.
mCamera.takePicture(null, mPicture, mPicture);
return true; //processed
private Camera.PictureCallback mPicture = new Camera.PictureCallback()
@Override
public void onPictureTaken(byte[] data, Camera camera)
File pictureFile = getOutputMediaFile();
if (pictureFile == null)
return;
try
FileOutputStream fos = new FileOutputStream(pictureFile);
fos.write(data);
fos.close();
catch (FileNotFoundException e)
Log.d("MotionDetector", "File not found: " + e.getMessage());
catch (IOException e)
Log.d("MotionDetector", "Error accessing file: " + e.getMessage());
;
private static File getOutputMediaFile()
File mediaStorageDir = new File(Environment.getExternalStorageDirectory(), "motiondetect");
if (!mediaStorageDir.exists())
if (!mediaStorageDir.mkdirs())
Log.d("MyCameraApp", "failed to create directory");
return null;
// Create a media file name
String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date());
File mediaFile;
mediaFile = new File(mediaStorageDir, timeStamp + ".jpg");
return mediaFile;
使用的权限和功能:
<uses-permission android:name="android.permission.CAMERA"/>
<uses-feature android:name="android.hardware.camera"/>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-feature android:name="android.hardware.camera.autofocus" />
<uses-feature android:name="android.hardware.camera.flash" />
我不知道为什么会发生崩溃。许多其他主题建议先调用 Camera.startPreview。我正在这样做,但它并没有解决问题。
拍照前的LogCat:
01-05 21:45:57.667: WARN/ActivityManager(754): No content provider found for permission revoke: file:///data/local/tmp/com.test.MotionDetector
01-05 21:45:57.667: WARN/ActivityManager(754): No content provider found for permission revoke: file:///data/local/tmp/com.test.MotionDetector
01-05 21:45:57.687: INFO/ActivityManager(754): Force stopping com.test.MotionDetector appid=10103 user=-1: uninstall pkg
01-05 21:45:57.687: INFO/ActivityManager(754): Killing 4264:com.test.MotionDetector/u0a103 (adj 7): stop com.test.MotionDetector
01-05 21:45:57.687: INFO/ActivityManager(754): Force finishing activity ActivityRecord437a6678 u0 com.test.MotionDetector/.MotionDetectActivity t144
01-05 21:45:57.697: WARN/InputDispatcher(754): channel '42adff40 com.test.MotionDetector/com.test.MotionDetector.MotionDetectActivity (server)' ~ Consumer closed input channel or an error occurred. events=0x9
01-05 21:45:57.697: ERROR/InputDispatcher(754): channel '42adff40 com.test.MotionDetector/com.test.MotionDetector.MotionDetectActivity (server)' ~ Channel is unrecoverably broken and will be disposed!
01-05 21:45:57.697: WARN/InputDispatcher(754): Attempted to unregister already unregistered input channel '42adff40 com.test.MotionDetector/com.test.MotionDetector.MotionDetectActivity (server)'
01-05 21:45:57.697: INFO/WindowState(754): WIN DEATH: Window42adff40 u0 com.test.MotionDetector/com.test.MotionDetector.MotionDetectActivity
01-05 21:45:57.757: INFO/PackageManager(754): Running dexopt on: com.test.MotionDetector
01-05 21:45:57.757: INFO/PackageManager(754): Package com.test.MotionDetector codePath changed from /data/app/com.test.MotionDetector-1.apk to /data/app/com.test.MotionDetector-2.apk; Retaining data and using new
01-05 21:45:57.807: INFO/ActivityManager(754): Force stopping com.test.MotionDetector appid=10103 user=-1: update pkg
01-05 21:45:57.807: WARN/PackageManager(754): Code path for pkg : com.test.MotionDetector changing from /data/app/com.test.MotionDetector-1.apk to /data/app/com.test.MotionDetector-2.apk
01-05 21:45:57.807: WARN/PackageManager(754): Resource path for pkg : com.test.MotionDetector changing from /data/app/com.test.MotionDetector-1.apk to /data/app/com.test.MotionDetector-2.apk
01-05 21:45:57.937: INFO/ActivityManager(754): Force stopping com.test.MotionDetector appid=10103 user=0: pkg removed
01-05 21:45:57.987: DEBUG/BackupManagerService(754): Received broadcast Intent act=android.intent.action.PACKAGE_REMOVED dat=package:com.test.MotionDetector flg=0x4000010 (has extras)
01-05 21:45:58.047: DEBUG/BackupManagerService(754): Received broadcast Intent act=android.intent.action.PACKAGE_ADDED dat=package:com.test.MotionDetector flg=0x4000010 (has extras)
01-05 21:45:58.567: INFO/Icing.InternalIcingCorporaProvider(12750): Updating corpora: A: com.test.MotionDetector, C: MAYBE
01-05 21:45:58.647: DEBUG/PackageAddedReceiver(1086): package added com.test.MotionDetector
01-05 21:45:58.737: INFO/ActivityManager(754): START u0 flg=0x10000000 cmp=com.test.MotionDetector/.MotionDetectActivity from pid 4578
01-05 21:45:58.777: INFO/ActivityManager(754): Start proc com.test.MotionDetector for activity com.test.MotionDetector/.MotionDetectActivity: pid=4630 uid=10103 gids=50103, 1028, 1015
01-05 21:45:59.627: INFO/ActivityManager(754): Displayed com.test.MotionDetector/.MotionDetectActivity: +861ms (total +972ms)
01-05 21:45:59.657: INFO/WindowManager(754): Screen frozen for +869ms due to Window43cb77a8 u0 com.test.MotionDetector/com.test.MotionDetector.MotionDetectActivity
【问题讨论】:
清单文件中缺少权限? 崩溃前 logcat 中显示了什么? @FredGrott:查看问题的变化 【参考方案1】:假设你想保存 jpeg,你不需要原始回调,所以 更改对 takePicture() 的调用:
mCamera.takePicture(null, mPicture, mPicture);
到
mCamera.takePicture(null, null, mPicture);
在您的 onTouchEvent() 中。这将使用 jpeg 图片回调。
调用 takePicture() 也会导致预览停止,因此如果您想拍摄更多照片或重新开始预览,您可能需要在 onPictureTaken() 回调中再次调用 startPreview()。
此外,在您的 onTouchEvent() 中,您可能会收到多个事件,因此请筛选出适合您的事件:
@Override
public boolean onTouchEvent(MotionEvent event)
Toast.makeText(context, "Picture taken", Toast.LENGTH_SHORT).show();
//System.gc(); tried this because it was suggested in a *** question but it didn't help.
switch(event.getAction())
case MotionEvent.ACTION_DOWN:
// A pressed gesture has started, the motion contains the initial starting location
break;
case MotionEvent.ACTION_UP:
// A pressed gesture has finished, the motion contains the final release location
// as well as any intermediate points since the last down or move event.
mCamera.takePicture(null, mPicture, mPicture);
break;
default:
break;
return true; //processed
如果将 takePicture() 放在 ACTION_DOWN 中,只要你触摸屏幕就会调用它,而在 ACTION_UP 中,它会在你移开手指时调用。看看哪一个适合你。
【讨论】:
谢谢,问题是 ontouchEvent 中有多个事件。 @Melquiades 请检查我的问题:***.com/questions/21723557/…以上是关于安卓:java.lang.RuntimeException:拍照失败的主要内容,如果未能解决你的问题,请参考以下文章
初始化 Visualizer 时的 Android 错误代码 -3
Cause: java.sql.SQLException: No operations allowed after statement closed.
Spark Standalone + Zeppelin + Docker:如何设置 SPARK_HOME
JBoss - 如何在 jboss-deployment-structure 中排除 javax.validation?
win系统执行spark-sql报错:java.io.IOException: (null) entry in command string: null ls -F C: mphive
win系统执行spark-sql报错:java.io.IOException: (null) entry in command string: null ls -F C: mphive