Capture Image from Camera and Display in Activity

前端 未结 16 1002
悲&欢浪女
悲&欢浪女 2020-11-21 06:43

I want to write a module where on a click of a button the camera opens and I can click and capture an image. If I don\'t like the image I can delete it and click one more i

16条回答
  •  旧巷少年郎
    2020-11-21 07:14

    Update (2020)

    Google has added a new ActivityResultRegistry API that "lets you handle the startActivityForResult() + onActivityResult() as well as requestPermissions() + onRequestPermissionsResult() flows without overriding methods in your Activity or Fragment, brings increased type safety via ActivityResultContract, and provides hooks for testing these flows" - source.

    The API was added in androidx.activity 1.2.0-alpha02 and androidx.fragment 1.3.0-alpha02.

    So you are now able to do something like:

    val takePicture = registerForActivityResult(ActivityResultContracts.TakePicture()) { success: Boolean ->
        if (success) {
            // The image was saved into the given Uri -> do something with it
        }
    }
    
    val imageUri: Uri = ...
    button.setOnClickListener {
        takePicture.launch(imageUri)
    }
    

    Take a look at the documentation to learn how to use the new Activity result API: https://developer.android.com/training/basics/intents/result#kotlin

    There are many built-in ActivityResultContracts that allow you to do different things like pick contacts, request permissions, take pictures or take videos. You are probably interested in the ActivityResultContracts.TakePicture shown above.

    Note that androidx.fragment 1.3.0-alpha04 deprecates the startActivityForResult() + onActivityResult() and requestPermissions() + onRequestPermissionsResult() APIs on Fragment. Hence it seems that ActivityResultContracts is the new way to do things from now on.


    Original answer (2015)

    It took me some hours to get this working. The code it's almost a copy-paste from developer.android.com, with a minor difference.

    Request this permission on the AndroidManifest.xml:

    
    

    On your Activity, start by defining this:

    static final int REQUEST_IMAGE_CAPTURE = 1;
    private Bitmap mImageBitmap;
    private String mCurrentPhotoPath;
    private ImageView mImageView;
    

    Then fire this Intent in an onClick:

    Intent cameraIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
    if (cameraIntent.resolveActivity(getPackageManager()) != null) {
        // Create the File where the photo should go
        File photoFile = null;
        try {
            photoFile = createImageFile();
        } catch (IOException ex) {
            // Error occurred while creating the File
            Log.i(TAG, "IOException");
        }
        // Continue only if the File was successfully created
        if (photoFile != null) {
            cameraIntent.putExtra(MediaStore.EXTRA_OUTPUT, Uri.fromFile(photoFile));
            startActivityForResult(cameraIntent, REQUEST_IMAGE_CAPTURE);
        }
    }
    

    Add the following support method:

    private File createImageFile() throws IOException {
        // Create an image file name
        String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date());
        String imageFileName = "JPEG_" + timeStamp + "_";
        File storageDir = Environment.getExternalStoragePublicDirectory(
                Environment.DIRECTORY_PICTURES);
        File image = File.createTempFile(
                imageFileName,  // prefix
                ".jpg",         // suffix
                storageDir      // directory
        );
    
        // Save a file: path for use with ACTION_VIEW intents
        mCurrentPhotoPath = "file:" + image.getAbsolutePath();
        return image;
    }
    

    Then receive the result:

    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        if (requestCode == REQUEST_IMAGE_CAPTURE && resultCode == RESULT_OK) {
            try {
                mImageBitmap = MediaStore.Images.Media.getBitmap(this.getContentResolver(), Uri.parse(mCurrentPhotoPath));
                mImageView.setImageBitmap(mImageBitmap);
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
    

    What made it work is the MediaStore.Images.Media.getBitmap(this.getContentResolver(), Uri.parse(mCurrentPhotoPath)), which is different from the code from developer.android.com. The original code gave me a FileNotFoundException.

提交回复
热议问题