某些设备上的Camera Preview性能问题

时间:2016-07-27 14:45:48

标签: android camera surfaceview

我通过这个例子使用android camera api创建了一个相机应用程序:https://examples.javacodegeeks.com/android/core/hardware/camera-hardware/android-camera-example/

我根据自己的需要做了一些更改,你可以看到下面的代码。问题是,后置摄像头的摄像头预览在我的LG G3设备上工作得很好,但在LG G4上它变得太慢了。它也适用于两台设备上的前置摄像头。

什么可能导致这个问题?

CameraPreview:

public class CameraPreview extends SurfaceView implements SurfaceHolder.Callback{

private static String TAG = "CameraPreview";

private SurfaceHolder mHolder;
private Camera mCamera;
private List<Size> mSupportedPreviewSizes;
private Size mPreviewSize;


public CameraPreview(Context context, Camera camera){
    super(context);
    mCamera = camera;

    mHolder = getHolder();
    mHolder.addCallback(this);
    // deprecated setting, but required on Android versions prior to 3.0
    mHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);


}

@Override
public void surfaceCreated(SurfaceHolder surfaceHolder) {
    try{
        Log.d(TAG, "Surface Created..");
        if(mCamera == null){
            mCamera.setPreviewDisplay(surfaceHolder);
            mCamera.setDisplayOrientation(90);
            mCamera.startPreview();
        }
    } catch (IOException e) {
        Log.d(VIEW_LOG_TAG, "Error setting camera preview: " + e.getMessage());
    }

}

public void refreshCamera(Camera camera) {
    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
    setCamera(camera);
    try {
        Log.d(TAG,"RefreshCamera..");
        if(mCamera == null){
            Log.d(TAG,"Camera null");
        }

        Camera.Parameters parameters = mCamera.getParameters();
        parameters.setPreviewSize(mPreviewSize.width, mPreviewSize.height);
        mCamera.setParameters(parameters);
        mCamera.setPreviewDisplay(mHolder);
        mCamera.setPreviewDisplay(mHolder);
        mCamera.setDisplayOrientation(90);
        mCamera.startPreview();
    } catch (Exception e) {
        Log.d(VIEW_LOG_TAG, "Error starting camera preview: " + e.getMessage());
    }
}

@Override
public void surfaceChanged(SurfaceHolder surfaceHolder, int i, int i1, int i2) {

    Log.d(TAG, "Surface Changed..");


    refreshCamera(mCamera);
}

public void setCamera(Camera camera) {
    //method to set a camera instance
    mCamera = camera;
}

@Override
public void surfaceDestroyed(SurfaceHolder surfaceHolder) {

     mCamera.release();
}

@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
    Log.d(TAG,"onMeasure..");
    final int width = resolveSize(getSuggestedMinimumWidth(), widthMeasureSpec);
    final int height = resolveSize(getSuggestedMinimumHeight(), heightMeasureSpec);
    setMeasuredDimension(width, height);
    if(mSupportedPreviewSizes==null){
        mSupportedPreviewSizes = mCamera.getParameters().getSupportedPreviewSizes();
    }else{

        mPreviewSize = getOptimalPreviewSize(mSupportedPreviewSizes, width, height);
        Log.d(TAG, "mPreviewSize set.. Width: " + mPreviewSize.width+" Height: " + mPreviewSize.height);
    }
}

private 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;
}

}

如果需要,我可以共享Activity类。

谢谢..

1 个答案:

答案 0 :(得分:0)

我使用表面视图时遇到了同样的问题。使用下面的预览类。我可以为所有设备屏幕工作。

