Takes long time to open in custom camera android?

2019-07-02 12:04发布

问题:

Hi I am working in custom camera. I used CameraPreview class from git. Everything works fine but problem is when i open camera from Activity A, it takes 4 seconds to open the camera. I am not getting any error. But getCameraInstance method calling takes long time to open the camera. How to reduce 4 seconds delay when opening the camera? I have clueless how to reduce the delay to go to TakePhotoFragment. Please help me to solve the issue

Here is CameraPreview:

public class CameraPreview extends SurfaceView implements SurfaceHolder.Callback {
    private Context mContext;
    private Camera camera;
    private SurfaceHolder surfaceHolder;
    public List<Camera.Size> mSupportedPreviewSizes;
    public Camera.Size mPreviewSize;
    private static final String TAG = "CameraPreview";

    public CameraPreview(Context context, Camera camera) {
        super(context);
        mContext = context;
        this.camera = camera;
        mSupportedPreviewSizes = camera.getParameters().getSupportedPreviewSizes();
        for (Camera.Size str : mSupportedPreviewSizes)
            Log.e(TAG, str.width + "/" + str.height);
        surfaceHolder = getHolder();
        surfaceHolder.addCallback(this);
        surfaceHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
    }

    @Override
    public void surfaceCreated(SurfaceHolder surfaceHolder) {
        try {
            this.camera.setPreviewDisplay(surfaceHolder);
            Camera.Parameters params = this.camera.getParameters();
            List<Camera.Size> sizes = params.getSupportedPictureSizes();
            Camera.Size mSize = null;

            List<Camera.Size> psizes = params.getSupportedPreviewSizes();
            Camera.Size pSize = null;

            Collections.sort(sizes, new Comparator<Camera.Size>() {
                @Override
                public int compare(Camera.Size t1, Camera.Size t2) {
                    return t1.width >= t2.width ? -1 : 1;
                }
            });
            Collections.sort(psizes, new Comparator<Camera.Size>() {
                @Override
                public int compare(Camera.Size t1, Camera.Size t2) {
                    return t1.width >= t2.width ? -1 : 1;
                }
            });
            for (Camera.Size size :
                    sizes) {
                if (size.width <= 1920) {
                    mSize = size;
                    break;
                }
            }
//            for (Camera.Size size :
//                    psizes) {
//                if (size.width == mSize.width) {
//                    pSize = size;
//                    break;
//                }
//            }
//            if (pSize==null){
            for (Camera.Size size :
                    psizes) {
                if (size.width <= 1920) {
                    pSize = size;
                    break;
                }
            }
//            }
            Log.i("CAMERA", "Available resolution: " + mSize.width + " " + mSize.height);
            Log.i("CAMERA", "Available resolution2: " + pSize.width + " " + pSize.height);

            params.setPictureSize(mSize.width, mSize.height);
            params.setPreviewSize(pSize.width, pSize.height);
            this.camera.setParameters(params);
            this.camera.startPreview();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    @Override
    public void surfaceChanged(SurfaceHolder surfaceHolder, 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 (surfaceHolder.getSurface() == null) {
            // preview surface does not exist
            return;
        }

        // stop preview before making changes
        try {
            camera.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
        try {
            Camera.Parameters parameters = camera.getParameters();
            parameters.setPreviewSize(mPreviewSize.width, mPreviewSize.height);
            camera.setParameters(parameters);
            camera.setDisplayOrientation(90);
            camera.setPreviewDisplay(surfaceHolder);
            camera.startPreview();

        } catch (Exception e) {
            Log.d(TAG, "Error starting camera preview: " + e.getMessage());
        }
    }

    @Override
    public void surfaceDestroyed(SurfaceHolder surfaceHolder) {
        this.camera.stopPreview();
        this.camera.release();
        getHolder().removeCallback(this);
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        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);
    }

    public 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.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;
    }
}

In CameraFragment:

public class TakePhotoFragment extends Fragment {
       private Button camera;
    private Button gallery;
    private Camera mCamera;
    private CameraPreview mCameraPreview;
    private FrameLayout preview;

    public static TakePhotoFragment newInstance() {
        return new TakePhotoFragment();
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
        View view = inflater.inflate(R.layout.rr_take_photo, container, false);
        camera = (Button) view.findViewById(R.id.button_capture);
        gallery = (Button) view.findViewById(R.id.gallery);
        mCamera = getCameraInstance();
        mCameraPreview = new CameraPreview(getActivity(), mCamera);
         preview = (FrameLayout) view.findViewById(R.id.camera_preview);
        preview.addView(mCameraPreview);
        camera.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
               /* Intent intent = new Intent(getActivity(), PhotoActivity.class);
                startActivity(intent);
                getActivity().finish();*/
                mCamera.takePicture(null, null, mPicture);
            }
        });
    //this takes long time to open
   private Camera getCameraInstance() {
        Camera camera = null;
        try {
            camera = Camera.open();
        } catch (Exception e) {
            // cannot get camera or does not exist
        }
        return camera;
    }

    Camera.PictureCallback mPicture = new Camera.PictureCallback() {
        @Override
        public void onPictureTaken(byte[] data, Camera camera) {
            File pictureFile = getOutputMediaFile();
            Log.e("pictureFile",pictureFile.getAbsolutePath());
            if (pictureFile == null) {
                return;
            }
            try {
                FileOutputStream fos = new FileOutputStream(pictureFile);
                fos.write(data);
                fos.close();
                SharedPreferencesHelper.setStringItem("gallery_item", pictureFile.getAbsolutePath());
                Intent intent = new Intent(getActivity(), PhotoActivity.class);
                startActivity(intent);
                getActivity().finish();
            } catch (FileNotFoundException e) {

            } catch (IOException e) {
            }
        }
    };

    private static File getOutputMediaFile() {
        File mediaStorageDir = new File(
                Environment
                        .getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES),
                "MyCameraApp");
        if (!mediaStorageDir.exists()) {
            if (!mediaStorageDir.mkdirs()) {
                Log.d("MyCameraApp", "failed to create directory");
                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");
        Log.e("mediaFile",mediaStorageDir.getPath());
        return mediaFile;
    }