Android Camera

7 minute read

AndroidManifest.xml

    <!-- Camera -->
    <uses-permission android:name="android.permission.CAMERA" />
    <!--<uses-permission android:name="android.permission.FLASHLIGHT" />-->

    <uses-feature android:name="android.hardware.camera" android:required="true"/>
    <uses-feature android:name="android.hardware.camera.autofocus"  android:required="false"/>
    <uses-feature android:name="android.hardware.camera.front" android:required="true" />

MainActivity.java

    Activity mActivity = this;

    // ----------------------------------------------
    // Permission
    // ----------------------------------------------
    static final int REQUEST_CAMERA = 1;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        // TODO Auto-generated method stub
        super.onCreate(savedInstanceState);

        grantPermission(android.Manifest.permission.CAMERA, REQUEST_CAMERA);
    }

    @Override
    protected void onDestroy() {
        // TODO Auto-generated method stub

        if (mCamera != null) {
            mCamera.stopPreview();
            mCamera.release();
            mCamera = null;
        }

        super.onDestroy();
    }

    ShutterCallback cameraShutterCallback = new ShutterCallback() {
        @Override
        public void onShutter() {
            // TODO Auto-generated method stub
        }
    };

    PictureCallback cameraPictureCallbackRaw = new PictureCallback() {
        @Override
        public void onPictureTaken(byte[] data, Camera camera) {
            // TODO Auto-generated method stub
        }
    };

    PictureCallback cameraPictureCallbackJpeg = new PictureCallback() {
        @Override
        public void onPictureTaken(byte[] data, Camera camera) {
            // TODO Auto-generated method stub

            Bitmap bm = null;

            if (data != null) {
                try {
                    BitmapFactory.Options opt;

                    opt = new BitmapFactory.Options();
                    opt.inTempStorage = new byte[16 * 1024];
                    Camera.Parameters parameters = camera.getParameters();
                    Camera.Size size = parameters.getPictureSize();

                    int height11 = size.height;
                    int width11 = size.width;
                    float mb = (width11 * height11) / 1024000;

                    if (mb > 4f)
                        opt.inSampleSize = 4;
                    else if (mb > 3f)
                        opt.inSampleSize = 2;

                    bm = BitmapFactory.decodeByteArray(data, 0, (data != null) ? data.length : 0, opt);
//                    bm = BitmapFactory.decodeByteArray(data, 0, (data != null) ? data.length : 0);

                    if (getResources().getConfiguration().orientation == Configuration.ORIENTATION_PORTRAIT) {
                        Matrix mtx = new Matrix(); // cf. mtx.setScale(-1, 1); // reverse right and right
                        mtx.postRotate(270);
                        bm = Bitmap.createBitmap(bm, 0, 0, bm.getWidth(), bm.getHeight(), mtx, false);
                    }

                } catch(Exception e) {
                    Log.e(TAG, "ERROR:Failed to capture " + e.getMessage());
                }
            }

            // change size
//            //Bitmap bmap = Bitmap.createBitmap(screenWidth, screenHeight, Bitmap.Config.ARGB_8888);
//
//            Canvas canvas = new Canvas(bmap);
//            canvas.drawBitmap(bm, 0f, 0f, null);
//
//            //FrameLayout layout = (FrameLayout)findViewById(R.id.am_fl_main);
//            RelativeLayout layout = (RelativeLayout)findViewById(R.id.containerImg);
//            Bitmap bitmap = Utils.GetBitmapScreenshot(layout);
//            canvas.drawBitmap(bitmap, 0f, 0f, null);

            if (mPlaying == true) {
                SaveCapturedImage(bm); // Use original image
                camera.startPreview();
            }

            if (mProgressDialog != null)
                mProgressDialog.dismiss();
        }
    };


    /**
     * 이미지를 저장함
     * @param newImage
     */
    private void SaveCapturedImage(Bitmap newImage) 
    {
        if (newImage == null) return;

        //String storagePath = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DCIM).getAbsolutePath();
        String storagePath = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES).getAbsolutePath();

        Date now = new Date();
        SimpleDateFormat format = new SimpleDateFormat("yyyyMMdd_HHmmss");
        String FileName = String.format("yourapp_%s.jpg", format.format(now));

        try {
            File file = new File(storagePath, FileName);

            FileOutputStream out = new FileOutputStream(file);
            newImage.compress(Bitmap.CompressFormat.JPEG, 80, out);

            out.flush();
            out.close();

            // Enable to show in the Gallery
            Intent mediaScan = new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE);
            Uri uriSavedImage = Uri.fromFile(file);
            mediaScan.setData(uriSavedImage);
            sendBroadcast(mediaScan);
