启动相机预览时,叠加创建失败

时间:2011-07-07 14:35:50

标签: android

我正在尝试使用以下代码将相机预览绘制到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失败”。

我已经阅读了示例代码以及此处的许多相关问题,但没有运气。我还检查了权限,我认为这是正确的。 有什么想法吗?

提前致谢。

3 个答案:

答案 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;
    }

}

我希望这肯定会有用