I created a button that lets the user choose between “Take picture with camera” and “Select picture from gallery”.
When the picture is taken/chosen, I then display it in an ImageView of the next activity which I do by passing the URI of the file created to store the taken/selected picture.
It works as expected when the user takes a picture with his camera but when he selects an image from gallery, no image is shown in the next activity despite both intents (take a picture and select a picture) being coded the same.
My question(s): Why isn’t the image displayed in the next activity ONLY when picked from the gallery ? Or how should I proceed to display it ?
Intent to open camera (working fine):
private void openCameraToTakePictureIntent() { Log.d(TAG, "Method for Intent Camera started"); Intent takePictureIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE); // Ensure that there's a camera activity to handle the intent if (takePictureIntent.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 } if (photoFile != null) { Uri photoURI = FileProvider.getUriForFile(this, "com.emergence.pantherapp.fileprovider", photoFile); takePictureIntent.putExtra(MediaStore.EXTRA_OUTPUT, photoURI); startActivityForResult(takePictureIntent, REQUEST_IMAGE_CAPTURE); } } }
Intent to access gallery and pick an image:
private void openGalleryIntent() { Log.d(TAG, "Method for Intent Gallery started"); Intent galleryIntent = new Intent(Intent.ACTION_PICK, MediaStore.Images.Media.INTERNAL_CONTENT_URI); if (galleryIntent.resolveActivity(getPackageManager()) != null) { File photoFile = null; try { photoFile = createImageFile(); } catch (IOException ex) { // Error occurred while creating the File } if (photoFile != null) { Uri photoURI = FileProvider.getUriForFile(this, "com.emergence.pantherapp.fileprovider", photoFile); galleryIntent.putExtra(MediaStore.EXTRA_OUTPUT, photoURI); startActivityForResult(galleryIntent, PICK_IMAGE); } } }
Then here’s the onActivityResult: (currentPhotoPath is the absolute path of the file created to store the image)
@Override protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) { super.onActivityResult(requestCode, resultCode, data); if (resultCode == Activity.RESULT_OK && requestCode == 1) { Log.d(TAG, currentPhotoPath); Intent intent = new Intent(this, ModifyPictureActivity.class); intent.putExtra("USER_IMAGE", currentPhotoPath); startActivity(intent); } else if (resultCode == Activity.RESULT_OK && requestCode == 2) { Log.d(TAG, currentPhotoPath); Intent intent = new Intent(this, ModifyPictureActivity.class); intent.putExtra("USER_IMAGE", currentPhotoPath); startActivity(intent); } }
Below is how the image is displayed in the following activity:
@Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_modify_picture); Intent intent = getIntent(); String imageUri = intent.getStringExtra("USER_IMAGE"); if (imageUri != null) { Log.d(TAG, imageUri); } else { Log.d(TAG, "imageUri was null"); } image = findViewById(R.id.picture); image.setImageURI(Uri.parse(imageUri)); }
I made sure to have the READ_EXTERNAL_STORAGE in the manifest and the xml layout is just set to “match_parent” for height and width but I can add them if it’s relevant.
Advertisement
Answer
Few Intent
actions use EXTRA_OUTPUT
. Mostly, that is an ACTION_IMAGE_CAPTURE
thing.
More typically, an Intent
for getting a piece of content (ACTION_PICK
, ACTION_GET_CONTENT
, ACTION_OPEN_DOCUMENT
, ACTION_CREATE_DOCUMENT
, ACTION_OPEN_DOCUMENT_TREE
, etc.) return a Uri from the content supplier in the
Intentdelivered to
onActivityResult(). Given your implementation, that would be
data.getData()to get that
Uri`.
You can then use a ContentResolver
and openInputStream()
to get an InputStream
on the content identified by the Uri
. In your case, for example, you could use that InputStream
to copy the bytes to a FileOutputStream
to make your own local copy of the content.
Note that you only have short-term access to the content identified by the Uri
.