I have got the URI of an Image in an Activity for example: ImageActivity and set the URI to an object named Item.
val item = Item()
item.imageURI = uri
Now, I have got the returned result from ImageActivity to for example: UploadActivity.
Now, I want to upload the Item object that I got from ImageActivity from UploadActivity. I am uploading the image by encoding the Bitmap of the image to Base64. So, I need the Bitmap of the image.
I got that by this:
val bitmap = MediaStore.Images.Media.getBitmap(contentResolver, item.imageURI)
item.itemImage = imageToString(bitmap)
But it is showing error:
java.lang.SecurityException: Permission Denial: opening provider com.miui.gallery.provider.GalleryOpenProvider from ProcessRecord
How to solve this? Please elaborate on your answer as much as possible.
I am getting this image from Gallery
I am going to interpret this as meaning that you are using an Intent like ACTION_GET_CONTENT or ACTION_PICK.
If so, then by default, the only place that Uri can be used is in the activity instance that receives it (ImageActivity in your case).
Your options include:
Get rid of UploadActivity and do something else. For example, you could have the actual uploading be performed by a repository, with the UI handled by ImageActivity (directly, via fragments, etc.).
Pass the Uri to UploadActivity via the "data" facet of an Intent, plus include FLAG_GRANT_READ_URI_PERMISSION on that Intent
That second option would look something like:
startActivity(Intent(this, OtherActivity::class.java).setData(yourUri).addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION))
(where yourUri is your Uri)
Related
In my Android Manifest I registered my Activity for being able to "open" specific files.
This all works fine. When I receive the new Intent and read the file data from the intent via
BufferedReader(InputStreamReader(contentResolver.openInputStream(intent.data)))
it works fine.
However, for a better view flow, I wanted to store the URI of the intent and show it in another view (asking the user how to proceed with the file). So I store this intent.data as a String and open another view first.
However, once the view is opened, I bascially call the same thing
val br = BufferedReader(InputStreamReader(act.contentResolver.openInputStream(fileUri)))
but here I get an exception
java.lang.SecurityException: Permission Denial: reading [FileBrowserApp I used for "opening the file"] uri content://... from pid=5242, uid=10159 requires the provider be exported, or grantUriPermission()
So it feels like the URI is somehow expired or such thing? Is this actually the case? Do I have to read the file directly when I receive the Intent? I was hoping for a way to keep the URI until I want to read the file.
I found the issue. Turns out, it is not a problem of an expiring Intent or anything like that. Instead my own "processing" changed the path.
What I did was taking the incoming Intent data as Uri. Later I fetched the provider path from that Uri again. However this caused a transformation of the query (instead of leaving it as a String in the first place) breaking the path.
In short: the problem is the URL encoding/decoding.
The original intent path (opened via the TotalComander - hence the com.ghisler path) looked like this:
content://com.ghisler.files/tree/primary%3A/document/primary%3Astorage%2Femulated%2F0%2Fbackup.bak
However getting the path from the Uri the colons were decoded leaving an output path of this:
content://com.ghisler.files/tree/primary:/document/primary:storage/emulated/0/backup.bak
You can clearly see the different encoding. As a consequence the file path was simply not the same after fetching it from the Uri again. This was causing the Exception - not an invalidation of the intent.
I am trying to implement gallery functionality in kotlin with android studio using default component. The goal is to click a button and open the desired path as a common Intent .
I can't understand how it is possible that the emulator only opens recent images for me instead of the path I specified on the file provider.
enter image description here
The part of code that I'm using is :
fun dispatcherGalleryImage(){
try {
val uri: Uri = Uri.parse(Environment.getExternalStoragePublicDirectory(requireActivity().getExternalFilesDir(Environment.DIRECTORY_PICTURES).toString().replace("/storage/emulated/0", "")).path.toString())
Log.info(uri.toString())
val intent=Intent(Intent.ACTION_GET_CONTENT)
intent.type ="image/*"
startActivityForResult(intent, TAKE_GALLERY_IMAGE)
}catch (ex: Exception){
Log.info(ex.toString())
}
}
I can't understand how it is possible that the emulator only opens recent images for me instead of the path I specified on the file provider
First, you are not using uri, except to log its value.
Second, the string that you are passing to Uri.parse() is not a valid string representation of a Uri (use Uri.fromFile() for a File).
Third, you are not using FileProvider. And a file:/// Uri is largely useless on Android 7.0+, as it will trigger a FileUriExposedException if you pass it in an Intent.
Fourth, ACTION_GET_CONTENT does not take a Uri as input. It is unclear why you are using ACTION_GET_CONTENT when you already have the content.
If your objective is to let the user view the image in their desired image viewer, use ACTION_VIEW, and put the FileProvider-supplied Uri and concrete (non-wildcard) MIME type in the Intent.
I'm now writing an app using android studio. In the main activity, I wrote a function to take a photo by using camera, then I want to pass this photo to the second activity. In the second activity, I want to upload this photo to a web API, and the type of the uploaded image has to be "JPEG".
I'm not sure I should use bundle or not. Or should I use "URI"? But when I call this:
URI photo_uri = photo.toURI();
There would be some problem. I couldn't run it. How can I fix this? This is what I wrote now, I use bundle:
// photo -> photo_uri, "photo.toURI()" doesn't work
Intent intent = new Intent(this, Main4Activity.class);
intent.putExtra("URI", photo_uri);
startActivity(intent);
And how can I receive the data(in JPEG type) in another activity?
You can send the file or uri path to second activity. After getting file or uri path you can convert that path into the file and upload it on the server.
You should check the Android docs about using the camera, there you have how to get the Uri, you must NEVER try to share the Bitmap itself.
About passing data between activities, you should use the Bundle so check this doc about Parcelables and Bundles which is the way to share data.
Regards!
Can we pass image and an image URI to other activity in same application using bundle?suggest me some way to do that?
USAGE :actually i have made an activity that crop an image taken from camera or from image stored in SD card depends upon the user.
and another app that uses a background image and a border image both are overlay so as to see PHOTOFRAME.
So now I want to combine both app so that the cropped image come from first app should become the background image for the second app.ie comes in photoframe.How can i do that?
Once you save your image in SD card
use this to cal the other activity.
final Intent intent = new Intent(MyClass.this, TargetClass.class);
final String root = Environment.getExternalStorageDirectory().getAbsolutePath();
intent.setData(Uri.parse(root + "/my/image/path/image.png"));
startActivity(intent);
if you are the reciever then you can get the path by calling
Uri path = getIntent().getData();
in the onCreate of the recieving activity. this is the standard way of checking for path by other activities.
Yes you can pass URI object,see putParcelable method in http://developer.android.com/reference/android/os/Bundle.html, URI already implements Parcelable interface,you can use corresponding get methods to get it.If any object that implements Parcelable interface then we can pass it using Bundle.
I'm trying to use a standard Intent that will take a picture, then allow approval or retake. Then I want to save the picture into a file.
Here's the Intent I am using:
Intent intent = new Intent(android.provider.MediaStore.ACTION_IMAGE_CAPTURE );
startActivityForResult( intent, 22 );
The documentation says:
The caller may pass an extra EXTRA_OUTPUT to control where this
image will be written. If the EXTRA_OUTPUT is not present, then a
small sized image is returned as a Bitmap object in the extra field. If
the EXTRA_OUTPUT is present, then the full-sized image will be
written to the Uri value of EXTRA_OUTPUT.
I don't pass extra output, I hope to get a Bitmap object in the extra field of the Intent passed into onActivityResult() (for this request). So where/how do you extract it? Intent has a getExtras(), but that returns a Bundle, and Bundle wants a key string to give you something back.
What do you invoke on the Intent to extract the bitmap?
Try calling getExtras().get("data") and casting the result to a Bitmap.
See here for an example.
On a related note, if you have the "crop" activity come up after taking the picture using intent.putExtra("crop", "true"), you'll get the cropped URI from getExtras().get("action").
I realize you've got this all fixed by now, just want to make sure no one tries to use this with crop and gets confused.
Reference: the apps-for-android LolCat activity.