//            galleryAddPic();

            Toast.makeText(context, context.getResources().getString(R.string.msg_capture), Toast.LENGTH_LONG).show();

        } catch (FileNotFoundException e) {
            Log.e(TAG, "ERROR:FileNotFoundException :" + e.toString());
            e.printStackTrace();
        } catch (IOException e) {
            Log.e(TAG, "ERROR:IOException :" + e.toString());
            e.printStackTrace();
        } finally {
            newImage.recycle();
            newImage = null;
        }
    }


    /**
     * Enable to show in the Gallery
     */
    private void galleryAddPic() {
        Intent mediaScanIntent = new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE);
        File f = new File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES).getAbsolutePath());
        Uri contentUri = Uri.fromFile(f);
        mediaScanIntent.setData(contentUri);
        this.sendBroadcast(mediaScanIntent);
    }

    /**
     * Capture screen shot
     */
    private boolean CaptureScreen(PictureCallback handler) {

        // Progress dialog
        mProgressDialog = new ProgressDialog(this);
        mProgressDialog.setIndeterminate(false);  // false로 하면 back button으로 취소 불가
        mProgressDialog.setProgressStyle(ProgressDialog.STYLE_SPINNER);

        // show progress dialog
        mProgressDialog.setMessage(context.getResources().getString(R.string.msg_capturing));
        mProgressDialog.show();

        // grant permission
        if (grantPermission(android.Manifest.permission.WRITE_EXTERNAL_STORAGE, REQUEST_WRITE_EXTERNAL_STORAGE) == true)
        {
            if (mCamera != null) {
                // 셔터후, Raw 이미지 생성후, JPE 이미지 생성후
                try  {
                    mCamera.takePicture(null, null, handler);
                } catch (Exception e) {
                    Log.e(TAG, "Failed to capture screen. - " + e.getMessage() + e.getStackTrace());
                    if (mProgressDialog != null)
                        mProgressDialog.dismiss();
                }
                return true;
            }
        }

        if (mProgressDialog != null)
            mProgressDialog.dismiss();

        return false;
    }

    /**
     * Camera Zoom
     * @param level
     */
    private void changeZoom(int level) {
        try {
            if (mPlaying == false) {
                mPlaying = true;
                if (mCamera != null) mCamera.startPreview();
//                mImageButton_PlayPause.setPressed(false);
                if(Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN) {
                    mImageButton_PlayPause.setBackgroundDrawable( getResources().getDrawable(R.drawable.button_selector) );
                } else {
                    mImageButton_PlayPause.setBackground( getResources().getDrawable(R.drawable.button_selector));
                }
                mImageButton_PlayPause.setImageResource(R.drawable.ic_pause_white_48dp);
            }

            try {
                if (mCamera == null) return;
                Camera.Parameters parameters = mCamera.getParameters();
                if (parameters.isZoomSupported()) {
                    parameters.setZoom(level);
                    mCamera.setParameters(parameters);

                    mCfgInfo.ZoomLevel = level;
                    mSeekBar_Zoom.setProgress(level);

                    try {
                        if (parameters.isSmoothZoomSupported()) {
                            mCamera.startSmoothZoom(level);
                        }
                    } catch (Exception ee) {

                    }
                }
            } catch (Exception e) {

            }
        }
        catch (Exception e) {
            Toast.makeText(getBaseContext(), "Failed to change zoom : " + e.getMessage(), Toast.LENGTH_SHORT).show();
            e.printStackTrace();
        }
    }

    /**
     * Camera Brightness
     * @param level
     */
    private void changeBrightness(int level) {
        try {
            if (mCamera == null) return;
            Camera.Parameters parameters = mCamera.getParameters();
            parameters.setExposureCompensation(level);
            mCamera.setParameters(parameters);
        }
        catch (Exception e) {
            Toast.makeText(getBaseContext(), "Failed to change brightness : " + e.getMessage(), Toast.LENGTH_SHORT).show();
            e.printStackTrace();
        }
    }

    /**
     * Change Camera focus
     */
    private void changeFocus() {
        if (mPlaying == false) {
            mPlaying = true;
            if (mCamera != null) mCamera.startPreview();
//                mImageButton_PlayPause.setPressed(false);
            if(Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN) {
                mImageButton_PlayPause.setBackgroundDrawable( getResources().getDrawable(R.drawable.button_selector) );
            } else {
                mImageButton_PlayPause.setBackground( getResources().getDrawable(R.drawable.button_selector));
            }
            mImageButton_PlayPause.setImageResource(R.drawable.ic_pause_white_48dp);
        }

        new Handler().postDelayed(new Runnable() {
            public void run()
            {
                try {
                    if (mCamera != null) {
                        Camera.Parameters p = mCamera.getParameters();
                        List<String> focusModes = p.getSupportedFocusModes();

                        if(focusModes != null && focusModes.contains(Camera.Parameters.FOCUS_MODE_AUTO)) {
                            mCamera.autoFocus(null);    // auto-focus now
                        }
                    }
                } catch (Exception e) {
                    e.printStackTrace();
                    Toast.makeText(getBaseContext(), "Failed to change autoFocus.", Toast.LENGTH_SHORT).show();
                }
            }
        }, 100);
    }
    /**
     * SurfaceHolder.Callback - surfaceChanged
     */
    @Override
    public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
        // TODO Auto-generated method stub

