Android store and load Image from gallery - android

I am currently allowing my user to pick an image from the gallery and I load it in an ImageView. Then I store in my sharedPreferences the URI of the image in order to be able to load it again later.
It won't work, and I've noticed that somehow the URI of the picture changed.
I was wondering how to simply store the Image I got from the gallery to be able to reload it later.

Then I store in my sharedPreferences the URI of the image in order to be able to load it again later.
That is not going to work. Not only might the Uri differ, but if the Uri has a content scheme, you lose the rights to work with the content identified by the Uri after your process ends. Plus, the user might get rid of the image.
I was wondering how to simply store the Image I got from the gallery to be able to reload it later.
Use Java I/O to make a copy of the image to a file that you control (e.g., on internal storage), then use that copy. Adjust your UI to reflect this (e.g., use verbs like "import" instead of "link").
Depending on how you got that Uri, you might be able to call takePersistableUriPermission() to try to get long-term rights to the content, in which case the Uri also should be stable (assuming that the user does not move or delete the content in question).

Better to store image path in shared preferences, then reload it again

Related

Android 11 URI usage (file:// content://)

We have some old issues with similar words, but most of them are about converting one or the other.
What I'm looking here is the "Right" behaviour of URI usage with the new changes. Let me give some context:
Before when we get an image URI this would return file://... format.
But since the new OS permissions changes, where we should not use WRITE_EXTERNAL_STORAGE anymore we should use getUriForFile(..) that return content://... path.(Scope Storage usage Android 11 Storage FAQ)
This can be spot on some Android guides, like: taken photos guide
The "problem" is that many users got used to use the URI of a crop image (for example) to create a file of it and save it.
Now, with this changes come the question:
How should we use the URI?
Make some code to check Android version and if more than 29 we should create a new file path for the URI?
Let the URI be the path to the image (content of file) and if someone wanna save it would need to create it own file path
Something else that I don't get yet about how to use URI right.
Obs: Asking this, because of a Android Image Crop open source project handover, where we need to upgrade the permissions for Android 10/11 but now we have this content/file issue. More here
Edit:
As pointed on the comments
Code returning file:// (not valid anymore since the changes)
Uri outputFileUri = null;
outputFileUri = Uri.fromFile(
new File(context.getExternalCacheDir().getPath(),
"pickImageResult.jpeg")
);
Code returning content://
outputFileUri = FileProvider.getUriForFile(
context,
context.getPackageName() + CommonValues.authority,
File.createTempFile("pickImageResult", ".jpeg", getImage)
);
The "problem" is that many users got used to use the URI of a crop image (for example) to create a file of it and save it.
In the end, this is your library, and you need to document what any Uri that you return is suitable for. After all, a Uri could point to:
A file on the filesystem (file)
A Web resource (https, or possibly http)
An Android resource (android.resource)
An asset in the app (file://android_asset)
Some arbitrary set of bytes (content)
Your library is for image cropping. While I have not examined the implementation, I assume that it all works inside the app itself. If so, there is nothing wrong with returning a file Uri, if you want to do so. Your code is writing a file somewhere (e.g., getCacheDir() on Context). The app using your library must have access to that file, or else you would have crashed trying to write it. A Uri created via Uri.fromFile(), for that file, is perfectly fine... in that app.
Where Uri.fromFile() becomes a problem is in passing the Uri to another app. However, your library is for cropping images, not sharing content with other apps. Your job, IMHO, is to give a cropped image back to the app. What the app does with it is up to that app, subject to whatever limitations there are in the Uri that you hand over.
The two options that you seem to be considering have different issues:
Uri Source
Advantages
Disadvantages
Uri.fromFile()
Cheap, easy
Can only be used within the app itself; cannot be passed to other apps
FileProvider
Uri can be passed to other apps
Requires a library and manifest configuration; cannot readily get to the underlying file
Since IMHO an image cropper is not an image sharing solution, Uri.fromFile() seems reasonable. If the app using your library wants to turn around and share the cropped image, they would set up FileProvider themselves and use FileProvider.getUriForFile(). The only catch is that either you need to document where the file will be written or give them an option to tell you what directory to use — that information will be needed to set up the FileProvider metadata.
Someday, if you elect to change the API, you might consider returning an ordinary File instead of a Uri. That way, there is no confusion about what it represents.
But, in the end, this is all your decision. If you want to use FileProvider, or you want to upload images to your own Web server and use https, that is all up to you. However, you should document what you are doing and what the Uri represents.

Cordova camera changes filename after saving to gallery on iOS

i am using the cordova camera plugin and saving images to the gallery/photos so they don't delete as prior to this my photos would be saved to the cache and delete quickly enough.
I attach the images i take and save with camera plugin to an email.
What i do is save the ImageURI from the camera function to localstorage to be called again if i resend the email at a later date.
This method works in the short-term and images attach successfully but not after a few hours.
The imageURI of captured images is usually on the format of cdv_photo_001.jpg for example.
However, the images are saved in photos/gallery and the filenames tend to be normal "IMG_0001.JPG" format and don't attach to the email.
is there a way i can get the actual gallery name while taking a picture.
Ive tried to save the image persistently using some guides but i could never get the moveTo to work.
Anyone any ideas?
Thanks

How can I utilize a persisted URI with apps that don't support ACTION_OPEN_DOCUMENT

My app allows a user to select media (images, video, audio) from whatever is their favorite app for navigating these documents. I then store the URI to that image (rather than downloading the entire image) into a db. On restart of the app, I need to utilize these URIs to pull thumbnails and for images, the complete image from the URIs in order to show them in the app.
I have read the various posts and the docs about using ACTION_OPEN_DOCUMENT initially, granting the appropriate URI permissions, then using takePersistableUriPermission on the resolver.
All that works great. The problem is, there are a lot of apps in the world that manage media choosing that don't support ACTION_OPEN_DOCUMENT, but that do support ACTION_GET_CONTENT.
What I want to do:
Provide a list of apps to allow the user to choose which one they have loaded that can find media for them they want to use in my app.
Use the selected app to choose the media.
Persist the URI of that media to a db so I can utilize it later.
This works perfectly when implementation of the initial intent for selecting the app to use to find the media is ACTION_OPEN_DOCUMENT.
I have no need to perform writes on the media - just open the selection (and utilize the resulting URIs chosen by the user), and store this URI for later usage.
How can I bridge the gap for needing persistent URI with apps that don't support a ACTION_OPEN_DOCUMENT intent?
If you want to use ACTION_GET_CONTENT:
Step #1: Make a copy of the data to some file that you control (open an InputStream on the content and copy the bytes to a FileOutputStream)
Step #2: Persist a Uri that points to your copy of the data
In other words, there is no guarantee that a Uri that you get back from ACTION_GET_CONTENT will be useful in five minutes, let alone five hours, five days, five weeks, etc.
Alternatively, integrate a file chooser library and limit yourself to files visible to you on the filesystem.

How do I pre-populate Glide cache?

I have an application that allows users to display photos. It is using Glide to download them.
When a user creates a photo locally, they can see it, instantly, in the application, because the app knows where the local file is.
Eventually, though, I have to upload the photo so that it is available to other users on other devices. All devices, including the one that created the photo now use the URI for the uploaded file. That means that the first time the device that created the photo views it, after it is uploaded, there is an annoying delay while the photo is downloaded again, redundantly. (After that is is in Glide's cache)
The application uploads the photo from the local file to its location behind the globally available URI. At that time it knows both the path to to local file and the URI from which it will, eventually, be downloaded.
I would love to be able, at that point, to pre-populate Glide's cache for the download URI, with the contents of the file. No redundant download; no annoying delay.
I've poked at Glide a little bit and I just don't see how to get it to do that.

Tracking an image after adding to media scanner (when an user selects it from the gallery)

I have an app that allows users to take images from their camera that get saved to the SD card and I run the media scanner on it so they are visible in the gallery. Users can also add images from the gallery.
I do some compression on the image before saving to SD card. So, when a user selects an image from gallery, if it was an image that was compressed and written by my app, I want to avoid it from getting compressed again. I was thinking of checking the image path to figure out if the image was from my app, but with URIs, I get strings like content://com.android.providers.media.documents/document/image%3A38691 and uri.getPath() doesn't seem to have the path.
What are my options to figure out if this image was from my app? Here are the things I can think of:
1) Uri uri = Uri.fromFile(file): This seems to be giving a value of file:///storage/emulated/0/Pictures/MyApp/image.jpg
2) Store a checksum of the data when I write to the SD card and check against this when I see the new image.
3) Somehow get the URI when the media scanner is run. Haven't figured out how to do this yet.
UPDATE: for option (3), looks like I can use a MediaScannerConnectionClient. Is this the best option? Store the path to URI mapping in a DB and refer to that each time the user adds a new image to my app from the gallery.

Categories

Resources