Uri content://media/external/file doesn't exist for some devices - android

I have an issue with some devices. I cannot replicate it on any device but I have quite a lot of crash reports reported by some users.
It is this exception:
java.lang.IllegalArgumentException: Unknown URL content://media/external/file
at android.content.ContentResolver.delete(ContentResolver.java:1024)
I use this:
context.getContentResolver().delete(MediaStore.Files.getContentUri("external"),
MediaStore.Files.FileColumns.DATA + "=?", new String[] { path });
After that I call MediaScannerConnection.scanFile() on file's parent directory, because it is imho most functional way how to notify MediaScanner about deletion of file and how to refresh MTP content. I tried all other ways that I have found here on stackoverflow (e.g.Android How to use MediaScannerConnection scanFile) but nothing is working as well as this.
Btw. I use it only for APIs 11 and newer. External storage is certainly mounted.
I have these questions:
1. Do you know any reason why this exception occurs ? I don't want just to ignore the exception. And I don't want to remove this code when it works quite good for most devices.
2. Do you know some new reliable method how to notify MediaScanner and how to refresh immediately content of MTP when some file is deleted ?

Most probably it has to do with caching on the device. Catching the exception and ignoring is not nice but my problem was fixed and it seems to work.

Related

What is Android 11's equivalent of '/dev/null'

Android 11 introduced multiple changes to file storage and access. Apparently one of them is that one can no longer target output to '/dev/null' (my scenario is actually exactly explained in this old question).
Although the cited question solved the particular issue, one thing remains unanswered: what is Android 11's equivalent to '/dev/null'. That is, if one does not need the output of a particular operation (and in our case it is an operation that creates a biggish file).
Eventually I ended up solving my problem the following way (answer tailored to MediaRecorder problem but can be generalized to other situations too):
fun MediaRecorder.setOutputFile(context: Context) {
val tmpRecordingFolder = File(context.filesDir, "tmp_media")
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
setOutputFile(File(tmpRecordingFolder, "recording.mp3"))
} else {
setOutputFile("/dev/null")
}
}
Basically I am setting the output to be in the internal storage. I hope the file will not get huge and I am deleting the file in as many places in the code as possible. This seems to work on newer devices, currently have not yet ran into storage problems either, but the solution is not rolled out to production yet. Will update my answer if problems are identified.
I had the same issue, you'll have to specify a path since MediaRecorder crashes in Android 11 if you don't provide it, in order to avoid writing a massive file you could try to flush the file by stopping / restarting MediaRecorder, I been dealing with this issue for a few days too.
I replied a more detailed answer here: MediaRecorder Android 11 start failed -1004

Pondering FileUriExposedException in Android 7

I'm an Android developer, and got a Nougat device recently, and noticed that a lot of the apps I've written crash on this device.
The crashes are traceable to FileUriExposedException, and I'm aware of the cause and fixes for this (targetSdkVersion < 24, FileProvider, content URIs, VmPolicy with StrictMode, etc.)
But I'm less clear on the big picture here. In my case, I have about a dozen apps that are interconnected, and they pass file URIs to each other. I can change them to the new standard, but doing so doesn't benefit me, and I also make use of old apps that I have no control over, and that don't know anything about content URIs.
I tried several file managers that I have, and noticed that an old version of ES File Explorer, and a new version of Mixplorer, both use file URIs when invoking apps, whereas Solid Explorer is using content URIs. So the situation appears to be very much up in the air.
I'm familiar with the Linux world, where it's possible to have either tight or loose file permissions. It's clear to me what the tight equivalent is on Nougat, but is there any equivalent of loose permissions? At the moment, my thought is to turn off the exception using the two-line StrictMode scheme, while gradually tweaking my applications in the desired direction, for example by handling both file and content URIs that are passed in.
Does anyone have thoughts on the bigger picture here?

Android getExternalCacheDir() returns null

I am trying to implement the best practices described in Loading Bitmaps effeciently
I've run into trouble because this line:
Utils.getExternalCacheDir(context)
inside of DiskLruCache.java is returning null, which means I get NullPointerException when I try to call .getPath()
Despite the somewhat cryptic NullPointerException that gets thrown the actual issues is that my application did not have WRITE_EXTERNAL permission, so the system was rejecting my attempt to use the ExternalDir for caching. Unfortunately this was happening at a low enough level in the code used in Displaying Bitmaps Effeciently that the Exception does not indicate SecurityException as it normally would if one were trying to write to the SD card without the proper permission.
To fix simply add this:
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
to your manifest.
This can also happen if you're running on a device or emulator without any external storage.

MediaMetadataRetriever mostly stopped working since update to Ice Cream Sandwich

