Как периодически делать скрытые снимки, позволяя пользователю сделать снимок с помощью кнопки? - PullRequest
0 голосов
/ 09 ноября 2018

После прочтения нескольких вопросов, похожих на мой вопрос, я думаю, что этот вопрос для ПРО!

Я использую Android Studio.

Я пытаюсь разрешить системе периодически делать «скрытые» снимки WHILE , позволяя пользователю делать снимки с помощью кнопки.

Чтобы попытаться объяснить, что должно случиться, представьте, что вы открываете свою камеру и пытаетесь сделать идеальный снимок, поэтому вам потребуется некоторое время, чтобы найти правильный угол. очевидно, все это время у вас есть предварительный просмотр того, что видит камера, и предварительный просмотр продолжается, пока вы не нажмете «сделать снимок» . Я пытаюсь создать то, что за время до нажатия кнопки «сделать снимок» система делает скрытые снимки в фоновом режиме. Позже я буду использовать снимок, сделанный пользователем, и снимки, сделанные системой, и сохранить их на моем устройстве для последующего редактирования.

[Очевидно, я не могу использовать предварительно встроенное приложение камеры для телефона Android]

До сих пор я полагался на: https://developer.android.com/guide/topics/media/camera#custom-camera для скелета моего кода.

ПРИМЕЧАНИЕ 1: Будут приветствоваться любые предложения.

ПРИМЕЧАНИЕ 2: Будут приветствоваться любые улучшения в моем коде.

ПРИМЕЧАНИЕ 3: Я читал на некоторых форумах, что я могу каким-то образом использовать SurfaceTexture, но я считаю, что примеры трудно понять

ПРИМЕЧАНИЕ 4: Я читал на некоторых форумах, что я могу каким-то образом использовать Camera2, но мне трудно понять примеры, и поэтому я в настоящее время использую устаревший Camera класс.

Мой код указан ниже:

public class CameraActivity extends AppCompatActivity {

