Overlay creation fails when starting camera preview
I'm trying to draw the camera preview onto a SurfaceHolder with this code:
@Override
public void onCreate(SurfaceHolder surfaceHolder) {
super.onCreate(surfaceHolder);
Log.d(TAG, "Releasing camera first, just to make sure");
releaseCamera();
Log.d(TAG, "Opening Camera object.");
mCamera = Camera.open();
if (mCamera == null) {
Log.d(TAG, "Camera is null.");
}
}
@Override
public void onSurfaceCreated(SurfaceHolder holder) {
super.onSurfaceCreated(holder);
Log.d(TAG, "Surface created.");
try {
if (holder == null) {
Log.d(TAG, "SurfaceHolder is empty.");
}
Log.d(TAG, "Setting preview display.");
mCamera.setPreviewDisplay(holder);
} catch (IOException e) {
Log.d(TAG, "IOException on setPreviewDisplay.");
releaseCamera();
}
}
@Override
public void onSurfaceChanged(SurfaceHolder holder, int format, int width, int height) {
super.onSurfaceChanged(holder, format, width, height);
Log.d(TAG, "Surface changed.");
Log.d(TAG, "Starting preview.");
mCamera.startPreview();
}
However, when I run the app, either on the emulator or my actual phone, I get the error "Overlay create failed - retrying" multiple times, followed by "Overlay Creation Failed!". I then get a RuntimeException, stating that "startPreview failed".
开发者_JS百科I've read through the sample code, as well as a lot of the related questions here, but no luck. I have also checked the permissions, which I think are correct. Any ideas?
Thanks in advance.
When setting up your SurfaceHolder try setting the type to SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS:
SurfaceHolder holder = surfaceView.getHolder();
holder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
surfaceView is an instance of SurfaceView which is declared in my layout.
ok.. try this... whole code in your camera App
public class CameraImage extends Activity implements SurfaceHolder.Callback,
OnClickListener {
static final int FOTO = 0;
Camera camera;
boolean previewRunning = false;
private final Context mContext = this;
@Override
public void onCreate(Bundle icicle) {
super.onCreate(icicle);
getWindow().setFormat(PixelFormat.TRANSLUCENT);
requestWindowFeature(Window.FEATURE_NO_TITLE);
getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,
WindowManager.LayoutParams.FLAG_FULLSCREEN);
setContentView(R.layout.camera_image);
sv = (SurfaceView) findViewById(R.id.camera);
sv.setOnClickListener(this);
sh = sv.getHolder();
sh.addCallback(this);
sh.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
}
@Override
protected void onRestoreInstanceState(Bundle savedInstanceState) {
super.onRestoreInstanceState(savedInstanceState);
}
Camera.PictureCallback mPictureCallback = new Camera.PictureCallback() {
public void onPictureTaken(byte[] imageData, Camera c) {
if (imageData != null) {
Intent mIntent = new Intent();
StoreByteImage(mContext, imageData, 50, "ImageName");
camera.startPreview();
setResult(FOTO, mIntent);
finish();
}
}
};
@Override
protected void onResume() {
super.onResume();
}
@Override
protected void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
}
@Override
protected void onStop() {
super.onStop();
}
public void surfaceCreated(SurfaceHolder holder) {
camera = Camera.open();
}
public void surfaceChanged(SurfaceHolder holder, int format, int w, int h) {
// XXX stopPreview() will crash if preview is not running
if (previewRunning) {
camera.stopPreview();
}
Camera.Parameters p = camera.getParameters();
p.setPreviewSize(w, h);
camera.setParameters(p);
try {
camera.setPreviewDisplay(holder);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
camera.startPreview();
previewRunning = true;
}
public void surfaceDestroyed(SurfaceHolder holder) {
camera.stopPreview();
previewRunning = false;
camera.release();
}
private SurfaceView sv;
private SurfaceHolder sh;
public void onClick(View arg0) {
camera.takePicture(null, mPictureCallback, mPictureCallback);
}
public static boolean StoreByteImage(Context mContext, byte[] imageData,
int quality, String expName) {
File sdImageMainDirectory = new File("/sdcard");
FileOutputStream fileOutputStream = null;
try {
long name = new Date().getTime();
BitmapFactory.Options options=new BitmapFactory.Options();
options.inSampleSize = 1;
Bitmap myImage = BitmapFactory.decodeByteArray(imageData, 0,
imageData.length,options);
fileOutputStream = new FileOutputStream(sdImageMainDirectory.toString() +"/"+Long.toString(name)+".jpg");
BufferedOutputStream bos = new BufferedOutputStream(fileOutputStream);
myImage.compress(CompressFormat.JPEG, quality, bos);
DataModel dbModel = new DataModel(mContext);
Calendar cal = Calendar.getInstance();
dbModel.insertMultimedia(sdImageMainDirectory.toString() +"/"+Long.toString(name)+".jpg", Long.toString(name), cal);
bos.flush();
bos.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
return true;
}
}
I hope this will certainly work
I'm pretty new to Android programming, so I'm not 100% sure on the answer to your question. However, I recently implemented something similar, and I was getting errors when I was calling startPreview() if the preview size was not set correctly using the setParameters(...) method. Perhaps this problem is related.
Here is the code that's working for me currently. This class was pulled from an example I found online, although I can't recall where.
EDIT: Found the original source I pulled this from: CameraPreview API Demo
// A simple wrapper around a Camera and a SurfaceView that renders a
// centered preview of the Camera to the surface. We need to center the
// SurfaceView because not all devices have cameras that support preview
// sizes at the same aspect ratio as the device's display.
class Preview extends ViewGroup implements SurfaceHolder.Callback {
private final String TAG = "Preview";
SurfaceView mSurfaceView;
SurfaceHolder mHolder;
Size mPreviewSize;
List<Size> mSupportedPreviewSizes;
Camera mCamera;
Preview(Context context) {
super(context);
mSurfaceView = new SurfaceView(context);
addView(mSurfaceView);
// Install a SurfaceHolder.Callback so we get notified when the
// underlying surface is created and destroyed.
mHolder = mSurfaceView.getHolder();
mHolder.addCallback(this);
mHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
}
public void setCamera(Camera camera) {
mCamera = camera;
if (mCamera != null) {
mSupportedPreviewSizes =
mCamera.getParameters().getSupportedPreviewSizes();
requestLayout();
}
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
// We purposely disregard child measurements because act as a
// wrapper to a SurfaceView that centers the camera preview instead
// of stretching it.
final int width = resolveSize(getSuggestedMinimumWidth(),
widthMeasureSpec);
final int height = resolveSize(getSuggestedMinimumHeight(),
heightMeasureSpec);
setMeasuredDimension(width, height);
if (mSupportedPreviewSizes != null) {
mPreviewSize = getOptimalPreviewSize(mSupportedPreviewSizes,
width, height);
}
}
@Override
protected void onLayout(boolean changed, int l, int t, int r, int b) {
if (changed && getChildCount() > 0) {
final View child = getChildAt(0);
final int width = r - l;
final int height = b - t;
int previewWidth = width;
int previewHeight = height;
if (mPreviewSize != null) {
previewWidth = mPreviewSize.width;
previewHeight = mPreviewSize.height;
}
// Center the child SurfaceView within the parent.
if (width * previewHeight > height * previewWidth) {
final int scaledChildWidth = previewWidth * height / previewHeight;
child.layout((width - scaledChildWidth) / 2, 0,
(width + scaledChildWidth) / 2, height);
} else {
final int scaledChildHeight = previewHeight * width / previewWidth;
child.layout(0, (height - scaledChildHeight) / 2,
width, (height + scaledChildHeight) / 2);
}
}
}
public void surfaceCreated(SurfaceHolder holder) {
// The Surface has been created, acquire the camera and tell it where
// to draw.
try {
if (mCamera != null) {
mCamera.setPreviewDisplay(holder);
}
} catch (IOException exception) {
Log.e(TAG, "IOException caused by setPreviewDisplay()", exception);
}
}
public void surfaceDestroyed(SurfaceHolder holder) {
// Surface will be destroyed when we return, so stop the preview.
if (mCamera != null) {
mCamera.stopPreview();
}
}
private Size getOptimalPreviewSize(List<Size> sizes, int w, int h) {
final double ASPECT_TOLERANCE = 0.1;
double targetRatio = (double) w / h;
if (sizes == null) return null;
Size optimalSize = null;
double minDiff = Double.MAX_VALUE;
int targetHeight = h;
// Try to find an size match aspect ratio and size
for (Size size : sizes) {
double ratio = (double) size.width / size.height;
if (Math.abs(ratio - targetRatio) > ASPECT_TOLERANCE) continue;
if (Math.abs(size.height - targetHeight) < minDiff) {
optimalSize = size;
minDiff = Math.abs(size.height - targetHeight);
}
}
// Cannot find the one match the aspect ratio, ignore the requirement
if (optimalSize == null) {
minDiff = Double.MAX_VALUE;
for (Size size : sizes) {
if (Math.abs(size.height - targetHeight) < minDiff) {
optimalSize = size;
minDiff = Math.abs(size.height - targetHeight);
}
}
}
return optimalSize;
}
public void surfaceChanged(SurfaceHolder holder, int format, int w, int h) {
// Now that the size is known, set up the camera parameters and begin
// the preview.
Camera.Parameters parameters = mCamera.getParameters();
parameters.setPreviewSize(mPreviewSize.width, mPreviewSize.height);
requestLayout();
mCamera.setParameters(parameters);
mCamera.startPreview();
}
}
精彩评论