我正在尝试使用以下代码将相机预览绘制到SurfaceHolder上:
@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();
}
然而,当我在模拟器或我的实际手机上运行应用程序时,我多次收到错误“Overlay create failed - retrying”,然后是“Overlay Creation Failed!”。然后我得到一个RuntimeException,声明“startPreview失败”。
我已经阅读了示例代码以及此处的许多相关问题,但没有运气。我还检查了权限,我认为这是正确的。 有什么想法吗?
提前致谢。
答案 0 :(得分:8)
设置SurfaceHolder时,请尝试将类型设置为SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS:
SurfaceHolder holder = surfaceView.getHolder();
holder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
surfaceView是SurfaceView的一个实例,它在我的布局中声明。
答案 1 :(得分:1)
我对Android编程很陌生,所以我不能100%肯定你的问题的答案。但是,我最近实现了类似的东西,如果使用setParameters(...)方法未正确设置预览大小,则在调用startPreview()时出现错误。也许这个问题是相关的。
这是目前为我工作的代码。这个课程是从我在网上找到的一个例子中提取的,虽然我不记得在哪里。
编辑:找到我从中提取的原始来源: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();
}
}
答案 2 :(得分:1)
好吧..试试这个...相机应用程序中的整个代码
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;
}
}
我希望这肯定会有用