Android Camera Intent: how to get full sized photo?

前端 未结 7 1455
遇见更好的自我
遇见更好的自我 2020-11-22 16:35

I am using intent to launch camera:

Intent cameraIntent = new Intent(
    android.provider.MediaStore.ACTION_IMAGE_CAPTURE);
getParent().startActivityForResu         


        
相关标签:
7条回答
  • 2020-11-22 16:53

    I also used the answer from Vicky but I had to save the uri to a bundle to avoid loss of it on orientation change. So if you don't get a result from your intent after tilting the device it might be because your uri did not survive the orientation change.

    static final int CAMERA_CAPTURE_REQUEST = 1;
    static final String ARG_CURRENT_PIC_URI = "CURRENT_PIC_URI";
    
    
    String pictureImagePath = folderName + "/" + imageFileName;
    File file = new File(Environment.getExternalStorageDirectory(), pictureImagePath);
    Uri outputFileUri = Uri.fromFile(file);
    
    mCurrentPicUri = outputFileUri.getPath();
    
    Intent cameraIntent = new Intent(android.provider.MediaStore.ACTION_IMAGE_CAPTURE);
    cameraIntent.putExtra(MediaStore.EXTRA_OUTPUT, outputFileUri);
    startActivityForResult(cameraIntent, CAMERA_CAPTURE_REQUEST);
    

    Activity Result code:

    @Override
    public void onActivityResult(int requestCode, int resultCode, Intent data) {
    
      if (requestCode == CAMERA_CAPTURE_REQUEST && resultCode == Activity.RESULT_OK) 
      {
        File imgFile = new  File(mCurrentPicUri);
        // do something with your image
        // delete uri
        mCurrentPicUri = "";
      }
    }
    

    save the uri to the bundle:

    @Override
    public void onSaveInstanceState(Bundle outState) {
      super.onSaveInstanceState(outState);
      // save uri to bundle
      outState.putString(ARG_CURRENT_PIC_URI, mCurrentPicUri);
    }
    

    retrieve it from your saved bundle during on create:

    if (bundle.containsKey(ARG_CURRENT_PIC_URI))
      mCurrentPicUri = bundle.getString(ARG_CURRENT_PIC_URI);
    
    0 讨论(0)
  • 2020-11-22 16:55

    To get full sized camera image you should point camera to save picture in temporary file, like:

        private URI mImageUri;
    
        Intent intent = new Intent("android.media.action.IMAGE_CAPTURE");
        File photo;
        try
        {
            // place where to store camera taken picture
            photo = this.createTemporaryFile("picture", ".jpg");
            photo.delete();
        }
        catch(Exception e)
        {
            Log.v(TAG, "Can't create file to take picture!");
            Toast.makeText(activity, "Please check SD card! Image shot is impossible!", 10000);
            return false;
        }
        mImageUri = Uri.fromFile(photo);
        intent.putExtra(MediaStore.EXTRA_OUTPUT, mImageUri);
        //start camera intent
        activity.startActivityForResult(this, intent, MenuShootImage);
    
    private File createTemporaryFile(String part, String ext) throws Exception
    {
        File tempDir= Environment.getExternalStorageDirectory();
        tempDir=new File(tempDir.getAbsolutePath()+"/.temp/");
        if(!tempDir.exists())
        {
            tempDir.mkdirs();
        }
        return File.createTempFile(part, ext, tempDir);
    }
    

    Then after image capture intent finished to work - just grab your picture from imageUri using following code:

    public void grabImage(ImageView imageView)
    {
        this.getContentResolver().notifyChange(mImageUri, null);
        ContentResolver cr = this.getContentResolver();
        Bitmap bitmap;
        try
        {
            bitmap = android.provider.MediaStore.Images.Media.getBitmap(cr, mImageUri);
            imageView.setImageBitmap(bitmap);
        }
        catch (Exception e)
        {
            Toast.makeText(this, "Failed to load", Toast.LENGTH_SHORT).show();
            Log.d(TAG, "Failed to load", e);
        }
    }
    
    
    //called after camera intent finished
    @Override
    public void onActivityResult(int requestCode, int resultCode, Intent intent)
    {
        //MenuShootImage is user defined menu option to shoot image
        if(requestCode==MenuShootImage && resultCode==RESULT_OK) 
        {
           ImageView imageView;
           //... some code to inflate/create/find appropriate ImageView to place grabbed image
           this.grabImage(imageView);
        }
        super.onActivityResult(requestCode, resultCode, intent);
    }
    

    P.S. Code need to be revised with respect to new security restriction applied in Android M - FileProvider: mImageUri has to be packed with FileProvider

    0 讨论(0)
  • 2020-11-22 16:55

    Even though this is an old question and it has an accepted answer,
    I would like to share my solution.
    In this case you don't have to create a temporary file.
    Additionally we creating a chooser which offers to user both: take a picture with the camera or pick an existing one from a gallery.

        Intent galleryIntent = new Intent(Intent.ACTION_PICK, MediaStore.Images.Media.EXTERNAL_CONTENT_URI);
        Intent cameraIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
        Intent chooser = new Intent(Intent.ACTION_CHOOSER);
        chooser.putExtra(Intent.EXTRA_INTENT, galleryIntent);
        chooser.putExtra(Intent.EXTRA_TITLE, getString(R.string.chooseaction));
        Intent[] intentArray = {cameraIntent};
        chooser.putExtra(Intent.EXTRA_INITIAL_INTENTS, intentArray);
        startActivityForResult(chooser, RESULT_LOAD_IMAGE);
    

    and here we retrieving results:

    @Override
    public void onActivityResult(int requestCode, int resultCode, Intent data) {
        // todo use appropriate resultCode in your case
        if (requestCode == RESULT_LOAD_IMAGE && resultCode == FragmentActivity.RESULT_OK) {
            if (data.getData() != null) {
                // this case will occur in case of picking image from the Gallery,
                // but not when taking picture with a camera
                try {
                    Bitmap bitmap = MediaStore.Images.Media.getBitmap(getActivity().getContentResolver(), data.getData());
    
                    // do whatever you want with the Bitmap ....           
    
                } catch (IOException e) {
                    e.printStackTrace();
                }
            } else {
                // this case will occur when taking a picture with a camera
                Bitmap bitmap = null;
                Cursor cursor = getActivity().getContentResolver().query(MediaStore.Images.Media.EXTERNAL_CONTENT_URI,
                        new String[]{MediaStore.Images.Media.DATA, MediaStore.Images.Media.DATE_ADDED,
                                MediaStore.Images.ImageColumns.ORIENTATION}, MediaStore.Images.Media.DATE_ADDED,
                        null, "date_added DESC");
                if (cursor != null && cursor.moveToFirst()) {
                    Uri uri = Uri.parse(cursor.getString(cursor.getColumnIndex(MediaStore.Images.Media.DATA)));
                    String photoPath = uri.toString();
                    cursor.close();
                    if (photoPath != null) {
                        bitmap = BitmapFactory.decodeFile(photoPath);
                    }
                }
    
                if (bitmap == null) {
                    // for safety reasons you can
                    // use thumbnail if not retrieved full sized image
                    bitmap = (Bitmap) data.getExtras().get("data");
                }
                // do whatever you want with the Bitmap ....
            }
    
            super.onActivityResult(requestCode, resultCode, data);
        }
    }
    
    0 讨论(0)
  • 2020-11-22 16:55

    API Level 29

    I tried the accepted answer, but both Environment.getExternalStorageDirectory() used in the accepted answer and Environment.getExternalStoragePublicDirectory() used in a subsequent answer are deprecated in API level 29. So is the MediaStore.Images.Media.DATA used in the third answer deprecated in API level 29. The following code (in Kotlin) stores the full image in MediaStore as shown in this stackoverflow answer to a different question and doesn't rely on the FileProvider:

        var imageUri: Uri? = null
    
        fun takePhoto(view: View?) {
            val values = ContentValues()
            values.put(MediaStore.MediaColumns.DISPLAY_NAME, "myimage.jpg")
            values.put(MediaStore.MediaColumns.MIME_TYPE, "image/jpeg")
            values.put(MediaStore.MediaColumns.RELATIVE_PATH, Environment.DIRECTORY_PICTURES)
            imageUri = contentResolver.insert(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, values)
    
            val intent = Intent(MediaStore.ACTION_IMAGE_CAPTURE)
            intent.putExtra(MediaStore.EXTRA_OUTPUT, imageUri)
            startActivityForResult(intent, TAKE_PHOTO_REQUEST)
        }
    
    0 讨论(0)
  • 2020-11-22 17:05

    Don't use onActivityResult's data. It took me many hours to test different solutions. A camera saves a picture (even if you don't set permissions for camera and card reading in AndroidManifest), but then onActivityResult returns data == null and MediaStore returns wrong path. In these solutions you simply get last gallery image, not your photo.

    private Uri photoUri;
    
    @Override
    public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
        super.onRequestPermissionsResult(requestCode, permissions, grantResults);
    
        ...
    }
    
    @Override
    public void onActivityResult(int requestCode, int resultCode, Intent data) {
        super.onActivityResult(requestCode, resultCode, data);
    
        if (requestCode == CAMERA_RESULT) {
            if (resultCode == RESULT_OK) {
                if (photoUri != null) {
                    image.setImageURI(photoUri);
                }
            }
        }
    }
    
    private void showCamera() {
        Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
        if (intent.resolveActivity(getContext().getPackageManager()) != null) {
            File file = null;
            try {
                file = createImageFile();
            } catch (IOException e) {
                e.printStackTrace();
            }
            photoUri = null;
            if (file != null) {
                photoUri = Uri.fromFile(file);
                intent.putExtra(MediaStore.EXTRA_OUTPUT, photoUri);
                startActivityForResult(intent, CAMERA_REQUEST);
            }
        }
    }
    
    private File createImageFile() throws IOException {
        // Create an image file name
        String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date());
        File storageDir = getContext().getExternalFilesDir(Environment.DIRECTORY_PICTURES);
        // File storageDir = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES);
        return File.createTempFile(timeStamp, ".jpg", storageDir);
    }
    
    0 讨论(0)
  • 2020-11-22 17:12

    To capture maximum picture size from camera, i hope these simple steps will be quite useful

     public static Camera mCamera;
    
    Camera.Parameters parameters = mCamera.getParameters();
      parameters.getSupportedPictureSizes();
    List<Camera.Size> supportedSizes = parameters.getSupportedPictureSizes();
      mSizePicture1 = supportedSizes.get(0);
      int cameraSize = supportedSizes.size();
      mSizePicture2 = supportedSizes.get(cameraSize - 1);
    
        if (mSizePicture1.height < mSizePicture2.height)
           mSizePicture = supportedSizes.get(cameraSize - 1);
        else
           mSizePicture = supportedSizes.get(0);
    
    parameters.setPictureSize(mSizePicture.width, mSizePicture.height);
    

    Here, the supported size of the each mobile is taken, from that which size is maximum that is fixed as picture size to capture.

    0 讨论(0)
提交回复
热议问题