Search code examples
androidandroid-intentmime-typesintentfilter

Open my application for a particular file and URL extension - intent-filter isn't working as intended


Question:

How can I get my application to open a file and url extension, unconditionally?

I am at my wit's end with setting up my intent-filter as none of it is really making any sense. My end goal is to open up anything that has a path ending in a certain extension. For the sake of an example, let's choose ".riley" as my goal extension.

My Base `intent-filter`

<intent-filter>
    <action android:name="android.intent.action.VIEW" />

    <category android:name="android.intent.category.DEFAULT" />
    <category android:name="android.intent.category.BROWSABLE" />

    <data
        android:host="*"
        android:mimeType="*/*"
        android:pathPattern=".*\\.riley" />
</intent-filter>

This currently works to open from file and content.

Issue #1: pathPattern

For starters, it doesn't seem as though the data parameter pathPattern does anything, as I have set:

<data
    android:host="*"
    android:mimeType="*/*"
    android:pathPattern=".*\\.riley" />

.. but I can still open Intents with Uri paths that do not end in ".riley" under the file and content scheme.

A couple example paths that my application opened using this intent-filter are:

Path: /storage/sdcard0/Download/MyApp.apk Path: /messagesByAccount/1

The "Path: " was just my own addition in the log for clarity. The first is from gmail under the file scheme and the second is from gtalk under the content scheme. Given that, I am already confused about how intent-filters work.

The pathPattern is being ignored on file and content schemes.

Issue #2: Opening in a browser

I've tried to get my application to open ".riley" extensions from browsers, however redirecting links don't have a MIME-type, so I removed the mimeType value from the data pattern (I had android:mimeType="*/*" earlier, as the MIME-type isn't consistent) and that allowed me to open from redirecting URLs just fine.

The problem came when I tried to open a direct ".riley" URL from the browser (eg: http://thisisnotarealdomainname.com/myfile.riley) and the option to open from my application was gone. Adding the mimeType value back to my data pattern allowed me to open from a direct URL.

The intent-filter won't let me open both direct and indirect URLs.

Issue #3: scheme

I would like to be able to open from a number of different scheme types (eg: http,file,content), but as soon as I removeschemealtogether, it disqualifies my application from opening thehttpscheme and when I specifyscheme="*", it disqualifies my application from opening ANY scheme. I've also tried adding moredata` patterns, but I get the feeling as though only one is taken into effect, as that doesn't help me at all.

So, specifying http will allow for http, but obviously hasn't allowed either file or content and not specifying the scheme disables http.

I cannot open from all different schemes.

To reiterate, how can I get my application to open a file and url extension, unconditionally, given these complications?


Solution

  • Issue #1: <data android:pathPattern=".*\\.riley" /> is simply invalid. Quoting the documentation:

    [pathPattern is] meaningful only if the scheme and host attributes are also specified for the filter.

    Issue #2: "however redirecting links don't have a MIME-type" should be incorrect, unless the Web server is seriously broken. An HTTP redirect itself does not have a MIME type, but that should be handled by the browser itself, as until the browser handles the redirection, it has no idea whether the URL points to something that it should handle (e.g., a Web page) or something that should be downloaded. The result of the redirect -- the HTTP 200 OK response -- should have a MIME type. If you are convinced that redirected URLs to downloads do not work, create a sample project demonstrating the error and post it somewhere for review.

    Issue #3: "I cannot open from all different schemes." -- use multiple <data> elements with multiple android:scheme attributes, in separate <intent-filter> elements.

    For example, the AOSP Music app has:

        <activity android:name="AudioPreview" android:theme="@android:style/Theme.Dialog"
                android:taskAffinity=""
                android:excludeFromRecents="true" android:exported="true" >
            <intent-filter>
                <action android:name="android.intent.action.VIEW" />
                <category android:name="android.intent.category.DEFAULT" />
                <data android:scheme="file"/>
                <data android:mimeType="audio/*"/>
                <data android:mimeType="application/ogg"/>
                <data android:mimeType="application/x-ogg"/>
                <data android:mimeType="application/itunes"/>
            </intent-filter>
            <intent-filter>
                <action android:name="android.intent.action.VIEW" />
                <category android:name="android.intent.category.DEFAULT" />
                <category android:name="android.intent.category.BROWSABLE" />
                <data android:scheme="http" />
                <data android:mimeType="audio/*"/>
                <data android:mimeType="application/ogg"/>
                <data android:mimeType="application/x-ogg"/>
                <data android:mimeType="application/itunes"/>
            </intent-filter>
            <intent-filter
                android:priority="-1">
                <action android:name="android.intent.action.VIEW" />
                <category android:name="android.intent.category.DEFAULT" />
                <category android:name="android.intent.category.BROWSABLE" />
                <data android:scheme="content" />
                <data android:mimeType="audio/*"/>
                <data android:mimeType="application/ogg"/>
                <data android:mimeType="application/x-ogg"/>
                <data android:mimeType="application/itunes"/>
            </intent-filter>
        </activity>
    

    You will notice that the action, category, and MIME type are the same in all three <intent-filter> stanzas; only the android:scheme attribute varies.

    Now, the file scheme for this Music app example will only work if some local file manager attaches the appropriate MIME type to the Intent; Music does not attempt to use android:pathPattern to match file extensions. In fact, Google rarely uses android:pathPattern. There is one occurrence in the AOSP Calendar app:

            <intent-filter
               android:priority="50">
               <action android:name="android.intent.action.VIEW" />
               <category android:name="android.intent.category.DEFAULT" />
               <category android:name="android.intent.category.BROWSABLE" />
               <data android:scheme="http" android:host="www.google.com" android:pathPrefix="/calendar/event" />
               <data android:scheme="https" android:host="www.google.com" android:pathPrefix="/calendar/event" />
               <data android:scheme="http" android:host="www.google.com" android:pathPattern="/calendar/hosted/.*/event" />
               <data android:scheme="https" android:host="www.google.com" android:pathPattern="/calendar/hosted/.*/event" />
            </intent-filter>
    

    But that's pretty much it. Certainly others have tried it -- there are a bunch of questions here on StackOveflow covering its use.