公共类SquareCameraPreview扩展了SurfaceView {

public static final String TAG = SquareCameraPreview.class.getSimpleName();
private static final int INVALID_POINTER_ID = -1;

private static final int ZOOM_OUT = 0;
private static final int ZOOM_IN = 1;
private static final int ZOOM_DELTA = 1;

private static final int FOCUS_SQR_SIZE = 100;
private static final int FOCUS_MAX_BOUND = 1000;
private static final int FOCUS_MIN_BOUND = -FOCUS_MAX_BOUND;

private static final double ASPECT_RATIO = 3.0 / 4.0;
private Camera mCamera;

private float mLastTouchX;
private float mLastTouchY;

// For scaling
private int mMaxZoom;
private boolean mIsZoomSupported;
private int mActivePointerId = INVALID_POINTER_ID;
private int mScaleFactor = 1;
private ScaleGestureDetector mScaleDetector;

// For focus
private boolean mIsFocus;
private boolean mIsFocusReady;
private Camera.Area mFocusArea;
private ArrayList<Camera.Area> mFocusAreas;

public SquareCameraPreview(Context context) {
    super(context);
    init(context);
}

public SquareCameraPreview(Context context, AttributeSet attrs) {
    super(context, attrs);
    init(context);
}

public SquareCameraPreview(Context context, AttributeSet attrs, int defStyle) {
    super(context, attrs, defStyle);
    init(context);
}

private void init(Context context) {
    mScaleDetector = new ScaleGestureDetector(context, new ScaleListener());
    mFocusArea = new Camera.Area(new Rect(), 1000);
    mFocusAreas = new ArrayList<Camera.Area>();
    mFocusAreas.add(mFocusArea);
}

/**
 * Measure the view and its content to determine the measured width and the
 * measured height
 */
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
    int height = MeasureSpec.getSize(heightMeasureSpec);
    int width = MeasureSpec.getSize(widthMeasureSpec);

    final boolean isPortrait =
            getResources().getConfiguration().orientation == Configuration.ORIENTATION_PORTRAIT;

    if (isPortrait) {
        if (width > height * ASPECT_RATIO) {
            width = (int) (height * ASPECT_RATIO + 0.5);
        } else {
            height = (int) (width / ASPECT_RATIO + 0.5);
        }
    } else {
        if (height > width * ASPECT_RATIO) {
            height = (int) (width * ASPECT_RATIO + 0.5);
        } else {
            width = (int) (height / ASPECT_RATIO + 0.5);
        }
    }

    setMeasuredDimension(width, height);
}

public int getViewWidth() {
    return getWidth();
}

public int getViewHeight() {
    return getHeight();
}

public void setCamera(Camera camera) {
    mCamera = camera;

    if (camera != null) {
        Camera.Parameters params = camera.getParameters();
        mIsZoomSupported = params.isZoomSupported();
        if (mIsZoomSupported) {
            mMaxZoom = params.getMaxZoom();
        }
    }
}

@Override
public boolean onTouchEvent(MotionEvent event) {
    mScaleDetector.onTouchEvent(event);

    final int action = event.getAction();
    switch (action & MotionEvent.ACTION_MASK) {
        case MotionEvent.ACTION_DOWN: {
            mIsFocus = true;

            mLastTouchX = event.getX();
            mLastTouchY = event.getY();

            mActivePointerId = event.getPointerId(0);
            break;
        }
        case MotionEvent.ACTION_UP: {
            if (mIsFocus && mIsFocusReady) {
                handleFocus(mCamera.getParameters());
            }
            mActivePointerId = INVALID_POINTER_ID;
            break;
        }
        case MotionEvent.ACTION_POINTER_DOWN: {
            mCamera.cancelAutoFocus();
            mIsFocus = false;
            break;
        }
        case MotionEvent.ACTION_CANCEL: {
            mActivePointerId = INVALID_POINTER_ID;
            break;
        }
    }

    return true;
}

private void handleZoom(Camera.Parameters params) {
    int zoom = params.getZoom();
    if (mScaleFactor == ZOOM_IN) {
        if (zoom < mMaxZoom) zoom += ZOOM_DELTA;
    } else if (mScaleFactor == ZOOM_OUT) {
        if (zoom > 0) zoom -= ZOOM_DELTA;
    }
    params.setZoom(zoom);
    mCamera.setParameters(params);
}

private void handleFocus(Camera.Parameters params) {
    float x = mLastTouchX;
    float y = mLastTouchY;

    if (!setFocusBound(x, y)) return;

    List<String> supportedFocusModes = params.getSupportedFocusModes();
    if (supportedFocusModes != null
            && supportedFocusModes.contains(Camera.Parameters.FOCUS_MODE_AUTO)) {
        Log.d(TAG, mFocusAreas.size() + "");
        params.setFocusAreas(mFocusAreas);
        params.setFocusMode(Camera.Parameters.FOCUS_MODE_AUTO);
        mCamera.setParameters(params);
        mCamera.autoFocus(new Camera.AutoFocusCallback() {
            @Override
            public void onAutoFocus(boolean success, Camera camera) {
                // Callback when the auto focus completes
            }
        });
    }
}