    private Camera mCamera;
    private CameraPreview mPreview; 
    // variable to break the photo taking loop
    boolean wasButtonPressed = false;
    static int numOfPicturesTakenUpTo25PPS = 0;
    boolean isItSafeToTakePicture = false;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_camera);
        // Create an instance of Camera
        mCamera = getCameraInstance();
        // Create our Preview view and set it as the content of our activity.
        try {
            mPreview = new CameraPreview(this, mCamera);
            FrameLayout preview = (FrameLayout) findViewById(R.id.camera_preview);
            preview.addView(mPreview);
        } catch (Exception e) {
            Log.d(TAG, "error: in the preview creation: " + e.getMessage());
            e.printStackTrace();
        }
        //double check
        numOfPicturesTakenUpTo25PPS = 0;
        // Add a listener to the Capture button
        Button captureButton = (Button) findViewById(R.id.button_capture);
        captureButton.setOnClickListener(
                new View.OnClickListener() {
                    @Override
                    public void onClick(View v) {
                        //
                        wasButtonPressed = true;

                        if (isItSafeToTakePicture == true) {
                            mCamera.takePicture(null, null, mPicture);
                            isItSafeToTakePicture = false;  //will be changed later to true by "onPictureTaken"
                        }

                    }
                }
        );
    }

    @Override
    protected void onStart(){
        super.onStart();
        Toast.makeText(getApplicationContext(), "user - please wait 2 seconds before taking pictures. (should be 2 secs)",Toast.LENGTH_LONG).show();
        // note user 2 secs have passed and its ok to use:
        Toast.makeText(getApplicationContext(), "You can start taking pictures",Toast.LENGTH_SHORT).show();
        // start taking pictures in a loop.       
        while (wasButtonPressed == false) {
            if (isItSafeToTakePicture == true) {
                mCamera.takePicture(null, null, mPicture);
                isItSafeToTakePicture = false;  //will be changed later to true by "onPictureTaken"
            }
        }

        //TODO: do I need to ensure that this [code above] won't be an infinite loop?


    }

    @Override
    protected void onResume(){
        super.onResume();

    }

    @Override
    protected void onPause() {
        super.onPause();
        releaseCamera();              // release the camera immediately on pause event
    }

    @Override
    protected void onStop() {
        super.onStop();
        releaseCamera();              // release the camera immediately
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        releaseCamera();              // release the camera immediately
    }

    //----------------------------------------------------------------------------------------------------------------//
    //-------------------------end of system functions. beginning of helping functions -------------------------------//
    //----------------------------------------------------------------------------------------------------------------//

    private void releaseCamera(){
        if (mCamera != null){
            mCamera.release();        // release the camera for other applications
            mCamera = null;
        }
    }

    public static Camera getCameraInstance(){                           
        Camera cam1 = null;
        try {
            int num_of_cameras = Camera.getNumberOfCameras();
            for (int i=0; i<num_of_cameras; i++) {
                Log.d(TAG, "[My Debugging message] Camera loop: i is " + i + " properties are: ");
            }
            cam1 = Camera.open(); // attempt to get a Camera instance
        }
        catch (Exception e){
            // Camera is not available (in use or does not exist)
            Log.d(TAG, "[My Debugging message] Error Opening the camera !! error message: " + e.getMessage());
            e.printStackTrace();
        }
        //addition: use "camera parameters" or "camera info" to validate information about the camera
        // end addition
        if (cam1 == null) {
            Log.d(TAG, "[My Debugging message] received a NULL camera !!! ");
        }
        return cam1; // returns null if camera is unavailable
    }



    private static final String TAG = "CameraActivity";


    Context context = this;
    private Camera.PictureCallback mPicture = new Camera.PictureCallback() {

        @Override
        public void onPictureTaken(byte[] data, Camera camera) {

            if (numOfPicturesTakenUpTo25PPS >= 25) {            ///only 25 pictures per second. so if we want to capture 2 seconds before button pressed - than //TODO: we need to make it 50 PPS
                numOfPicturesTakenUpTo25PPS = 0;
            }

            File pictureFile = new File(getFilesDir() + File.separator + "IMG_" + numOfPicturesTakenUpTo25PPS + ".bmp");
            String pictureFilename = "IMG_" + numOfPicturesTakenUpTo25PPS + ".bmp";  //used later for the log.

            numOfPicturesTakenUpTo25PPS++;

            if (pictureFile == null) {
                Log.d(TAG, "[My Debugging message] Error creating media file, check storage permissions");
                //no path to picture, return
                isItSafeToTakePicture = true;
                return;
            }

            try {

                FileOutputStream fos = new FileOutputStream(pictureFile);
                fos.write(data);
                fos.close();

            } catch (FileNotFoundException e) {
                Log.d(TAG, "[My Debugging message] File not found: " + e.getMessage());
                e.printStackTrace();
            } catch (IOException e) {
                Log.d(TAG, "[My Debugging message] Error accessing file: " + e.getMessage());
                e.printStackTrace();
            } catch (Exception e) {
                Log.d(TAG, "[My Debugging message] other error:  " + e.getMessage());
                e.printStackTrace();
            }

            //if we got here with no exceptions:
            Log.d(TAG, "[My Debugging message] File saved [supposedly]: " + pictureFilename + " at " + getFilesDir()); 
            //finished saving picture, it is now safe to take a new picture
            isItSafeToTakePicture = true;

            //WARNING - these next few lines are a test
            camera.release();
            camera = null;
        }
    };



    //----------------------------------------------------------------------------------------------------------------//
    //------------------------------------------ Camera Preview Section ----------------------------------------------//
    //----------------------------------------------------------------------------------------------------------------//

    public class CameraPreview extends SurfaceView implements SurfaceHolder.Callback {              ///TODO: how to fix this shit right here ?:
        private SurfaceHolder mHolder;
        private Camera mCamera;

        // CTOR ?
        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();
                isItSafeToTakePicture = true;
            } catch (IOException e) {
                Log.d(TAG, "[My Debugging message] Error starting camera preview: " + e.getMessage());
                e.printStackTrace();
            } catch (Exception e) {
                Log.d(TAG, "[My Debugging message] Error starting camera preview: " + e.getMessage());
                e.printStackTrace();
            }

        }

        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
                Log.d(TAG, "[My Debugging message] preview surface does not exist [CameraPreview.java]");
                return;
            }
            // stop preview before making changes
            try {
                mCamera.stopPreview();
            } catch (Exception e) {
                // ignore: tried to stop a non-existent preview
                Log.d(TAG, "[My Debugging message] Error STOPPING camera preview: " + e.getMessage());
                e.printStackTrace();
            }
            // set preview size and make any resize, rotate or
            // reformatting changes here


            // start preview with new settings
            try {
                mCamera.setPreviewDisplay(mHolder);
                mCamera.startPreview();
                isItSafeToTakePicture = true;
            } catch (Exception e) {
                Log.d(TAG, "[My Debugging message] Error starting camera preview: " + e.getMessage());
                e.printStackTrace();
            }
        }

        ///-----------------------------------------------------------------------------------------------------///
    }
    }

Заранее спасибо.

...