//        if (mCamera != null)
//            mCamera.startPreview(); // begin the preview
//        else
//            return;

        if (mCamera == null) return;

        if (mPreviewing) {
            if (mCamera != null)
                mCamera.stopPreview();
            mPreviewing = false;
        }

        final Camera.Parameters parameters = mCamera.getParameters();

        try {
            mPreviewing = true;
            if (parameters.getFocusMode().equals(Camera.Parameters.FOCUS_MODE_CONTINUOUS_PICTURE))
            {
                parameters.setFocusMode(Camera.Parameters.FOCUS_MODE_CONTINUOUS_PICTURE);
            }

            if (mCamera != null) {
                List<String> lModes = parameters.getSupportedFocusModes();
                if (lModes != null)
                {
                    if (lModes.contains(Camera.Parameters.FOCUS_MODE_AUTO))
                    {
                        parameters.setFocusMode(Camera.Parameters.FOCUS_MODE_AUTO); // auto-focus mode if supported
                        mCamera.setParameters(parameters);        // set parameters on device
                    }
                }

                mCamera.setParameters(parameters);
                mCamera.setPreviewDisplay(holder);
                mCamera.startPreview();
                changeFocus();
            }
        }
        catch (IOException e) {
            Log.v(TAG, "ERROR:checking :" + e.toString());
        }
    }

    /**
     * SurfaceHolder.Callback - surfaceCreated
     */
    @Override
    public void surfaceCreated(SurfaceHolder holder) {
        // TODO Auto-generated method stub
        try {
//            openFrontFacingCamera();
            if (mCamera == null)
                mCamera = Camera.open(Camera.CameraInfo.CAMERA_FACING_FRONT);
            SetCameraDisplayOrientation(this, Camera.CameraInfo.CAMERA_FACING_FRONT, mCamera); // Front

            Camera.Parameters parameters = mCamera.getParameters();
            mCfgInfo.MaxZoomLevel = parameters.getMaxZoom();
            mSeekBar_Zoom.setMax(mCfgInfo.MaxZoomLevel);

//            int initZoomLevel = 0;
            changeZoom(mCfgInfo.ZoomLevel);
//            mSeekBar_Zoom.setProgress(mCfgInfo.ZoomLevel);

        } catch (RuntimeException e) {
            Log.e(TAG, "Device camera is not working properly. - " + e.getMessage());
        }
    }

    /**
     * SurfaceHolder.Callback - surfaceDestroyed
     */
    @Override
    public void surfaceDestroyed(SurfaceHolder holder) {
        // TODO Auto-generated method stub
        if (mCamera != null) {
            mCamera.stopPreview();
            mCamera.release();
            mCamera = null;
        }
        mPreviewing = false;
    }

    public static void SetCameraDisplayOrientation(Activity activity, int cameraId, Camera camera) {
        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;
        }
        camera.setDisplayOrientation(result);

        Camera.Parameters params = camera.getParameters();
        params.setRotation(result);