public void setIsFocusReady(final boolean isFocusReady) {
    mIsFocusReady = isFocusReady;
}

private boolean setFocusBound(float x, float y) {
    int left = (int) (x - FOCUS_SQR_SIZE / 2);
    int right = (int) (x + FOCUS_SQR_SIZE / 2);
    int top = (int) (y - FOCUS_SQR_SIZE / 2);
    int bottom = (int) (y + FOCUS_SQR_SIZE / 2);

    if (FOCUS_MIN_BOUND > left || left > FOCUS_MAX_BOUND) return false;
    if (FOCUS_MIN_BOUND > right || right > FOCUS_MAX_BOUND) return false;
    if (FOCUS_MIN_BOUND > top || top > FOCUS_MAX_BOUND) return false;
    if (FOCUS_MIN_BOUND > bottom || bottom > FOCUS_MAX_BOUND) return false;

    mFocusArea.rect.set(left, top, right, bottom);

    return true;
}

private class ScaleListener extends ScaleGestureDetector.SimpleOnScaleGestureListener {

    @Override
    public boolean onScale(ScaleGestureDetector detector) {
        mScaleFactor = (int) detector.getScaleFactor();
        handleZoom(mCamera.getParameters());
        return true;
    }
}

}

  

public class CameraFragment extends Fragment实现了SurfaceHolder.Callback,Camera.PictureCallback {

public static int HIGH_RESOLUTION_WIDTH=1000;
public static int HIGH_RESOLUTION_HIGHT=1500;
public static String clorie_count;
private long startTime = 0L;

public static final String TAG = CameraFragment.class.getSimpleName();
public static final String CAMERA_ID_KEY = "camera_id";
public static final String CAMERA_FLASH_KEY = "flash_mode";
public static final String IMAGE_INFO = "image_info";

private static final int PICTURE_SIZE_MAX_WIDTH = 1280;
private static final int PREVIEW_SIZE_MAX_WIDTH = 640;

private int mCameraID;
private String mFlashMode;
private Camera mCamera;
private SquareCameraPreview mPreviewView;
private SurfaceHolder mSurfaceHolder;

private boolean mIsSafeToTakePhoto = false;

private ImageParameters mImageParameters;

private CameraOrientationListener mOrientationListener;
@Override
public void onAttach(Activity activity) {
    super.onAttach(activity);
    context = activity;
    mOrientationListener = new CameraOrientationListener(context);
}

View view;
Dialog listDialog;

@SuppressLint("NewApi")
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
        Bundle savedInstanceState) {

    view = inflater.inflate(R.layout.camera_fragment, container, false);

    if (savedInstanceState == null) {
            mCameraID = getBackCameraID();
            mFlashMode = CameraSettingPreferences.getCameraFlashMode(getActivity());
            mImageParameters = new ImageParameters();
        } else {
            mCameraID = savedInstanceState.getInt(CAMERA_ID_KEY);
            mFlashMode = savedInstanceState.getString(CAMERA_FLASH_KEY);
            mImageParameters = savedInstanceState.getParcelable(IMAGE_INFO);
        }
   mPreviewView = (SquareCameraPreview) view.findViewById(R.id.camerapreview);
         mPreviewView.getHolder().addCallback(CameraFragment.this);
         mImageParameters.mIsPortrait =getResources().getConfiguration().orientation == Configuration.ORIENTATION_PORTRAIT;

         capture_icon.setOnClickListener(new OnClickListener() {

        @Override
        public void onClick(View v) {
            // TODO Auto-generated method stub
            takePicture();
        }
    });
return view;
}
         private void takePicture() {

            if (mIsSafeToTakePhoto) {
                setSafeToTakePhoto(false);

                mOrientationListener.rememberOrientation();

                // Shutter callback occurs after the image is captured. This can
                // be used to trigger a sound to let the user know that image is taken
                Camera.ShutterCallback shutterCallback = null;

                // Raw callback occurs when the raw image data is available
                Camera.PictureCallback raw = null;

                // postView callback occurs when a scaled, fully processed
                // postView image is available.
                Camera.PictureCallback postView = null;

                // jpeg callback occurs when the compressed image is available
                mCamera.takePicture(shutterCallback, raw, postView, this);
            }
        }        

        private void setSafeToTakePhoto(final boolean isSafeToTakePhoto) {
        mIsSafeToTakePhoto = isSafeToTakePhoto;
    }

    private void setCameraFocusReady(final boolean isFocusReady) {
        if (this.mPreviewView != null) {
            mPreviewView.setIsFocusReady(isFocusReady);
        }
    }
    /**
     * Determine the current display orientation and rotate the camera preview
     * accordingly
     */
    private void determineDisplayOrientation() {
        CameraInfo cameraInfo = new CameraInfo();
        Camera.getCameraInfo(mCameraID, cameraInfo);

        // Clockwise rotation needed to align the window display to the natural position
        int rotation = getActivity().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 displayOrientation;

        // CameraInfo.Orientation is the angle relative to the natural position of the device
        // in clockwise rotation (angle that is rotated clockwise from the natural position)
        if (cameraInfo.facing == CameraInfo.CAMERA_FACING_FRONT) {
            // Orientation is angle of rotation when facing the camera for
            // the camera image to match the natural orientation of the device
            displayOrientation = (cameraInfo.orientation + degrees) % 360;
            displayOrientation = (360 - displayOrientation) % 360;
        } else {
            displayOrientation = (cameraInfo.orientation - degrees + 360) % 360;
        }

        mImageParameters.mDisplayOrientation = displayOrientation;
        mImageParameters.mLayoutOrientation = degrees;

        mCamera.setDisplayOrientation(mImageParameters.mDisplayOrientation);
    }
    private void setupCamera() {
        // Never keep a global parameters
        Camera.Parameters parameters = mCamera.getParameters();

        Size bestPreviewSize = determineBestPreviewSize(parameters);
        Size bestPictureSize = determineBestPictureSize(parameters);

        parameters.setPreviewSize(bestPreviewSize.width, bestPreviewSize.height);
        parameters.setPictureSize(bestPictureSize.width, bestPictureSize.height);


        // Set continuous picture focus, if it's supported
        if (parameters.getSupportedFocusModes().contains(Camera.Parameters.FOCUS_MODE_CONTINUOUS_PICTURE)) {
            parameters.setFocusMode(Camera.Parameters.FOCUS_MODE_CONTINUOUS_PICTURE);
        }

        final View changeCameraFlashModeBtn = getView().findViewById(R.id.flash);
        List<String> flashModes = parameters.getSupportedFlashModes();
        if (flashModes != null && flashModes.contains(mFlashMode)) {
            parameters.setFlashMode(mFlashMode);
            changeCameraFlashModeBtn.setVisibility(View.VISIBLE);
        } else {
            changeCameraFlashModeBtn.setVisibility(View.INVISIBLE);
        }

        // Lock in the changes
        mCamera.setParameters(parameters);
    }
    private Size determineBestPreviewSize(Camera.Parameters parameters) {
        return determineBestSize(parameters.getSupportedPreviewSizes(), PREVIEW_SIZE_MAX_WIDTH);
    }

    private Size determineBestPictureSize(Camera.Parameters parameters) {
        return determineBestSize(parameters.getSupportedPictureSizes(), PICTURE_SIZE_MAX_WIDTH);
    }

    private Size determineBestSize(List<Size> sizes, int widthThreshold) {
        Size bestSize = null;
        Size size;
        int numOfSizes = sizes.size();
        for (int i = 0; i < numOfSizes; i++) {
            size = sizes.get(i);
            boolean isDesireRatio = (size.width / 4) == (size.height / 3);
            boolean isBetterSize = (bestSize == null) || size.width > bestSize.width;

            if (isDesireRatio && isBetterSize) {
                bestSize = size;
            }
        }

        if (bestSize == null) {
            Log.d(TAG, "cannot find the best camera size");
            return sizes.get(sizes.size() - 1);
        }

        return bestSize;
    }

     /**
     * Start the camera preview
     */
    private void startCameraPreview() {
        determineDisplayOrientation();
        setupCamera();

        try {
            mCamera.setPreviewDisplay(mSurfaceHolder);
            mCamera.startPreview();

            setSafeToTakePhoto(true);
            setCameraFocusReady(true);
        } catch (IOException e) {
            Log.d(TAG, "Can't start camera preview due to IOException " + e);
            e.printStackTrace();
        }
    }

    private void getCamera(int cameraID) {
        try {
            mCamera = Camera.open(cameraID);
            mPreviewView.setCamera(mCamera);
        } catch (Exception e) {
            Log.d(TAG, "Can't open camera with id " + cameraID);
            e.printStackTrace();
        }
    }

    @Override
    public void onPictureTaken(byte[] arg0, Camera arg1) {
        // TODO Auto-generated method stub



        HERE YOU GET THE PHOTO BYTE[] arg0

        CONVERT IT TO BITMAP OR STROE INTO A FILE


    }

    @Override
    public void surfaceChanged(SurfaceHolder arg0, int arg1, int arg2,
            int arg3) {
        // TODO Auto-generated method stub

    }

    @Override
    public void surfaceCreated(SurfaceHolder holder) {
        // TODO Auto-generated method stub
         mSurfaceHolder = holder;

            getCamera(mCameraID);
            startCameraPreview();
    }

    @Override
    public void surfaceDestroyed(SurfaceHolder arg0) {
        // TODO Auto-generated method stub

    } 



        private static class CameraOrientationListener extends OrientationEventListener {

            private int mCurrentNormalizedOrientation;
            private int mRememberedNormalOrientation;

            public CameraOrientationListener(Context context) {
                super(context, SensorManager.SENSOR_DELAY_NORMAL);
            }

            @Override
            public void onOrientationChanged(int orientation) {
                if (orientation != ORIENTATION_UNKNOWN) {
                    mCurrentNormalizedOrientation = normalize(orientation);
                }
            }

            /**
             * @param degrees Amount of clockwise rotation from the device's natural position
             * @return Normalized degrees to just 0, 90, 180, 270
             */
            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() {
                mRememberedNormalOrientation = mCurrentNormalizedOrientation;
            }

            public int getRememberedNormalOrientation() {
                rememberOrientation();
                return mRememberedNormalOrientation;
            }
        }
        /*@Override
        public void onResume() {
            super.onResume();

            if (mCamera == null) {
                restartPreview();
            }
        }*/

        @Override
        public void onStop() {
            mOrientationListener.disable();

            // stop the preview
            if (mCamera != null) {
                stopCameraPreview();
                mCamera.release();
                mCamera = null;
            }
            if (getKillStatus()) {
                android.os.Process.killProcess(android.os.Process.myPid());
            }
           // CameraSettingPreferences.saveCameraFlashMode(getActivity(), mFlashMode);

            super.onStop();
        }
        @Override
        public void onResume() {
            super.onResume();
            /*if (camera != null) {
                camera.stopPreview();
                preview.setupCamera(null,isResolutionHigh);
                camera.release();
                camera = null;
            }

            int numCams = Camera.getNumberOfCameras();
            if (numCams > 0) {
                try {
                    camera = Camera.open(0);
                    camera.startPreview();
                    preview.setupCamera(camera,isResolutionHigh);

                } catch (RuntimeException ex) {
                    // Toast.makeText(ctx, getString(R.string.camera_not_found),
                    // Toast.LENGTH_LONG).show();
                }
            }*/
            if (mCamera == null) {
                restartPreview();
            }

        }
        private void restartPreview() {
            if (mCamera != null) {
                stopCameraPreview();
                mCamera.release();
                mCamera = null;
            }

            getCamera(mCameraID);
            startCameraPreview();
        }
        /**
         * Stop the camera preview
         */
        private void stopCameraPreview() {
            setSafeToTakePhoto(false);
            setCameraFocusReady(false);

            // Nulls out callbacks, stops face detection
            mCamera.stopPreview();
            mPreviewView.setCamera(null);
        }
        private int getBackCameraID() {
            return CameraInfo.CAMERA_FACING_BACK;
        }

}        
  

