While trying to get a picture using a Camera intent as describe in the documentation.
I've added the required MediaStore.EXTRA_OUTPUT extra but the problem was that it didn't save the file where I wanted. So I read the documentation more carefully, and compared it with what I was doing (since I didn't blindly copy/pasted the provided sample code), and found that I was using
intent.putExtra(MediaStore.EXTRA_OUTPUT, myFile.toURI());
Instead of
intent.putExtra(MediaStore.EXTRA_OUTPUT, Uri.fromFile(myFile));
The second version worked perfectly, but I can't figure out why. The documentation for both methods don't state anything related to incompatibility between the two.
Shouldn't the two give the same result, or am I missing a subtle difference?
Just from a quick test here:
Uri.fromFile() returns a Uri (android.net.Uri)
file.toURI() returns a URI (java.net.URI)
I expect this is causing the problem.
The content produced by Uri.fromFile() and file.toURI() is not the same...
for the same file "f" located on the sdcard.
"f.toURI()" will add this into your Bundle {output=file:/mnt/sdcard/Gp/Gp.db}
and "Uri.fromFile(f)" will add {output=file:///mnt/sdcard/Gp/Gp.db}
Related
My requirement is to take the picture from the camera in Android, and not to save the picture in a file but rather save it in the memory, so the file is not left behind.
I know one option is to delete the file afterwards, but this is not good enough, I need another level of security so there is no trace left at all. The code below is from "Taking Photos Simply", I have shortened the code for brevity.
Intent takePictureIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
if (takePictureIntent.resolveActivity(getPackageManager()) != null) {
// **Create the File** where the photo should go
File photoFile = createImageFile();
if (photoFile != null) {
Uri photoURI = FileProvider.getUriForFile(...,...,photoFile);
takePictureIntent.putExtra(..., photoURI);
startActivityForResult(takePictureIntent, REQUEST_TAKE_PHOTO);
}
}
String mCurrentPhotoPath;
private File createImageFile() throws IOException {
// Create an **image file** name
return image;
}
The point here is that a "File" is required, which I need to do away with. My research so far has led me to create my own ContentProvider like this https://gist.github.com/m039/6550133 "Custom ContentProvider", based on memory array (android). I was hoping for a simpler solution than this. Any other ideas would be greatly appreciated, thank you.
My research so far has led me to create my own ContentProvider like this https://gist.github.com/m039/6550133 "Custom ContentProvider", based on memory array (android).
That particular ContentProvider example will be of limited use, as virtually nothing in it is relevant for this use case. That being said, having a ContentProvider where you stream the results into memory, rather than disk, is your only somewhat-viable solution for ACTION_IMAGE_CAPTURE. Bear in mind that this approach will not work much of the time, because:
You may not be able to allocate the memory buffer that you need, particularly since, strictly speaking, you do not know how big it needs to be ahead of time. You could use the camera APIs, find the highest resolution, then use that to size your memory buffer ahead of time, but even then you will run into challenges due to heap fragmentation.
Not that many camera apps support content as a Uri scheme at the moment. For example, Google's did not support it until the summer of 2016. By 2018 or so, most camera apps should support content (I hope), but even then it will not be 100%.
I was hoping for a simpler solution than this.
You can work with the camera APIs directly, but that will be more complicated.
I am looking to add something to help with this in my CWAC-Cam2 library, though I have not implemented yet as of late 2016.
You could see if there are other camera libraries that support giving you the results in memory.
And that's about it.
I have a video that I save to .../Movies/MyApp/abcde.mp4. So I know where it is. When I load it through my app using an implicit intent to ACTION_GET_CONTENT, the path is returned as content:/media/external/video/media/82 when I do
data.getData().toString()
The problem with that path is that it works when I try to access it with MediaRecorder as
mVideoView.setVideoURI(Uri.parse(mVideoStringPath))
However if I try to convert it to a path in another thread (for a job queue), the file is not found
new File(mVideoStringPath)
when I use the technique (copy and paste) described at How to get file path in onActivityResult in Android 4.4, still get the error
java.lang.RuntimeException: Invalid image file
Also per my logging, the new technique shows the path to the video as
video path: /storage/emulated/0/Movies/MyApp/abc de.mp4
notice the space in abc de.mp4. that indeed is the name of the file. And the phone's camera app has no trouble playing
However if I try to convert it to a path in another thread (for a job queue), the file is not found
That is because it is not a path to a file. It is a Uri, which is an opaque handle to some data.
How to get actual path to video from onActivityResult
You don't. You use the Uri. There is no requirement that the Uri point to a file. There is no requirement that the Uri, if it happens to represent a file, represent one that you have direct filesystem access to.
you need to escape the space the the file path in order to construct a File object from it.
filepath.replace(" ", "\\ ");
I am trying to read an image in my C++ code
LOGD("Loading image '%s' ...\n", (*inFile).c_str());;
Mat img = imread(*inFile, CV_LOAD_IMAGE_GRAYSCALE);
CV_Assert(img.data != 0);
and get the following output:
09-25 17:08:24.798: D/IRISREC(12120): Loading image '/data/data/com.example.irisrec/files/input/osoba1.jpg' ...
09-25 17:08:24.798: E/cv::error()(12120): OpenCV Error: Assertion failed (img.data != 0) in int wahet_main(int, char**), file jni/wahet.cpp, line 4208
The file exists. But strange is, that if I try to preview the image using Root File Browser it is just black. I copied the files there manually.
EDIT:
The code works fine under Windows with .png and .jpg format. I am just trying to port an existing C++ project for Iris Recognition to Android.
imread() determines the type of file based on its content not by the file extension. If the header of the file is corrupted, it makes sense that the method fails.
Here are a few things you could try:
Copy those images back to the computer and see if they can be opened by other apps. There's a chance that they are corrupted in the device;
Make sure there is a file at that location and that your user has permission to read it;
Test with types of images (jpg, png, tiff, bmp, ...);
For testing purposes it's always better to be more direct. Get rid of inFile:
Example:
Mat img = imread("/data/data/com.example.irisrec/files/input/osoba1.jpg", CV_LOAD_IMAGE_GRAYSCALE);
if (!img.data) {
// Print error message and quit
}
When debugging, first try to get more data on the problem.
It's an unfortunate design that imread() doesn't provide any error info. The docs just say that it'll fail "because of missing file, improper permissions, unsupported or invalid format".
Use the debugger to step into the code if you can. Can you tell where it fails?
Search for known problems, stackoverflow.com/search?q=imread, e.g. imread not working in OpenCV.
Then generate as many hypotheses as you can. For each one, think of a way to test it. E.g.
The image file is malformed (as #karlphillip offered). -- See if other software can open the file.
The image file is not a supported format. -- Verify the file format on your desktop. Test that desktop OpenCV can read it. Check the docs to verify the image formats that AndroidCV can read.
The image file is not at the expected path. -- Write code to test if there's a file at that path, and verify its length.
The image file does not have read permission. -- Write code to open the file for reading.
A problem with the imread() arguments. -- Try defaulting the second argument.
I was able to solve this issue only by copying the image files in code.I stored them in my asset folder first and copied them to internal storage following this example.
If someone can explain this to me please do this.
It could be a permission issue.You would have to request the permission from Java code in your Activity class like this in Android 6.0 or above. Also make sure that in your AndroidManifest.xml, you have the the following line :
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
In your activity file add this:
if (PermissionUtils.requestPermission(
this,
HOME_SCREEN_ACTIVITY,
Manifest.permission.READ_EXTERNAL_STORAGE)) {
Mat image = Imgcodecs.imread(filePath,Imgcodecs.IMREAD_COLOR);
}
I struggled a long time to find this and I was getting Mat object null for all the time before.
I'm facing with the following problem:
I created application where user can keep his own private files and I need to pass these files to default viewers (PDFViewer for example).
The problem is that files are private and PDFViewer has no access to my files. I solved this issue using approach that is used in email clients - I created content provider where I return ParcelFileDescriptor.
Now it works great, but I faced with new problem - documentation says I need to use Intent.FLAG_GRANT_READ_URI_PERMISSION flag when I pass URI to PDFViewer, but in my case it works well even without this flag and even with "android:grantUriPermissions="false""
Looks like now my files become not private because of content provider.
How to make it honor Intent.FLAG_GRANT_READ_URI_PERMISSION flag?
Found the problem - I forgot to add "android:readPermission" flag to my provider
Something weird is happening in my application im not sure if it is worth uploading all the code...
Intent pictureIntent = new Intent(android.provider.MediaStore.ACTION_IMAGE_CAPTURE);
pictureIntent.putExtra( MediaStore.EXTRA_OUTPUT, imageUriToSaveCameraImageTo );
startActivityForResult(Intent.createChooser(pictureIntent, strAvatarPrompt), TAKE_AVATAR_CAMERA_REQUEST);
I use this code to take an photo. The photo gets saved in the DCIM folder and also into imageUriSaveCameraImageto which points to sdcard/folder...The image is given the name image1.jpg..once run it works.
Then i delete the files from DCIM and sdcard/folder and run the application again and take a different photo...for some reason the old photo appears in the folder...it must be caching or storing a copy of it else where...does anyone know where and how i can delete it?thanks
Android indeed caches thumbnails of all the photos in another location.
See here:
http://www.droidforums.net/forum/droid-general-discussions/30998-thumbnail-cache-can-cleared.html
I can't give you an exact answer, but my feeling is that the MediaStore is a ContentProvider, so you may be able to call ContentResolver.delete(URI).