我正在创建一个自定义相机应用。我面临的问题是当我在前后摄像头之间切换时,摄像头预览会冻结。通过调用
启动前置或后置摄像头的活动时boolean opened = safeCameraOpenInView(view, Camera.CameraInfo.CAMERA_FACING_BACK)
在片段的OnCreateView方法中,两个摄像头将按预期在启动时显示。只要我在开关按钮的点击监听器中调用相同的方法,摄像机就会立即冻结。
这是一个新的实现,我尝试了所有代码都在同一个片段中,而不是基于这里的问题的自定义类:Custom class camera live preview freezes on camera switch但结果完全相同。我很确定我需要用表面视图做一些事情来将它绑定到新相机,但我不知道如何做到这一点。有人有指示吗?
我的活动:
public class Camera2ActivityFragment extends Fragment {
// Native camera.
private Camera mCamera;
// View to display the camera output.
private CameraPreview mPreview;
// Reference to the containing view.
private View mCameraView;
/**
* Default empty constructor.
*/
public Camera2ActivityFragment(){
super();
}
/**
* Static factory method
* @param sectionNumber
* @return
*/
public static Camera2ActivityFragment newInstance(int sectionNumber) {
Camera2ActivityFragment fragment = new Camera2ActivityFragment();
//Bundle args = new Bundle();
//args.putInt(ARG_SECTION_NUMBER, sectionNumber);
//fragment.setArguments(args);
return fragment;
}
/**
* OnCreateView fragment override
* @param inflater
* @param container
* @param savedInstanceState
* @return
*/
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_camera2, container, false);
boolean opened = safeCameraOpenInView(view, Camera.CameraInfo.CAMERA_FACING_BACK);
if(opened == false){
Log.d("CameraGuide","Error, Camera failed to open");
return view;
}
// Trap the capture button.
Button captureButton = (Button) view.findViewById(R.id.btnCameraStart);
captureButton.setOnClickListener(
new View.OnClickListener() {
@Override
public void onClick(View v) {
// get an image from the camera
mCamera.takePicture(null, null, mPicture);
}
}
);
Button switchCameraButton = (Button) view.findViewById(R.id.btnSwitchCamera);
switchCameraButton.setOnClickListener(
new View.OnClickListener() {
@Override
public void onClick(View v) {
safeCameraOpenInView(getView(), Camera.CameraInfo.CAMERA_FACING_FRONT); //ISSUE OCCURS HERE!
}
}
);
return view;
}
/**
* Recommended "safe" way to open the camera.
* @param view
* @return
*/
private boolean safeCameraOpenInView(View view, int camID) {
boolean qOpened = false;
releaseCameraAndPreview();
//mCamera = getCameraInstance(Camera.CameraInfo.CAMERA_FACING_BACK);
mCamera = getCameraInstance(camID);
mCameraView = view;
qOpened = (mCamera != null);
if(qOpened == true){
mPreview = new CameraPreview(getActivity().getBaseContext(), mCamera,view);
FrameLayout preview = (FrameLayout) view.findViewById(R.id.camera_view);
preview.addView(mPreview);
mPreview.startCameraPreview();
}
return qOpened;
}
/**
* Safe method for getting a camera instance.
* @return
*/
public static Camera getCameraInstance(int camID){
Camera c = null;
try {
c = Camera.open(camID); // attempt to get a Camera instance
}
catch (Exception e){
e.printStackTrace();
}
return c; // returns null if camera is unavailable
}
@Override
public void onPause() {
super.onPause();
}
@Override
public void onDestroy() {
super.onDestroy();
releaseCameraAndPreview();
}
/**
* Clear any existing preview / camera.
*/
private void releaseCameraAndPreview() {
if (mCamera != null) {
mCamera.stopPreview();
mCamera.release();
mCamera = null;
}
if(mPreview != null){
mPreview.destroyDrawingCache();
mPreview.mCamera = null;
}
}
/**
* Surface on which the camera projects it's capture results. This is derived both from Google's docs and the
* excellent StackOverflow answer provided below.
*
* Reference / Credit: https://stackoverflow.com/questions/7942378/android-camera-will-not-work-startpreview-fails
*/
class CameraPreview extends SurfaceView implements SurfaceHolder.Callback {
// SurfaceHolder
private SurfaceHolder mHolder;
// Our Camera.
private Camera mCamera;
// Parent Context.
private Context mContext;
// Camera Sizing (For rotation, orientation changes)
private Camera.Size mPreviewSize;
// List of supported preview sizes
private List<Camera.Size> mSupportedPreviewSizes;
// Flash modes supported by this camera
private List<String> mSupportedFlashModes;
// View holding this camera.
private View mCameraView;
public CameraPreview(Context context, Camera camera, View cameraView) {
super(context);
// Capture the context
mCameraView = cameraView;
mContext = context;
setCamera(camera);
// Install a SurfaceHolder.Callback so we get notified when the
// underlying surface is created and destroyed.
mHolder = getHolder();
mHolder.addCallback(this);
mHolder.setKeepScreenOn(true);
// deprecated setting, but required on Android versions prior to 3.0
mHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
}
/**
* Begin the preview of the camera input.
*/
public void startCameraPreview()
{
try{
mCamera.setPreviewDisplay(mHolder);
mCamera.startPreview();
}
catch(Exception e){
e.printStackTrace();
}
}
/**
* Extract supported preview and flash modes from the camera.
* @param camera
*/
private void setCamera(Camera camera)
{
// Source: https://stackoverflow.com/questions/7942378/android-camera-will-not-work-startpreview-fails
mCamera = camera;
mSupportedPreviewSizes = mCamera.getParameters().getSupportedPreviewSizes();
mSupportedFlashModes = mCamera.getParameters().getSupportedFlashModes();
// Set the camera to Auto Flash mode.
if (mSupportedFlashModes != null && mSupportedFlashModes.contains(Camera.Parameters.FLASH_MODE_AUTO)){
Camera.Parameters parameters = mCamera.getParameters();
parameters.setFlashMode(Camera.Parameters.FLASH_MODE_AUTO);
parameters.setRotation(90);
//parameters.setPreviewSize(mPreviewSize.width, mPreviewSize.height);
mCamera.setParameters(parameters);
mCamera.setDisplayOrientation(90);
}
requestLayout();
}
/**
* The Surface has been created, now tell the camera where to draw the preview.
* @param holder
*/
public void surfaceCreated(SurfaceHolder holder) {
try {
mCamera.setPreviewDisplay(holder);
//mCam = Camera.open();
//mCam.setPreviewDisplay(holder);
} catch (IOException e) {
e.printStackTrace();
}
}
/**
* Dispose of the camera preview.
* @param holder
*/
public void surfaceDestroyed(SurfaceHolder holder) {
if (mCamera != null){
mCamera.stopPreview();
}
}
/**
* React to surface changed events
* @param holder
* @param format
* @param w
* @param h
*/
public void surfaceChanged(SurfaceHolder holder, int format, int w, int h) {
//Log.e(TAG, "surfaceChanged => w=" + w + ", h=" + h);
// If your preview can change or rotate, take care of those events here.
// Make sure to stop the preview before resizing or reformatting it.
if (mHolder.getSurface() == null){
// preview surface does not exist
return;
}
// stop preview before making changes
try {
mCamera.stopPreview();
//mCamera.release();
} catch (Exception e){
// ignore: tried to stop a non-existent preview
}
// set preview size and make any resize, rotate or reformatting changes here
// start preview with new settings
try {
Camera.Parameters parameters = mCamera.getParameters();
parameters.setPreviewSize(mPreviewSize.width, mPreviewSize.height);
parameters.setRotation(90);
parameters.setFocusMode(Camera.Parameters.FOCUS_MODE_CONTINUOUS_PICTURE);
mCamera.setParameters(parameters);
mCamera.setDisplayOrientation(90);
mCamera.setPreviewDisplay(mHolder);
mCamera.enableShutterSound(true);
mCamera.startPreview();
} catch (Exception e){
//Log.d(TAG, "Error starting camera preview: " + e.getMessage());
}
}
/**
* Calculate the measurements of the layout
* @param widthMeasureSpec
* @param heightMeasureSpec
*/
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec)
{
/*
// Source: https://stackoverflow.com/questions/7942378/android-camera-will-not-work-startpreview-fails
final int width = resolveSize(getSuggestedMinimumWidth(), widthMeasureSpec);
final int height = resolveSize(getSuggestedMinimumHeight(), heightMeasureSpec);
setMeasuredDimension(width, height);
if (mSupportedPreviewSizes != null){
mPreviewSize = getOptimalPreviewSize(mSupportedPreviewSizes, width, height);
}
*/
final int width = resolveSize(getSuggestedMinimumWidth(), widthMeasureSpec);
final int height = resolveSize(getSuggestedMinimumHeight(), heightMeasureSpec);
if (mSupportedPreviewSizes != null) {
mPreviewSize = getOptimalPreviewSize(mSupportedPreviewSizes, width, height);
}
float ratio;
if(mPreviewSize.height >= mPreviewSize.width)
ratio = (float) mPreviewSize.height / (float) mPreviewSize.width;
else
ratio = (float) mPreviewSize.width / (float) mPreviewSize.height;
// One of these methods should be used, second method squishes preview slightly
setMeasuredDimension(width, (int) (width * ratio));
// setMeasuredDimension((int) (width * ratio), height);
}
/**
* Update the layout based on rotation and orientation changes.
* @param changed
* @param left
* @param top
* @param right
* @param bottom
*/
@Override
protected void onLayout(boolean changed, int left, int top, int right, int bottom)
{
// Source: https://stackoverflow.com/questions/7942378/android-camera-will-not-work-startpreview-fails
if (changed) {
final int width = right - left;
final int height = bottom - top;
int previewWidth = width;
int previewHeight = height;
if (mPreviewSize != null){
Display display = ((WindowManager)mContext.getSystemService(Context.WINDOW_SERVICE)).getDefaultDisplay();
switch (display.getRotation())
{
case Surface.ROTATION_0:
previewWidth = mPreviewSize.height;
previewHeight = mPreviewSize.width;
mCamera.setDisplayOrientation(90);
break;
case Surface.ROTATION_90:
previewWidth = mPreviewSize.width;
previewHeight = mPreviewSize.height;
break;
case Surface.ROTATION_180:
previewWidth = mPreviewSize.height;
previewHeight = mPreviewSize.width;
break;
case Surface.ROTATION_270:
previewWidth = mPreviewSize.width;
previewHeight = mPreviewSize.height;
mCamera.setDisplayOrientation(180);
break;
}
}
final int scaledChildHeight = previewHeight * width / previewWidth;
mCameraView.layout(0, height - scaledChildHeight, width, height);
}
}
/**
*
* @param sizes
* @param width
* @param height
* @return
*/
private Camera.Size getOptimalPreviewSize(List<Camera.Size> sizes, int width, int height)
{
final double ASPECT_TOLERANCE = 0.1;
double targetRatio = (double) height / width;
if (sizes == null)
return null;
Camera.Size optimalSize = null;
double minDiff = Double.MAX_VALUE;
int targetHeight = height;
for (Camera.Size size : sizes) {
double ratio = (double) size.height / size.width;
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;
}
}
/**
* Picture Callback for handling a picture capture and saving it out to a file.
*/
private Camera.PictureCallback mPicture = new Camera.PictureCallback() {
@Override
public void onPictureTaken(byte[] data, Camera camera) {
File pictureFile = getOutputMediaFile();
if (pictureFile == null){
Toast.makeText(getActivity(), "Image retrieval failed.", Toast.LENGTH_SHORT)
.show();
return;
}
try {
FileOutputStream fos = new FileOutputStream(pictureFile);
fos.write(data);
fos.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
};
/**
* Used to return the camera File output.
* @return
*/
private File getOutputMediaFile(){
File mediaStorageDir = new File(Environment.getExternalStoragePublicDirectory(
Environment.DIRECTORY_PICTURES), "Pocket Booth");
if (! mediaStorageDir.exists()){
if (! mediaStorageDir.mkdirs()){
Log.d("Camera Guide", "Required media storage does not exist");
return null;
}
}
// Create a media file name
String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date());
File mediaFile;
mediaFile = new File(mediaStorageDir.getPath() + File.separator +
"IMG_"+ timeStamp + ".jpg");
//DialogHelper.showDialog( "Success!","Your picture has been saved!",getActivity());
return mediaFile;
}
}
答案 0 :(得分:4)
好吧,在这里,我将为您编写一个关于捕获的教程 通过启用相机的一些常见功能,使用Camera图像。
第1步:创建预览类
/**
* A basic Camera preview class
*/
public class CameraPreview extends SurfaceView implements SurfaceHolder.Callback {
private static final String TAG = "CameraPreview";
private SurfaceHolder mHolder;
private Camera mCamera;
public CameraPreview(Context context, Camera camera) {
super(context);
mCamera = camera;
// Install a SurfaceHolder.Callback so we get notified when the
// underlying surface is created and destroyed.
mHolder = getHolder();
mHolder.addCallback(this);
// deprecated setting, but required on Android versions prior to 3.0
mHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
}
public void surfaceCreated(SurfaceHolder holder) {
// The Surface has been created, now tell the camera where to draw the preview.
try {
mCamera.setPreviewDisplay(holder);
mCamera.startPreview();
} catch (IOException e) {
Log.d(TAG, "Error setting camera preview: " + e.getMessage());
}
}
public void surfaceDestroyed(SurfaceHolder holder) {
// empty. Take care of releasing the Camera preview in your activity.
}
public void surfaceChanged(SurfaceHolder holder, int format, int w, int h) {
// If your preview can change or rotate, take care of those events here.
// Make sure to stop the preview before resizing or reformatting it.
if (mHolder.getSurface() == null) {
// preview surface does not exist
return;
}
// stop preview before making changes
try {
mCamera.stopPreview();
} catch (Exception e) {
// ignore: tried to stop a non-existent preview
}
// set preview size and make any resize, rotate or
// reformatting changes here
// start preview with new settings
startPreview();
}
public void resetCamera(Camera camera) {
mCamera = camera;
}
public void startPreview() {
try {
mCamera.setPreviewDisplay(mHolder);
mCamera.startPreview();
} catch (Exception e) {
Log.d(TAG, "Error starting camera preview: " + e.getMessage());
}
}
}
第2步:使用FrameLayout
进行预览。
<FrameLayout
android:id="@+id/cameraPreview"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
第3步:获取camera
并发送到预览课程。您可能需要在通过相机之前设置所需的参数。
/**
* Create our Preview view and set it as the content of UI.
*/
private void initCameraPreview(final int cameraId, final boolean createPreview) {
mCamera = getCameraInstance(cameraId);
setupCameraParameters(cameraId);
if (createPreview) {
mPreview = new CameraPreview(this, mCamera);
mPreviewHolder.addView(mPreview);
}
mReadyToCapture = true;
}
/**
* A safe way to get an instance of the Camera object.
*/
private Camera getCameraInstance(int cameraId) {
Camera c = null;
try {
c = Camera.open(cameraId); // attempt to get a Camera instance
} catch (Exception e) {
e.printStackTrace();
// Camera is not available (in use or does not exist)
}
return c; // returns null if camera is unavailable
}
/**
* Measure and Setup the camera parameters.
*/
private void setupCameraParameters(int cameraId) {
boolean hasFlash;
Camera.Parameters parameters = mCamera.getParameters();
mPreviewSize = determineBestPreviewSize(parameters);
parameters.setPreviewSize(mPreviewSize.width, mPreviewSize.height);
Camera.Size bestPictureSize = determineBestPictureSize(parameters);
parameters.setPictureSize(bestPictureSize.width, bestPictureSize.height);
hasFlash = Util.hasSystemFeature(this, PackageManager.FEATURE_CAMERA_FLASH);
if (mCurrentCameraId == Camera.CameraInfo.CAMERA_FACING_FRONT) {
hasFlash = Util.hasFrontCameraFlash(parameters);
} else {
parameters.setFocusMode(Camera.Parameters.FOCUS_MODE_AUTO);
}
if (hasFlash)
parameters.setFlashMode(mFlashMode);
int[] orientations = Util.getCameraDisplayOrientation(this, cameraId);
mDisplayOrientation = orientations[0];
mLayoutOrientation = orientations[1];
mCamera.setDisplayOrientation(mDisplayOrientation);
mCamera.setParameters(parameters);
}
private Camera.Size determineBestPreviewSize(Camera.Parameters parameters) {
List<Camera.Size> sizes = parameters.getSupportedPreviewSizes();
return determineBestSize(sizes);
}
private Camera.Size determineBestPictureSize(Camera.Parameters parameters) {
List<Camera.Size> sizes = parameters.getSupportedPictureSizes();
return determineBestSize(sizes);
}
private Camera.Size determineBestSize(List<Camera.Size> sizes) {
Camera.Size bestSize = null;
for (Camera.Size currentSize : sizes) {
boolean isDesiredRatio = (currentSize.width / 4) == (currentSize.height / 3);
boolean isBetterSize = (bestSize == null || currentSize.width > bestSize.width);
boolean isInBounds = currentSize.width <= PICTURE_SIZE_MAX_WIDTH;
if (isDesiredRatio && isInBounds && isBetterSize) {
bestSize = currentSize;
}
}
if (bestSize == null) {
return sizes.get(0);
}
return bestSize;
}
步骤4:交换相机的写入方法
/**
* Swapping between system cameras
*/
private void swapCamera() {
if (!(Camera.getNumberOfCameras() > 1)) {
/* No front facing camera to switch.*/
return;
}
mReadyToCapture = false;
mCamera.stopPreview();
releaseCamera(false);
if (mCurrentCameraId == Camera.CameraInfo.CAMERA_FACING_BACK)
mCurrentCameraId = Camera.CameraInfo.CAMERA_FACING_FRONT;
else
mCurrentCameraId = Camera.CameraInfo.CAMERA_FACING_BACK;
initCameraPreview(mCurrentCameraId, false);
mPreview.resetCamera(mCamera);
mPreview.startPreview();
}
步骤5:切换闪光的方法
/**
* Toggling camera flash to ON/OFF
*/
private void toggleFlash() {
if (Util.hasSystemFeature(this, PackageManager.FEATURE_CAMERA_FLASH)) {
Camera.Parameters parameters = mCamera.getParameters();
if (mCurrentCameraId == Camera.CameraInfo.CAMERA_FACING_FRONT) {
if (!Util.hasFrontCameraFlash(parameters)) {
/* Front facing camera doesn\'t supported flash. */
return;
}
}
mReadyToCapture = false;
if (Camera.Parameters.FLASH_MODE_ON.equals(parameters.getFlashMode())) {
mFlashMode = Camera.Parameters.FLASH_MODE_OFF;
} else {
mFlashMode = Camera.Parameters.FLASH_MODE_ON;
}
mCameraHandler.post(new Runnable() {
@Override
public void run() {
mCamera.stopPreview();
releaseCamera(false);
initCameraPreview(mCurrentCameraId, false);
mPreview.resetCamera(mCamera);
mPreview.startPreview();
}
});
} else {
/* warning_no_flash */
}
}
步骤6:在屏幕状态变化期间处理相机的方法
/**
* Release the camera for other applications
*/
private void releaseCamera(boolean remove) {
if (mCamera != null) {
if (remove)
mPreview.getHolder().removeCallback(mPreview);
mCamera.release();
mCamera = null;
}
}
第7步:实用程序类。
/**
* Check whether the given feature available in s/m
*
* @return Returns true if the devices supports the feature, else
* false.
*/
public static boolean hasSystemFeature(Context context, String feature) {
return context.getPackageManager().hasSystemFeature(feature);
}
/**
* Check whether front camera flash feature available in s/m
*/
public static boolean hasFrontCameraFlash(Camera.Parameters cameraParameters) {
boolean result = true;
if (cameraParameters.getFlashMode() == null) {
result = false;
}
List<String> supportedFlashModes = cameraParameters.getSupportedFlashModes();
if (supportedFlashModes == null || supportedFlashModes.isEmpty()
|| supportedFlashModes.size() == 1 &&
supportedFlashModes.get(0).equals(Camera.Parameters.FLASH_MODE_OFF)) {
result = false;
}
return result;
}
/**
* Showing camera in the same orientation as the display
*/
public static int[] getCameraDisplayOrientation(Activity activity,
int cameraId) {
Camera.CameraInfo info =
new Camera.CameraInfo();
Camera.getCameraInfo(cameraId, info);
int rotation = activity.getWindowManager().getDefaultDisplay()
.getRotation();
int degrees = 0;
switch (rotation) {
case Surface.ROTATION_0:
degrees = 0;
break;
case Surface.ROTATION_90:
degrees = 90;
break;
case Surface.ROTATION_180:
degrees = 180;
break;
case Surface.ROTATION_270:
degrees = 270;
break;
}
int result;
if (info.facing == Camera.CameraInfo.CAMERA_FACING_FRONT) {
result = (info.orientation + degrees) % 360;
result = (360 - result) % 360; // compensate the mirror
} else { // back-facing
result = (info.orientation - degrees + 360) % 360;
}
return new int[]{result, degrees};
}
第8步:捕获
// Get an image from the camera
if (null != mCamera && mReadyToCapture) {
mCameraOrientationListener.rememberOrientation();
mCamera.takePicture(mShutter, null, mPicture)
}
/**
* Camera shutter sound callback,
* used to enable sound while capture
*/
private Camera.ShutterCallback mShutter = new Camera.ShutterCallback() {
@Override
public void onShutter() {
}
};
/**
* Camera picture callback
*/
private Camera.PictureCallback mPicture = new Camera.PictureCallback() {
@Override
public void onPictureTaken(byte[] data, Camera camera) {
mReadyToCapture = false;
Bitmap bitmap = BitmapFactory.decodeByteArray(data, 0, data.length);
int rotation = ((mCurrentCameraId == Camera.CameraInfo.CAMERA_FACING_BACK ? mDisplayOrientation :
((360 - mDisplayOrientation) % 360)) + mCameraOrientationListener.getRememberedOrientation()
+ mLayoutOrientation) % 360;
if (rotation != 0) {
Matrix matrix = new Matrix();
matrix.postRotate(rotation);
bitmap = Bitmap.createBitmap(bitmap, 0, 0, bitmap.getWidth(), bitmap.getHeight(), matrix, false);
}
}
};
步骤9:用于处理图像旋转的相机方向监听器
/**
* Orientation listener to remember the device's orientation when the user presses
* the shutter button.
* <p/>
* The orientation will be normalized to return it in steps of 90 degrees
* (0, 90, 180, 270).
*/
public class CameraOrientationListener extends OrientationEventListener {
private int currentNormalizedOrientation;
private int rememberedNormalizedOrientation;
public CameraOrientationListener(Context context) {
super(context, SensorManager.SENSOR_DELAY_NORMAL);
}
@Override
public void onOrientationChanged(int orientation) {
if (orientation != ORIENTATION_UNKNOWN) {
currentNormalizedOrientation = normalize(orientation);
}
}
private int normalize(int degrees) {
if (degrees > 315 || degrees <= 45) {
return 0;
}
if (degrees > 45 && degrees <= 135) {
return 90;
}
if (degrees > 135 && degrees <= 225) {
return 180;
}
if (degrees > 225 && degrees <= 315) {
return 270;
}
throw new RuntimeException("The physics as we know them are no more. Watch out for anomalies.");
}
public void rememberOrientation() {
rememberedNormalizedOrientation = currentNormalizedOrientation;
}
public int getRememberedOrientation() {
return rememberedNormalizedOrientation;
}
}
第10步:处理国家
@Override
public void onPause() {
super.onPause();
mReadyToCapture = false;
releaseCamera(true);
}
@Override
public void onResume() {
super.onResume();
removePreview();
mReadyToCapture = false;
smoothCameraLoading();
}
private void removePreview() {
mPreviewHolder.removeAllViews();
}
private void smoothCameraLoading() {
mCameraHandler.post(new Runnable() {
@Override
public void run() {
initCameraPreview(mCurrentCameraId, true);
}
});
}
步骤11:使用实例变量
private String mFlashMode = Camera.Parameters.FLASH_MODE_OFF;
private int mCurrentCameraId = Camera.CameraInfo.CAMERA_FACING_BACK;
private int mDisplayOrientation;
private int mLayoutOrientation;
private boolean mReadyToCapture = false;
private Camera.Size mPreviewSize;
private FrameLayout mPreviewHolder;
private Camera mCamera;
private CameraPreview mPreview;
private Handler mCameraHandler;
private CameraOrientationListener mCameraOrientationListener;
private FrameLayout mRootView;
答案 1 :(得分:2)
在我的相机应用程序中,它适用于与您不同的东西: 1.在surfaceCreated打开相机。 2.在SurfaceChanged中使用StartPreview并且没有stopPreview。 3.在surfaceDestoryed中释放相机。
要更改相机,只需将surfaceView设置为INVISIBLE,然后设置相机参数,然后再将surfaceView设置为VISIBLE。在我的应用程序中,我只这样做:
mbtCamera.setOnClickListener(new OnClickListener(){
@Override
public void onClick(View v) {
// TODO Auto-generated method stub
if(cameraMax > 1){
mSurfaceView.setVisibility(View.INVISIBLE);
if(mCameraParam.isZoomSupported()) cameraZoomRatios.clear();
if(cameraUsing == 0) cameraUsing = 1; else cameraUsing = 0;
mCameraOverlayView.setScaleFactor(1.0f);
mSurfaceView.setVisibility(View.VISIBLE);
}
}
});
希望这会有所帮助!
完整的回调:
class CameraSurfaceHolderCallback implements SurfaceHolder.Callback {
@Override
public void surfaceCreated(SurfaceHolder holder) {
mCamera = Camera.open(cameraUsing);
mCameraParam = mCamera.getParameters();
supportFlashMode = mCameraParam.getSupportedFlashModes();
if(supportFlashMode == null) mbtFlash.setVisibility(View.INVISIBLE);
android.hardware.Camera.CameraInfo info = new android.hardware.Camera.CameraInfo();
android.hardware.Camera.getCameraInfo(cameraUsing, info);
int rotation = 0;
if (info.facing == CameraInfo.CAMERA_FACING_FRONT){
rotation = (info.orientation - rt + 360) % 360;
if(mCameraParam.getSupportedFlashModes() == null) mbtFlash.setVisibility(View.INVISIBLE);
}
else{ // back-facing camera
rotation = (info.orientation + rt) % 360;
mbtFlash.setVisibility(View.VISIBLE);
if(flashMode.equals(Camera.Parameters.FLASH_MODE_AUTO)) icons[0] = BitmapFactory.decodeResource(getResources(), R.drawable.ic_action_flash_automatic);
else if(flashMode.equals(Camera.Parameters.FLASH_MODE_OFF)) icons[0] = BitmapFactory.decodeResource(getResources(), R.drawable.ic_action_flash_off);
else if(flashMode.equals(Camera.Parameters.FLASH_MODE_ON)) icons[0] = BitmapFactory.decodeResource(getResources(), R.drawable.ic_action_flash_on);
Matrix rot = new Matrix();
rot.setRotate(360-rt, icons[0].getWidth()/2, icons[0].getHeight()/2);
icons[0] = Bitmap.createBitmap(icons[0], 0, 0, icons[0].getWidth(), icons[0].getHeight(), rot, true);
mbtFlash.setImageBitmap(icons[0]);
mCameraParam.setFlashMode(flashMode);
}
if(mCameraParam.isZoomSupported()){
cameraZoomRatios = mCameraParam.getZoomRatios();
mCameraOverlayView.setMaxScaleFactor(cameraZoomRatios.get(mCameraParam.getMaxZoom())/100f);
}else mCameraOverlayView.setMaxScaleFactor(1.0f);
List<Size> ss = mCameraParam.getSupportedPictureSizes();
Size maxResolution = ss.get(0);
long pixel1, pixel2;
pixel1 = maxResolution.width * maxResolution.height;
for(int i=0; i<ss.size(); i++){
pixel2 = ss.get(i).width * ss.get(i).height;
if(pixel2 > pixel1){
maxResolution = ss.get(i);
pixel1 = pixel2;
}
}
mCameraParam.setPictureSize(maxResolution.width, maxResolution.height);
mCameraParam.setJpegQuality(100);
LayoutParams rlParams = (LayoutParams) mSurfaceView.getLayoutParams();
WindowManager wm = (WindowManager) getSystemService(WINDOW_SERVICE);
Display dp = wm.getDefaultDisplay();
DisplayMetrics dm = new DisplayMetrics();
dp.getMetrics(dm);
float dpiScale = dm.density;
float wScaleFactor = (dm.widthPixels-10*dpiScale)/maxResolution.height;
float hScaleFactor = (dm.heightPixels-mllTopButtons.getHeight()-mllBotButtons.getHeight()-10*dpiScale)/maxResolution.width;
if(wScaleFactor < hScaleFactor){
rlParams.width = (int) (dm.widthPixels - 10*dpiScale);
rlParams.height = (int) (maxResolution.width * wScaleFactor);
}else{
rlParams.width = (int) (maxResolution.height * hScaleFactor);
rlParams.height = (int) (dm.heightPixels-mllTopButtons.getHeight()-mllBotButtons.getHeight()-10*dpiScale);
}
mSurfaceView.setLayoutParams(rlParams);
mCameraOverlayView.setLayoutParams(rlParams);
ss = mCameraParam.getSupportedJpegThumbnailSizes();
float photoAspectRatio, thumbAspectRatio;
photoAspectRatio = (float)maxResolution.width / maxResolution.height;
thumbAspectRatio = 0;
pixel1 = 0;
for(int i=0; i<ss.size(); i++){
if(ss.get(i).height != 0) thumbAspectRatio = (float)ss.get(i).width / ss.get(i).height;
if(thumbAspectRatio == photoAspectRatio){
if(pixel1 == 0)
{
maxResolution = ss.get(i);
pixel1 = ss.get(i).width * ss.get(i).height;
}else{
pixel2 = ss.get(i).width * ss.get(i).height;
if((pixel2 < pixel1)&&(pixel2 != 0)){
maxResolution = ss.get(i);
pixel1 = pixel2;
}
}
}
}
if(pixel1 != 0){
mCameraParam.setJpegThumbnailSize(maxResolution.width, maxResolution.height);
mCameraParam.setJpegThumbnailQuality(100);
}
List<String> focusModes = mCameraParam.getSupportedFocusModes();
if(focusModes.contains(Camera.Parameters.FOCUS_MODE_AUTO)){
mCameraParam.setFocusMode(Camera.Parameters.FOCUS_MODE_AUTO);
focusingColor = Color.YELLOW;
}
int minEv = mCameraParam.getMinExposureCompensation();
int maxEv = mCameraParam.getMaxExposureCompensation();
if((minEv == 0)&&(maxEv == 0)) mCameraOverlayView.setEVCompensate(false);
else mCameraOverlayView.setEVCompensate(minEv, maxEv);
mCameraParam.setRotation(rotation);
mCamera.setParameters(mCameraParam);
}
@Override
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
try {
mCamera.setDisplayOrientation(90);
mCamera.setPreviewDisplay(mSurfaceView.getHolder());
List<Size> ss = mCameraParam.getSupportedPreviewSizes();
Size maxResolution = ss.get(0);
long pixel1, pixel2;
float photoAspectRatio, previewAspectRatio;
photoAspectRatio = (float)mCameraParam.getPictureSize().width / mCameraParam.getPictureSize().height;
previewAspectRatio = 0;
pixel1 = 0;
for(int i=0; i<ss.size(); i++){
if(ss.get(i).height != 0) previewAspectRatio = (float)ss.get(i).width / ss.get(i).height;
if(previewAspectRatio == photoAspectRatio){
if(pixel1 == 0)
{
maxResolution = ss.get(i);
pixel1 = ss.get(i).width * ss.get(i).height;
}else{
pixel2 = ss.get(i).width * ss.get(i).height;
if(pixel2 > pixel1){
maxResolution = ss.get(i);
pixel1 = pixel2;
}
}
}
}
if(pixel1 != 0) mCameraParam.setPreviewSize(maxResolution.width, maxResolution.height);
mCamera.setParameters(mCameraParam);
mCamera.startPreview();
}
catch(Exception e){}
}
@Override
public void surfaceDestroyed(SurfaceHolder holder) {
mCamera.stopPreview();
mCamera.release();
}
}
我在活动中使用它而没有片段。我不确定这会有什么不同。
答案 2 :(得分:2)
我认为safeCameraOpenInView
方法存在一点问题,那就是:
您的新相机视图是在冻结的图片下制作的。
所以你应该编辑这一行:preview.addView(mPreview);
这样:preview.addView(mPreview, preview.getChildCount());
或者您可以先删除上一个摄像机视图,然后添加新视频:
preview.removeAllViews();
preview.addView(mPreview);
希望这会奏效。