Is it somehow possible to get a File object from an DocumentFile? With some small trick I can get the real path of the file, but the File class is not allowed to read/write there...
I need to access media files from USB OTG or secondary storage and I need following functions:
get exif data from images => I really need that for
getting the location of the image
getting the real creation date of the image
actually, for displaying purpose, I need all exif data
ability to rotate images (this would be possible by creating a temp image, delete the old one and rename the temp image)
Any idea on how to achieve that?
Is it somehow possible to get a File object from an DocumentFile?
No.
With some small trick I can get the real path of the file
Not reliably. After all, the Storage Access Framework does not require there to be an actual file. Various DocumentProvider implementations work off of cloud services, where the data is not stored locally on the device until needed. Beyond that, whatever approach that you are using is dependent upon internal implementation that may vary by device, let alone Android OS version. And, to top it off, you still cannot necessarily access the data even if you derive a path, as you may not have filesystem access to that location (e.g., files held on internal storage by the DocumentProvider).
get exif data from images
Use the stream, along with EXIF code that can work with streams, such as this one or this one, found by searching the Internet for android exif stream.
ability to rotate images (this would be possible by creating a temp image, delete the old one and rename the temp image)
You don't have a choice to make a local copy, rotate the image, and then write the image back to the original DocumentFile using an OutputStream. Whether that "local copy" is only in RAM, or needs to be an actual file on disk, depends a bit on how you were planning on rotating it.
Related
I have a use case, where I need to capture an image file using MediaStore.ACTION_IMAGE_CAPTURE intent, store it in a temporary location and transfer it over network.
Due to its "temporary" characteristic, I was wondering is it more appropriate for me to store the image file in getExternalCacheDir.
However, I have a concern, system might automatic perform "clean up" on cache folder, in the middle of operation.
If such concern is a valid concern, is it more appropriate for me to store the image file in getExternalFilesDir?
Based on the documentation of getExternalCacheDir:
The platform does not always monitor the space available in shared storage, and thus may not automatically delete these files. Apps
should always manage the maximum space used in this location.
Currently the only time files here will be deleted by the platform is when running on Build.VERSION_CODES.JELLY_BEAN_MR1 or later and
Environment.isExternalStorageEmulated(File) returns true.
Given the nature of file as temporary, you should be quite safe with using getExternalCacheDir unless your storage is emulated.
If you wan't to ensure that you need to have these files even on emulated storage then go ahead with getExternalFilesDir
Lets say I have an App that allows me to rate mugs. Therefore, I enter some rating criterias, take a Picture of the mug and then save it to a DataBase, to look at it later.
At the moment, I save the picture on a path obtained by
getExternalFilesDir(Environment.DIRECTORY_PICTURES)
and save the path to my SQLite database to look at it later.
This works fine, however, as I rate a hole bunch of mugs all day and change my phone quiet often, I want to be able to backup my App and its data by common Android backup solutions. This works fine with the SQLite Database that holds the data and is stored in App-Context.
But since the database just holds a path to the taken picture (as returned by getExternalFilesDir), the picture is not backed-up. Where do I have to save the picure, to ensure that any common Android backup software will also grap the pictures?
Is it possible to ensure that the path stored in the database is the same, after I put the backup on a new phone? Since it may be possible that the App is located somewhere else on the new phone, absolute paths are not a good idea here... Is it possible to save the picture relative to the App and just save the relative path?
As suggested by greenapps, a possible solution is to save just the relative path of the image in the database. Instead of using
getExternalFilesDir(Environment.DIRECTORY_PICTURES)
I now use
getFilesDir()
to get the app intern folder and save images there. When I want to load the picture I build the path with the same method to get the app dir and the relative path saved in the database.
I wanted to know the best approach to passing information from an app to another app on the same devices in android.
For example:
I open google apps and I share a document with my App A.
Google App generated an intent and sends a content URI. From my
understanding, the content uri contains information about the file
(filename, file size, mimetype) and the ability to extract the
content which is located in the cache of the google app on the
device.
When App A opens, it reads the content URI. Ideally, it
should be able to extract the information from the content uri and
then render the image. What this means is that App A will display the image shared. In this example, google app shares a docement, and App A wants to open and display the document within it's own app.
The confusing part
From searching the web, it seems that some people actually try to
extract the file path from the content URI. This requires that you
have permission to access another app's cache or storage space
within the device. Let's say this is possible. It also makes some
assumptions that it's possible to extract the file path.
After reading some articles:
https://commonsware.com/blog/2016/03/14/psa-file-scheme-ban-n-developer-preview.html
https://commonsware.com/blog/2014/07/04/uri-not-necessarily-file.html
https://commonsware.com/blog/2016/03/15/how-consume-content-uri.html
it seems that, ideally you should never assume that you can extract the file path and that google has made some updates that makes this not possible.
Work around:
Eventhough i'm not able to extract the file path from the
contentUri, I'm able to read the bytes of what the contentUri is
pointing to. So I could save it to a file that is relevant to the
local cache of App A and pass that path along to get render or pass
the bytes back. This refers to App A displaying the content. That is passing the path or bytes and let's make the assumption that it knows how to display it given that information.
Question:
The work around does not seem ideal because technically you are
save the file again on the device. There are two locations with the
same content ( google app storage and App A's storage). You also
have to manage when to delete the App A's file that you created.
This doesn't really seem ideal and was wondering what the best
approach would be? Or is this the expected flow?
Also I don't know
if it's ideal to pass the bytes back up vs. just a file path.
Update
To be more specific, the app i'm creating is a hybrid where i'm using cordova plugin to interact with a web app. The web app has methods to process or display the shared document based on file path. So ideally I want to keep it consistent with just reading the file path so that the other platforms that the web app supports does not break.
Any advice appreciated,
D
Eventhough i'm not able to extract the file path from the contentUri, I'm able to read the bytes of what the contentUri is pointing to.
Correct. This is not significantly different than how you use an HTTPS URL, where you also do not have direct filesystem access to the content (in that case, resident on a different server).
So I could save it to a file that is relevant to the local cache of App A and pass that path along to get render or pass the bytes back.
Or, just consume the bytes. Again, drawing an analogy to an HTTPS URL, there is no requirement to save those bytes to disk to use them.
The work around does not seem ideal because technically you are save the file again on the device. There are two locations with the same content ( google app storage and App A's storage). You also have to manage when to delete the App A's file that you created.
Then do not save the file again on the device, and simply use the stream of bytes. Again, this is not significantly different than using an HTTPS URL.
This doesn't really seem ideal and was wondering what the best approach would be?
Do not write the bytes to disk. Just use them.
So ideally I want to keep it consistent with just reading the file path so that the other platforms that the web app supports does not break.
Your choices are:
Improve the Web app code, such that a local file path is one possible source of the data, or
Suffer the problems with making copies of that data
After all, bear in mind that the Uri you are given via ACTION_SEND does not have to be a content Uri. It could very easily be an http or https Uri.
I need to store the list of downloaded image in device.I need to know what is the best way for storing images.If i store it in sd card when the user removes the sd card from device.In that situation how to overcome this problem.
If you are bothering about the sdCard removal then only on option is available to save on phone memory that is always available.
Or if you have Internet available what about moving to cloud ???
but if the main concern is security of Images you can go with the answer of user #shree202
For the security purpose you can change the extension
Say From JPG ==>> .db
it is use less for other applications and also user manually can't change the extension
and also for more secure way You can encrypt it by changing it to byte.
If you are going to open the images right from your own application, then, you can remove the extension of the image file and then save. After that, while accessing the image you can get the file list and display it again in your application by appending the file extension.
What i want is that i have made a picture chooser, the image chosen i then want to save in my own object.
Like i have a class called personalFile, this file then includes all details, name, birthdate etc.. I have made it so i can update this personal file and save them to the external storage getExternalFilesDir() using an ObjectOutPutStream.
Now i have taken a picture of the person, and have browsed my way to the picture and gotten the uri path to the picture, now how do I save this file together with the rest of the information in my class?
I have tried looking but havnt found anyone doing this. The reason is also i'd like to be able to send the personal record to another phone using mms, email or alike and be able to open it there with the picture and all.
One way of doing it (albeit not the most efficient) would be to have a byte[] image; member variable in your class and read the content of your file into that byte array. You are quite likely to experience issues though if the image size is large. The other alternative would be to just copy the image file to your external storage and inside your class simply save the file name of the file. Either way, I'm not sure of the merit of saving images as part of your persistent app data (unless the images are really small).