和您的XML文件

&#13;
&#13;
<com.demo.camera.SquareCameraPreview
        android:id="@+id/camerapreview"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        />
&#13;
&#13;
&#13;

ImageParameter类

&#13;
&#13;
public class ImageParameters implements Parcelable {

    public boolean mIsPortrait;

    public int mDisplayOrientation;
    public int mLayoutOrientation;

    public int mCoverHeight, mCoverWidth;
    public int mPreviewHeight, mPreviewWidth;

    public ImageParameters(Parcel in) {
        mIsPortrait = (in.readByte() == 1);

        mDisplayOrientation = in.readInt();
        mLayoutOrientation = in.readInt();

        mCoverHeight = in.readInt();
        mCoverWidth = in.readInt();
        mPreviewHeight = in.readInt();
        mPreviewWidth = in.readInt();
    }

    public ImageParameters() {}

    public int calculateCoverWidthHeight() {
       return Math.abs(mPreviewHeight - mPreviewWidth) / 2;
    }

    public int getAnimationParameter() {
        return mIsPortrait ? mCoverHeight : mCoverWidth;
    }

    public boolean isPortrait() {
        return mIsPortrait;
    }

    public ImageParameters createCopy() {
        ImageParameters imageParameters = new ImageParameters();

        imageParameters.mIsPortrait = mIsPortrait;
        imageParameters.mDisplayOrientation = mDisplayOrientation;
        imageParameters.mLayoutOrientation = mLayoutOrientation;

        imageParameters.mCoverHeight = mCoverHeight;
        imageParameters.mCoverWidth = mCoverWidth;
        imageParameters.mPreviewHeight = mPreviewHeight;
        imageParameters.mPreviewWidth = mPreviewWidth;

        return imageParameters;
    }

