I want to be able to download a file with a particular extension from the 'net, and have it passed to my application to deal with it, but I haven't been able to figure out the intent filter. The filetype is not included in the mimetypes, and I tried using
<data android:path="*.ext" />
but I couldn't get that to work.
On Android 4 the rules became more strict then they used to be. Use:
If you want the files to be opened directly from Gmail, dropbox or any of the buildin android file tools, then use the following code (delete 'android:host="*"' that made the file unreachable for gmail) :
The data filter must be written in one statement as per Android version 4.x
Here is how I defined my activity in my AndroidManifest.xml to get this to work.
The
scheme
offile
indicates that this should happen when a local file is opened (rather than protocol like HTTP).mimeType
can be set to\*/\*
to match any mime type.pathPattern
is where you specify what extension you want to match (in this example.kdb
). The.*
at the beginning matches any squence of characters. These strings require double escaping, so\\\\.
matches a literal period. Then, you end with your file extension. One caveat with pathPattern is that.*
is not a greedy match like you would expect if this was a regular expression. This pattern will fail to match paths that contain a.
before the.kdb
. For a more detailed discussion of this issue and a workaround see hereFinally, according to the Android documentation, both
host
andscheme
attributes are required for thepathPattern
attribute to work, so just set that to the wildcard to match anything.Now, if you select a
.kdb
file in an app like Linda File Manager, my app shows up as an option. I should note that this alone does not allow you to download this filetype in a browser, since this only registers with the file scheme. Having an app like Linda File Manager on your phone resisters itself generically allowing you to download any file type.There's a lot of misinformation on this topic, not least from Google's own documentation. The best, and given the strange logic, possibly the only real documentation is the source code.
The intent filter implementation has logic that almost defies description. The parser code is the other relevant piece of the puzzle.
The following filters get pretty close to sensible behaviour. The path patterns do apply, for "file" scheme intents.
The global mime type pattern match will match all types so long as the file extension matches. This isn't perfect, but is the only way to match the behaviour of file managers like ES File Explorer, and it is limited to intents where the URI/file extension matches.
I haven't included other schemes like "http" here, but they will probably work fine on all these filters.
The odd scheme out is "content", for which the extension is not available to the filter. But so long as the provider states your MIME type (E.g. Gmail will pass on the MIME type for the attachment unimpeded), the filter will match.
Gotchas to be aware of:
With all this in mind, here's an example with comments:
Brian's answer is very close, but here's a clean and error-free way to have your app invoked when trying to open a file with your own custom extension (no need for scheme or host):
I've been struggling with this quite a bit for a custom file extension, myself. After a lot of searching, I found this web page where the poster discovered that Android's patternMatcher class (which is used for the pathPattern matching in Intent-Filters) has unexpected behavior when your path contains the first character of your match pattern elsewhere in the path (like if you're trying to match "*.xyz", the patternMatcher class stops if there's an "x" earlier in your path). Here's what he found for a workaround, and worked for me, although it is a bit of a hack: