Android intent filter not working
Asked Answered
F

1

5

My app can open the following file formats:

  • kml (application/vnd.google-earth.kml+xml)
  • kmz (application/vnd.google-earth.kmz)
  • gpx (application/gpx+xml)

I'm trying to set up properly my intent filters so that my app is proposed when trying to open one of these file types, through the following schemes:

  • http
  • https
  • file
  • content

I would expect the following filter to catch all cases (except files with dots in the name, but that's another problem):

<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="file" />
    <data android:scheme="http" />
    <data android:scheme="https" />
    <data android:scheme="content" />

    <data android:pathPattern=".*\\.kml" />
    <data android:pathPattern=".*\\.kmz" />
    <data android:pathPattern=".*\\.gpx" />

    <data android:mimeType="application/vnd.google-earth.kml+xml" />
    <data android:mimeType="application/vnd.google-earth.kmz" />
    <data android:mimeType="application/gpx+xml" />

</intent-filter>

But if the file explorer does not set properly the GPX content type, GPX files are not recognized (even though they are properly named, with ".gpx" extension).

Does someone know what's the problem?

Fabri answered 2/9, 2016 at 21:1 Comment(4)
I would set this up as two filters. One is file and the extensions. The other is the other schemes and the MIME types. As it stands, for example, if the content has the right MIME type, but the path does not have one of those extensions (as it rarely will for content), your filter will not match. In general, file extensions are the least reliable approach on Android.Radiotherapy
Thanks! I nearly there, I have something that seems to handle all cases. Why would you restrict the scheme on the 2 filters? Why not one filter for extensions and one for mime types, both for all schemes?Fabri
Well, for http and https, the MIME type would be more reliable IMHO. For content, frequently there is no file extension. I tend to take the approach of using a smaller scope that is less likely to give me erroneous results. But, if you want to apply all four schemes in both filters, that probably works.Radiotherapy
OK thanks! I'll do what I said though, I prefer to have the app not being able open a provided file than the app not proposing to open a file that it can handle.Fabri
F
11

So here is what I ended up with:

<!--Mime type set -->
<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="file" />
    <data android:scheme="http" />
    <data android:scheme="https" />
    <data android:scheme="content" />

    <!-- Valid mime types -->
    <data android:mimeType="application/vnd.google-earth.kml+xml" />
    <data android:mimeType="application/vnd.google-earth.kmz" />
    <data android:mimeType="application/gpx+xml" />

    <!-- Invalid mime types used by some bad software -->
    <data android:mimeType="application/kml" />
    <data android:mimeType="application/kmz" />
    <data android:mimeType="application/gpx" />

    <data android:mimeType="application/kml+xml" />
    <data android:mimeType="application/kmz+xml" />

    <data android:mimeType="application/vnd.google-earth.kml" />
    <data android:mimeType="application/vnd.google-earth.gpx" />
    <data android:mimeType="application/vnd.google-earth.kmz+xml" />
    <data android:mimeType="application/vnd.google-earth.gpx+xml" />

    <data android:mimeType="text/kml" />
    <data android:mimeType="text/kmz" />
    <data android:mimeType="text/gpx" />

    <data android:mimeType="text/kml+xml" />
    <data android:mimeType="text/kmz+xml" />
    <data android:mimeType="text/gpx+xml" />

    <data android:mimeType="text/xml+kml" />
    <data android:mimeType="text/xml+kmz" />
    <data android:mimeType="text/xml+gpx" />

</intent-filter>

<!-- Mime type not set but valid extensions -->
<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="file" />
    <data android:scheme="http" />
    <data android:scheme="https" />
    <data android:scheme="content" />

    <data android:host="*" />

    <data android:pathPattern="/.*..*..*..*..*\\.gpx" />
    <data android:pathPattern="/.*..*..*..*..*\\.kml" />
    <data android:pathPattern="/.*..*..*..*..*\\.kmz" />
    <data android:pathPattern="/.*..*..*..*\\.gpx" />
    <data android:pathPattern="/.*..*..*..*\\.kml" />
    <data android:pathPattern="/.*..*..*..*\\.kmz" />
    <data android:pathPattern="/.*..*..*\\.gpx" />
    <data android:pathPattern="/.*..*..*\\.kml" />
    <data android:pathPattern="/.*..*..*\\.kmz" />
    <data android:pathPattern="/.*..*\\.gpx" />
    <data android:pathPattern="/.*..*\\.kml" />
    <data android:pathPattern="/.*..*\\.kmz" />
    <data android:pathPattern="/.*\\.gpx" />
    <data android:pathPattern="/.*\\.kml" />
    <data android:pathPattern="/.*\\.kmz" />

</intent-filter>

<!-- Invalid mime type but valid extensions -->
<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="file" />
    <data android:scheme="http" />
    <data android:scheme="https" />
    <data android:scheme="content" />

    <data android:host="*" />
    <data android:mimeType="*/*" />

    <data android:pathPattern="/.*..*..*..*..*\\.gpx" />
    <data android:pathPattern="/.*..*..*..*..*\\.kml" />
    <data android:pathPattern="/.*..*..*..*..*\\.kmz" />
    <data android:pathPattern="/.*..*..*..*\\.gpx" />
    <data android:pathPattern="/.*..*..*..*\\.kml" />
    <data android:pathPattern="/.*..*..*..*\\.kmz" />
    <data android:pathPattern="/.*..*..*\\.gpx" />
    <data android:pathPattern="/.*..*..*\\.kml" />
    <data android:pathPattern="/.*..*..*\\.kmz" />
    <data android:pathPattern="/.*..*\\.gpx" />
    <data android:pathPattern="/.*..*\\.kml" />
    <data android:pathPattern="/.*..*\\.kmz" />
    <data android:pathPattern="/.*\\.gpx" />
    <data android:pathPattern="/.*\\.kml" />
    <data android:pathPattern="/.*\\.kmz" />

</intent-filter>

Seems to be working on all the file manager I tested (FX, ES, Astro, File Commander).

(For those wondering about the weird path patterns see pathPattern to match file extension does not work if a period exists elsewhere in the file name?)

Fabri answered 4/9, 2016 at 11:51 Comment(2)
IIRC yes it does!Fabri
This was the only intent-filter example I could find on the web that worked for me. Thanks!Unrounded

© 2022 - 2024 — McMap. All rights reserved.