    public String getStringValues() {
        return "is Portrait: " + mIsPortrait + "," +
                "\ncover height: " + mCoverHeight + " width: " + mCoverWidth
                + "\npreview height: " + mPreviewHeight + " width: " + mPreviewWidth;
    }

    @Override
    public int describeContents() {
        return 0;
    }

    @Override
    public void writeToParcel(Parcel dest, int flags) {
        dest.writeByte((byte) (mIsPortrait ? 1 : 0));

        dest.writeInt(mDisplayOrientation);
        dest.writeInt(mLayoutOrientation);

        dest.writeInt(mCoverHeight);
        dest.writeInt(mCoverWidth);
        dest.writeInt(mPreviewHeight);
        dest.writeInt(mPreviewWidth);
    }

    public static final Creator<ImageParameters> CREATOR = new Parcelable.Creator<ImageParameters>() {
        @Override
        public ImageParameters createFromParcel(Parcel source) {
            return new ImageParameters(source);
        }

        @Override
        public ImageParameters[] newArray(int size) {
            return new ImageParameters[size];
        }
    };
}
&#13;
&#13;
&#13;

您需要相机设置首选项的另一个课程

&#13;
&#13;
public class CameraSettingPreferences {

    private static final String FLASH_MODE = "squarecamera__flash_mode";

    private static SharedPreferences getCameraSettingPreferences(@NonNull final Context context) {
        return context.getSharedPreferences("com.desmond.squarecamera", Context.MODE_PRIVATE);
    }

    protected static void saveCameraFlashMode(@NonNull final Context context, @NonNull final String cameraFlashMode) {
        final SharedPreferences preferences = getCameraSettingPreferences(context);

        if (preferences != null) {
            final SharedPreferences.Editor editor = preferences.edit();
            editor.putString(FLASH_MODE, cameraFlashMode);
            editor.apply();
        }
    }

    public static String getCameraFlashMode(@NonNull final Context context) {
        final SharedPreferences preferences = getCameraSettingPreferences(context);

        if (preferences != null) {
            return preferences.getString(FLASH_MODE, Camera.Parameters.FLASH_MODE_AUTO);
        }

        return Camera.Parameters.FLASH_MODE_AUTO;
    }
}
&#13;
&#13;
&#13;

如果您有任何疑问,请告诉我。