Since I upgraded my Galaxy S2 to Android 4 I am having some weird problem with my audio player application.
Since the upgrade MediaMetadataRetriever doesn't output much info other than the track number and the embedded picture. No title, no artist, pretty much nothing.
I am currently at a loss, as the problem is just made worse that the Android 4.0.3 emulator doesn't have the same problem.
Googling for this didn't help much, although I find it hard to imagine that I would be the only one with this kind of problem. My wife's SGS2 shows the same problem, so I don't expect it to be some strange problem limited to my phone.
Does anybody know if that might be a problem limited to ICS for the SGS2?
Did anybody else experience problems with MediaMetadataRetriever on ICS?
And, I guess most importantly, does anybody have a solution for this?
In case you want to check if my application has that problem on your phone you can get either code or APKs at http://www.sourceforge.net/projects/andrstoryteller
Any general advice on how I might be able to track down the problem would help as well.
I will test your sample application when I have a moment but in the meantime you may also want to think about another solution besides MediaMetadataRetriever since it limits your API compatibility and (apparently) doesn't always work. My project, ServeStream, uses a stripped down version of Apache Tika to retrieve the metadata. You may want to consider this approach in your own project. Here is a URL to the Tika jar and the class to do the parsing:
http://servestream.svn.sourceforge.net/viewvc/servestream/trunk/lib/tika-app-1.0.jar?view=log
http://servestream.svn.sourceforge.net/viewvc/servestream/trunk/src/net/sourceforge/servestream/utils/MetadataRetriever.java?revision=1033&view=markup
I noticed the same issue on ICS (On Galaxy SII and Galaxy Tab II both running ICS 4.0.3).
This seems to impact only mp3.
I guess one of the solutions as William suggested would be to use an external library but I also prefer to use what android offers rather then external libraries.
What bothers me is that I cannot find other posts reporting the same issue apart from this one. Though, I don't think I am doing it wrong:
I have tried two solutions:
MediaMetadataRetriever mmdr = new MediaMetadataRetriever();
mmdr.setDataSource(path);
String title = mmdr.extractMetadata(MediaMetadataRetriever.METADATA_KEY_TITLE);
and
File file = new File(path);
FileInputStream inputStream;
inputStream = new FileInputStream(file);
mmdr = new MediaMetadataRetriever();
mmdr.setDataSource(inputStream.getFD());
inputStream.close();
String title = mmdr.extractMetadata(MediaMetadataRetriever.METADATA_KEY_TITLE);
MediaMetadataRetriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_TITLE) always retuns null.
The path is correct and the mp3 file does have the ID3 tag with the title and everything.
A solution that I thought of apart from using an external library would be to query the MediaStore on the file's path:
Cursor c = mContext.getContentResolver().query(MediaStore.Audio.Media.EXTERNAL_CONTENT_URI, new String[] {MediaStore.MediaColumns.TITLE},
MediaStore.MediaColumns.DATA + "=?",
new String[] { path }, null);
String title;
if(c!=null && c.moveToFirst())
title = c.getString(c.getColumnIndex(MediaStore.MediaColumns.TITLE))
}
If the MediaScanner scanned it (it should have), the info should be there. This should also work for API levels before 10.
Basically, what I do in my project is the following: If SDK version is < 10 or the file's extension is mp3 and SDK version is 15, I query the MediaStore, otherwise I use MediaMetaDataRetriever.
A little update on the situation.
I have just put a couple of Ogg/Vorbis files onto my phone and there it can read the tags properly.
Will have to test with some more files, but maybe this has only stopped working for MP3 files.
Would be cool if I could get a couple of more people with ICS phones to test this.
Anyway, I'm currently looking into an alternative way to get this information, so I probably won't be using MediaMetadataRetriever for much longer.

listening for file changes in android file-system without file observer

I am still new to android programming, (wrote one small app so far) and I am also new to stack overflow. I am looking to write something that will listed for changes in a file, exactly like how file observer works. but the issue is the file im looking at receives changes from the kernel, and i realized that file observer does seem to pick up on changes unless it is done by the user. thanks.
I know this is old, but I figure I should Post the answer I found.
The solution is UEventObserver
doc: (http://www.androidjavadoc.com/1.1_r1_src/android/os/UEventObserver.html)
I found my answer in the "frameworks / base / services / java / com / android / server /" area of the android source code where they listen to changes reported form the kernel.
my implementation of the solution is here: https://github.com/gh123man/ICS_tablet_HW_rotationlock/blob/master/frameworks/base/services/java/com/android/server/RotationSwitchObserver.java
I believe there is no good solution. FileObserver will only report events that originate in user space - kernel originated events (i.e. to procfs file) are not reported. Further, the File operations won't work either, so you can can't check the hash, length, modified date, etc. of these files.
My observations are based on 2.3.6.
"the file im looking at receives changes from the kernel"
If you are referring to file from the procfs, or some other virtual-file, I fear inotify won't help you a lot...
search for "Q: Are there any limitations for use of inotify?"
Q: Are there any limitations for use of inotify?
Yes. Some filesystems (e.g. procfs or some network filesystems) don't emit
events in some cases.

Categories

Resources