//        params.setFocusMode(Camera.Parameters.FOCUS_MODE_MACRO);
    }

    /**
     * request permission
     * @param perm_str android.Manifest.permission.xxx
     * @param req_code REQUEST_xxx
     */
    private boolean grantPermission(String perm_str, int req_code) {
        int permission = ContextCompat.checkSelfPermission(mActivity, perm_str);
        if(permission != PackageManager.PERMISSION_GRANTED) {
            ActivityCompat.requestPermissions(mActivity, new String[]{perm_str}, req_code);
            return false;
        }
        return true;
    }

    /**
     * Receive permission result
     * @param requestCode
     * @param permissions
     * @param grantResults
     */
    @Override
    public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
        super.onRequestPermissionsResult(requestCode, permissions, grantResults);

        int idx;
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
            switch (requestCode) {
                case REQUEST_CAMERA:
                    for (idx = 0; idx < permissions.length; idx++) {
                        String permission = permissions[idx];
                        int grantResult = grantResults[idx];
                        if (permission.equals(android.Manifest.permission.CAMERA) && grantResult == PackageManager.PERMISSION_GRANTED) {
                            Log.v(TAG, "CAMERA Permitted");

                            // Restart this application
                            PackageManager packageManager = context.getPackageManager();
                            Intent intent = packageManager.getLaunchIntentForPackage(context.getPackageName());
                            ComponentName componentName = intent.getComponent();
                            Intent mainIntent = Intent.makeRestartActivityTask(componentName);
                            context.startActivity(mainIntent);
                            System.exit(0);
                            break;
                        }
                    }
                    if (idx == permissions.length) {
                        ShowEndProgram(); // End this program
                    }
                case REQUEST_WRITE_EXTERNAL_STORAGE:
                    for (idx = 0; idx < permissions.length; idx++) {
                        String permission = permissions[idx];
                        int grantResult = grantResults[idx];
                        if (permission.equals(android.Manifest.permission.WRITE_EXTERNAL_STORAGE) && grantResult == PackageManager.PERMISSION_GRANTED) {
                            Log.v(TAG, "WRITE_EXTERNAL_STORAGE Permitted");
                            break;
                        }
                    }
            }
        }
    }

    /**
     * Confirm stop or not
     */
    private void ShowEndProgram() {
        if (mActivity.isFinishing()) return; // to prevent BadTokenException

        if (ActivityCompat.shouldShowRequestPermissionRationale(this, android.Manifest.permission.CAMERA)) {
            showToastLong(getResources().getString(R.string.msg_need_camera_permission));
            startInstalledAppDetailsActivity(mActivity);
            finish();
        }
    }

    /**
     * Shows a {@link Toast} on the UI thread.
     *
     * @param text The message to show
     */
    private void showToastLong(final String text) {
        final Activity activity = mActivity;
        if (activity != null) {
            activity.runOnUiThread(new Runnable() {
                @Override
                public void run() {
                    Toast.makeText(activity, text, Toast.LENGTH_LONG).show();
                }
            });
        }
    }

    private void delayedStopPreView(int delayMillis) {
        if (mPauseHandler == null)  mPauseHandler = new Handler();
        mPauseHandler.removeCallbacks(mPauseRunnable);
        mPauseHandler.postDelayed(mPauseRunnable, delayMillis);
    }

    private final Runnable mCaptureRunnable = new Runnable() {
        @Override
        public void run() {
            CaptureScreen(cameraPictureCallbackJpeg);
//            CaptureScreen(mPictureTest);
        }
    };

    private void delayedCapture(int delayMillis) {
        if (mPauseHandler == null)  mPauseHandler = new Handler();
        mPauseHandler.removeCallbacks(mCaptureRunnable);
        mPauseHandler.postDelayed(mCaptureRunnable, delayMillis);
    }

Tags:

Categories:

Updated:

Leave a comment