我已经实现了一个显示相机预览的活动,它工作正常。最初在活动开始时我用前置摄像头开始活动。该应用程序工作正常,但现在我正在尝试实现按钮切换相机的飞行。我的意思是它不应该重新启动整个活动,而是将摄像机从前向后切换,反之亦然。但是我遇到了以下问题:
我的问题是
到目前为止我做了什么
这是我切换相机的方式:
public static Camera getCameraInstance2(Camera camera) {
if (camera != null) {
camera.stopPreview();
camera.release();
camera = null;
}
//swap the id of the camera to be used
if (currentCameraId == Camera.CameraInfo.CAMERA_FACING_BACK) {
currentCameraId = Camera.CameraInfo.CAMERA_FACING_FRONT;
} else {
currentCameraId = Camera.CameraInfo.CAMERA_FACING_BACK;
}
try {
camera = Camera.open(currentCameraId);
camera.startPreview();
} catch (Exception e) {
e.printStackTrace();
}
return camera;
}
它正在打开相机,但没有显示其预览。
这是我的Surfaceview类
public class CameraPreview extends SurfaceView implements SurfaceHolder.Callback {
private Camera camera;
public static SurfaceHolder holder;
private Activity activity;
public CameraPreview(Context context, AttributeSet attrs, Activity activity) {
super(context, attrs);
}
public CameraPreview(Context context, AttributeSet attrs) {
super(context, attrs);
}
public CameraPreview(Context context) {
super(context);
}
public void init(Camera camera,Activity activity) {
this.camera = camera;
this.activity = activity;
initSurfaceHolder();
}
@SuppressWarnings("deprecation") // needed for < 3.0
private void initSurfaceHolder() {
holder = getHolder();
holder.addCallback(this);
holder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
}
@Override
public void surfaceCreated(SurfaceHolder holder) {
initCamera(holder);
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
}
private void initCamera(SurfaceHolder holder) {
try {
Camera.Parameters param;
param = camera.getParameters();
Camera.Size bestSize = null;
List<Camera.Size> sizeList = camera.getParameters().getSupportedPreviewSizes();
bestSize = sizeList.get(0);
for(int i = 1; i < sizeList.size(); i++){
if((sizeList.get(i).width * sizeList.get(i).height) > (bestSize.width * bestSize.height)){
bestSize = sizeList.get(i);
}
}
List<Integer> supportedPreviewFormats = param.getSupportedPreviewFormats();
Iterator<Integer> supportedPreviewFormatsIterator = supportedPreviewFormats.iterator();
while(supportedPreviewFormatsIterator.hasNext()){
Integer previewFormat =supportedPreviewFormatsIterator.next();
if (previewFormat == ImageFormat.YV12) {
param.setPreviewFormat(previewFormat);
}
}
param.setPreviewSize(bestSize.width, bestSize.height);
Log.v("Best Preview Size"+bestSize.width+":/::/:"+bestSize.height);
param.setPictureSize(bestSize.width, bestSize.height);
camera.setParameters(param);
requestLayout();
camera.setPreviewDisplay(holder);
camera.startPreview();
} catch (Exception e) {
Log.d("Error setting camera preview", e);
}
}
@Override
public void surfaceChanged(SurfaceHolder mHolder, int format, int width, int height) {
//new work around
Camera.Parameters param;
param = camera.getParameters();
Camera.Size bestSize = null;
List<Camera.Size> sizeList = camera.getParameters().getSupportedPreviewSizes();
bestSize = sizeList.get(0);
for(int i = 1; i < sizeList.size(); i++){
if((sizeList.get(i).width * sizeList.get(i).height) > (bestSize.width * bestSize.height)){
bestSize = sizeList.get(i);
}
}
List<Integer> supportedPreviewFormats = param.getSupportedPreviewFormats();
Iterator<Integer> supportedPreviewFormatsIterator = supportedPreviewFormats.iterator();
while(supportedPreviewFormatsIterator.hasNext()){
Integer previewFormat =supportedPreviewFormatsIterator.next();
if (previewFormat == ImageFormat.YV12) {
param.setPreviewFormat(previewFormat);
}
}
param.setPreviewSize(bestSize.width, bestSize.height);
param.setPictureSize(bestSize.width, bestSize.height);
camera.setParameters(param);
Display display = ((WindowManager)activity.getSystemService(Context.WINDOW_SERVICE)).getDefaultDisplay();
if(display.getRotation() == Surface.ROTATION_0) {
camera.setDisplayOrientation(90);
param.setPreviewSize(bestSize.width, bestSize.height);
} else if(display.getRotation() == Surface.ROTATION_270) {
camera.setDisplayOrientation(180);
param.setPreviewSize(bestSize.width, bestSize.height);
}
requestLayout();
try {
camera.setPreviewDisplay(holder);
} catch (IOException e) {
e.printStackTrace();
}
camera.startPreview();
}// end surfaceChanged
@Override
public void surfaceDestroyed(SurfaceHolder holder) {
Log.e("TABACT"+"surfaceDestroyed()");
camera.stopPreview();
camera.setPreviewCallback(null);
camera.release();
camera = null;
this.getHolder().removeCallback(this);
// camera.release();
// camera.stopPreview();
}
public static Camera.Size getOptimalPreviewSize(List<Camera.Size> sizes, int w, int h) {
final double ASPECT_TOLERANCE = 0.1;
double targetRatio=(double)h / w;
if (sizes == null) return null;
Camera.Size optimalSize = null;
double minDiff = Double.MAX_VALUE;
int targetHeight = h;
for (Camera.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);
}
}
if (optimalSize == null) {
minDiff = Double.MAX_VALUE;
for (Camera.Size size : sizes) {
if (Math.abs(size.height - targetHeight) < minDiff) {
optimalSize = size;
minDiff = Math.abs(size.height - targetHeight);
}
}
}
return optimalSize;
}
我添加了名为“CameraPreview”的表面预览类。
EDIT3
我已经检查了一件事,那就是当我写信获取相机实例并开始预览时,它的起始相机成功了。我的意思是第一次当Activity恢复它的启动前置摄像头,当它恢复第二次启动后置摄像头时,每一件事都很好。我正在使用上面分享的代码切换相机。 现在的问题是,当我从活动按钮尝试此代码时预览卡住了,而相机在最后一个相机预览的预览背景中切换。
因此,如何在切换后删除最后一个摄像头预览,并在活动中通过新打开的摄像头开始新预览。
**我在想什么**
当用户点击翻盖相机按钮时,我应该显示对话框,其中有一个按钮可以切换相机,这会将活动置于暂停状态,点击是按钮只需关闭将恢复活动的对话框,结果它将显示切换摄像头的预览。
上层方法可能有用,但这不是一个好方法。但可能是什么解决方案。请与我分享。
答案 0 :(得分:0)
您需要从根布局中删除以前连接的CameraPreview,然后将此CameraPreview添加到已更改的摄像头。 举例来说,我使用FrameLayout来显示CameraPreview,然后如果我希望从前到后更改相机预览,反之亦然,我将删除附加到FrameLayout的视图(layout.removeAllViews()),然后添加CameraPreview改变了cameraId。
答案 1 :(得分:-1)
根据答案:Android: Switch camera when button clicked我让这段代码对我有用:
private void switchCamera() {
if (mCamera != null) {
mCamera.setPreviewCallback(null);
mCamera.stopPreview();
mCamera.release();
mCamera = null;
try {
if (mCameraFacing == Camera.CameraInfo.CAMERA_FACING_FRONT) {
mCameraFacing = Camera.CameraInfo.CAMERA_FACING_BACK;
}
else {
mCameraFacing = Camera.CameraInfo.CAMERA_FACING_FRONT;
}
mCamera = Camera.open(mCameraFacing);
mCamera.setPreviewDisplay(mPreview.getHolder());
mCamera.startPreview();
}
catch (final Exception e) {
e.printStackTrace();
}
}
}
我这里的关键是stopPreview()
,只需重置Camera
并开始新的startPreview()
。