Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Android: Associate app with custom file type

I've got a file type, the extension is '.rfts' (really it's just storing a JSON string that represents user configurations for an audio amplifier). I'd like to be able to open this file when it's an attachment from an e-mail (Gmail for example) so I can import user settings from another tablet.

Here's what my manifest looks like (note that I didn't include the other activities in this, but there's 4 others that don't have intent filters).

<application
    android:allowBackup="true"
    android:icon="@mipmap/ic_launcher"
    android:label="@string/app_name"
    android:supportsRtl="true"
    android:theme="@style/RFtheme" >
    <activity
        android:name=".activity.MainActivity"
        android:screenOrientation="landscape"
        android:windowSoftInputMode="adjustPan" >
        <intent-filter>
            <action android:name="android.intent.action.MAIN" />

            <category android:name="android.intent.category.LAUNCHER" />
        </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"/>
            <category android:name="android.intent.category.OPENABLE"/>
            <data android:scheme="file"/>
            <data android:mimeType="*/*"/>

            <data android:pathPattern="\\.rfts$"/>
            <data android:host="*"/>
        </intent-filter>
    </activity>

    <provider
        android:name=".model.FileProvider"
        android:authorities="com.rockfordcorp.app3sixty.provider"
        android:enabled="true"
        android:exported="true" >
    </provider>
</application>

I've been trying several other suggested fixes from other questions, but they were for things like opening a pdf from a browser.

When I try to open a .rfts attachment in Gmail, it tells me "You don't have an app that can open this file (.rfts). Try searching google play for one that can"

I'm at a loss as to what I need to be doing here. I don't have any idea what mime Gmail would be using to open a .rfts, nor what scheme it would be using. I've tried a few different combinations but nothings really worked. I just haven't put in the magic combination of category, mimetype, pattern and scheme that Android is looking for to associate this file to my app.

EDIT some success, but not quite there yet.

The questions suggested as fixes are off the mark, and the reason is because the scheme required is actually 'content', not 'file'

The intent filter that works is

<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" android:mimeType="*/*" android:pathPattern=".*\\.rfts"/>
            <data android:scheme="content" android:pathPattern=".*\\.rfts" android:mimeType="application/octet-stream" />
            <!-- <data android:host="*"/> -->
        </intent-filter>

Without the android:sceheme="content" it does not work.

However, a new problem arises. Gmail now opens all file types that are not previously associated with another app. For example, if I were to try to open a .rfff file, it uses my app. If you try to open a .txt it opens a chooser for Chrome or HTML viewer.

This is close, but it opening other file types is problematic. Android:pathPattern evidently has no effect on what filetype my app is associated with.

As this question was marked as a possible duplicate I want to point out the solution suggested is not working for opening a file from g-mail not web, nor does it cover opening a custom filetype. Using that 'solution' with the file type swapped out causes g-mail to continue to insist there is no app on the device capable of opening the file type.

A different solution likely needs to be provided to associate opening this custom filetype via the intent from Gmail.

like image 513
Magic Marbles Avatar asked Dec 15 '15 22:12

Magic Marbles


1 Answers

Update 2020

Android has moved towards content URIs and MIME-Types for intent filters.

The Problem

A content URI does not necessarily have to contain the file's extension or name and it will be different between different applications that are providing the content/file.

Here are some example content URIs from different email applications for the same email attachment:

Gmail -> content://com.google.android.gm.sapi/[email protected]/message_attachment_external/%23thread-a%3Ar332738858767305663/%23msg-a%3Ar-5439466788231005876/0.1?account_type=com.google&mimeType=application%2Foctet-stream&rendition=1

Outlook -> content://com.microsoft.office.outlook.fileprovider/outlookfile/data/data/com.microsoft.office.outlook/cache/file-download/file--2146063402/filename.customextention

Samsung Email App -> content://com.samsung.android.email.attachmentprovider/1/1/RAW

As can see they are all different and are not guaranteed to contain anything related to your actual file. Thus, you cannot use the android:pathPattern like most have suggested.

A work around solution for email attachments

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

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

    <data android:scheme="content"/>
    <data android:host="*"/>

    <!--  Required for Gmail and Samsung Email App  -->
    <data android:mimeType="application/octet-stream"/>

    <!--  Required for Outlook  -->
    <data android:mimeType="application/my-custom-extension"/>
</intent-filter>

Through testing I found the MIME-Types that Gmail, Outlook, and Samsung Email used and added those to my intent-filter.

Caveats/Gotchas

  • I found that with my above solution, if I opened any file that was a binary type, it would automatically launch my app. I handled this in my activity by displaying a failed state if we could not parse the file. I figured this was a pretty rare event so it would acceptable.

  • I could not find any way to launch my app via the file browser without adding <data android:mimeType="*/*"/> to my intent-filter. I couldn't use this because it would then launch my app whenever the user clicked any file on their phone (not just the custom-file-extension ones). I would not recommend adding this to your intent-filter.

  • I had no luck using android:scheme="file" at all.

  • I tested this on a Samsung Galaxy S10 on Android 10

Final Thoughts

  • There is currently no elegant solution for associating your app with a specific extension type in Android. This was the best that I could do in my situation.
like image 154
alexander antaya Avatar answered Sep 30 '22 06:09

alexander antaya