Android 相机 takePicture() 失败
Posted
技术标签:
【中文标题】Android 相机 takePicture() 失败【英文标题】:Android Camera takePicture() failed 【发布时间】:2016-04-05 19:26:01 【问题描述】:我一直在尝试使用相机在 android 中使用 Surface Preview 拍照。 Surface Preview 跨越布局中的整个屏幕。
每当我调用 takePicture 时,它都会失败并说我没有启用预览。
这里是活动变量、图片方法和相机拍照代码(在 onResume() 中):
public class FawkesRCActivity extends Activity implements SurfaceHolder.Callback
SurfaceView mSurfaceView;
SurfaceHolder mHolder;
public Camera mCamera;
...
Camera.PictureCallback camHolla = new Camera.PictureCallback()
public void onPictureTaken(byte[] data, Camera camera)
String photoFile = "F_Auton.jpg";
File sdDir = Environment
.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES);
String filename =sdDir + File.separator + photoFile;
File pictureFile = new File(filename);
try
FileOutputStream fos = new FileOutputStream(pictureFile);
fos.write(data);
fos.close();
catch (Exception e)
Log.d("Errored:", e.getMessage());
;
public void setCamera(Camera camera)
if (mCamera == camera) return;
stopPreviewAndFreeCamera();
mCamera = camera;
if (mCamera != null)
List<Camera.Size> localSizes = mCamera.getParameters().getSupportedPreviewSizes();
try
mCamera.setPreviewDisplay(mHolder);
catch (IOException e)
e.printStackTrace();
// Important: Call startPreview() to start updating the preview
// surface. Preview must be started before you can take a picture.
mCamera.startPreview();
@Override
public void surfaceCreated(SurfaceHolder surfaceHolder)
public void surfaceChanged(SurfaceHolder holder, int format, int w, int h)
mCamera.startPreview();
public void surfaceDestroyed(SurfaceHolder holder)
// Surface will be destroyed when we return, so stop the preview.
if (mCamera != null)
// Call stopPreview() to stop updating the preview surface.
mCamera.stopPreview();
/**
* When this function returns, mCamera will be null.
*/
private void stopPreviewAndFreeCamera()
if (mCamera != null)
// Call stopPreview() to stop updating the preview surface.
mCamera.stopPreview();
// Important: Call release() to release the camera for use by other
// applications. Applications should release the camera immediately
// during onPause() and re-open() it during onResume()).
mCamera.release();
mCamera = null;
@Override
protected void onResume()
FawkesRCActivity.this.runOnUiThread(new Runnable()
public void run()
mSurfaceView = (SurfaceView) findViewById(R.id.cameraPreview);
// Install a SurfaceHolder.Callback so we get notified when the
// underlying surface is created and destroyed.
mHolder = mSurfaceView.getHolder();
mHolder.addCallback(FawkesRCActivity.this);
mHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
// Search for the front facing camera
int numberOfCameras = Camera.getNumberOfCameras();
int camId=0;
for (int i = 0; i < numberOfCameras; i++)
Camera.CameraInfo info = new Camera.CameraInfo();
Camera.getCameraInfo(i, info);
if (info.facing == Camera.CameraInfo.CAMERA_FACING_BACK)
camId=i;
if (safeCameraOpen(camId))Log.e("Camera","All Good"); else Log.e("Camera","Errored");
try
SurfaceTexture surfaceTexture = new SurfaceTexture(0);
mCamera.setPreviewTexture(surfaceTexture);
// mCamera.startPreview();
catch(Exception e)
e.printStackTrace();
try
mCamera.takePicture(null, null, null, camHolla);
catch(Exception e)
e.printStackTrace();
);
super.onResume();
private boolean safeCameraOpen(int id)
boolean qOpened = false;
try
releaseCameraAndPreview();
mCamera = Camera.open(id);
qOpened = (mCamera != null);
catch (Exception e)
Log.e(getString(R.string.app_name), "failed to open Camera");
e.printStackTrace();
return qOpened;
private void releaseCameraAndPreview()
setCamera(null);
if (mCamera != null)
mCamera.release();
mCamera = null;
这是错误:
12-31 20:00:15.407 3244-5501/? E/Camera2Client﹕ takePicture: Camera 0: Cannot take picture without preview enabled
12-31 20:00:15.408 6988-6988/? W/System.err﹕ java.lang.RuntimeException: takePicture failed
12-31 20:00:15.408 6988-6988/? W/System.err﹕ at android.hardware.Camera.native_takePicture(Native Method)
12-31 20:00:15.408 6988-6988/? W/System.err﹕ at android.hardware.Camera.takePicture(Camera.java:1434)
12-31 20:00:15.408 6988-6988/? W/System.err﹕ at org.fawkes.fawkesrc.FawkesRCActivity$5.run(FawkesRCActivity.java:327)
12-31 20:00:15.408 6988-6988/? W/System.err﹕ at android.app.Activity.runOnUiThread(Activity.java:5524)
12-31 20:00:15.408 6988-6988/? W/System.err﹕ at org.fawkes.fawkesrc.FawkesRCActivity.onResume(FawkesRCActivity.java:298)
12-31 20:00:15.408 6988-6988/? W/System.err﹕ at android.app.Instrumentation.callActivityOnResume(Instrumentation.java:1258)
12-31 20:00:15.408 6988-6988/? W/System.err﹕ at android.app.Activity.performResume(Activity.java:6327)
12-31 20:00:15.408 6988-6988/? W/System.err﹕ at android.app.ActivityThread.performResumeActivity(ActivityThread.java:3092)
12-31 20:00:15.408 6988-6988/? W/System.err﹕ at android.app.ActivityThread.handleResumeActivity(ActivityThread.java:3134)
12-31 20:00:15.408 6988-6988/? W/System.err﹕ at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2481)
12-31 20:00:15.408 6988-6988/? W/System.err﹕ at android.app.ActivityThread.-wrap11(ActivityThread.java)
12-31 20:00:15.408 6988-6988/? W/System.err﹕ at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1344)
12-31 20:00:15.409 6988-6988/? W/System.err﹕ at android.os.Handler.dispatchMessage(Handler.java:102)
12-31 20:00:15.409 6988-6988/? W/System.err﹕ at android.os.Looper.loop(Looper.java:148)
12-31 20:00:15.409 6988-6988/? W/System.err﹕ at android.app.ActivityThread.main(ActivityThread.java:5417)
12-31 20:00:15.409 6988-6988/? W/System.err﹕ at java.lang.reflect.Method.invoke(Native Method)
12-31 20:00:15.409 6988-6988/? W/System.err﹕ at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:726)
12-31 20:00:15.409 6988-6988/? W/System.err﹕ at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:616)
在论坛搜索了几个小时后,我完全迷失了方向,我们将不胜感激。
【问题讨论】:
【参考方案1】:相机操作不是即时的,而且通常不是同步的。一些设备需要在 startPreview() 和 takePicture() 之间有很大的延迟,例如在 OnePlus One 上,您至少需要 100 毫秒。
对代码的最小修复可能是
try
SurfaceTexture surfaceTexture = new SurfaceTexture(0);
mCamera.setPreviewTexture(surfaceTexture);
// mCamera.startPreview();
catch(Exception e)
e.printStackTrace();
mSurfaceView.postDelayed(new Runnable()
@Override
public void run()
try
mCamera.takePicture(null, null, null, camHolla);
catch(Exception e)
e.printStackTrace();
, 100);
super.onResume();
【讨论】:
【参考方案2】:我不是专家,但我认为您在拍照之前没有致电mCamera.startPreview()
。您可以尝试在此之前调用它。
您可以看看这个CameraFragment Sample 作为开始相机预览等的参考。
【讨论】:
以上是关于Android 相机 takePicture() 失败的主要内容,如果未能解决你的问题,请参考以下文章
mCamera.takePicture(null, null, mPicture) 不起作用
Cordova 和 proguard:takePicture 上的相机插件 NPE