web-dev-qa-db-ja.com

Android特定のファイル拡張子の意図フィルター?

特定の拡張子を持つファイルを「ネット」からダウンロードできるようにしたいので、それを処理するためにアプリケーションに渡しますが、インテントフィルターを把握できませんでした。ファイルタイプはMIMEタイプに含まれていないため、使用してみました

<data Android:path="*.ext" />

しかし、私はそれを機能させることができませんでした。

88
Curyous

AndroidManifest.xmlでアクティビティを定義して、これを機能させる方法を次に示します。

<activity Android:name="com.keepassdroid.PasswordActivity">
    <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:mimeType="*/*" />
        <data Android:pathPattern=".*\\.kdb" />
        <data Android:Host="*" />
    </intent-filter>
</activity>

schemefileは、(HTTPなどのプロトコルではなく)ローカルファイルが開かれたときに発生することを示します。

mimeType\*/\*に設定して、任意のMIMEタイプに一致させることができます。

pathPatternは、一致させる拡張子を指定する場所です(この例では.kdb)。先頭の.*は、文字のシーケンスに一致します。これらの文字列には二重エスケープが必要なので、\\\\.はリテラルピリオドと一致します。次に、ファイル拡張子で終わります。 pathPatternの注意点の1つは、.*は、これが正規表現である場合に予想される貪欲な一致ではないことです。このパターンは、.の前に.kdbを含むパスの照合に失敗します。この問題の詳細と回避策については、 here を参照してください。

最後に、Androidのドキュメントによれば、Host属性とscheme属性の両方がpathPattern属性が機能するために必要であるため、それを設定するだけです。ワイルドカードを使用して、すべてに一致させます。

これで、Linda File Managerなどのアプリで.kdbファイルを選択すると、私のアプリがオプションとして表示されます。これだけでは、ファイルスキームに登録するだけなので、ブラウザでこのファイルタイプをダウンロードすることはできません。携帯電話にLinda File Managerのようなアプリを登録すると、一般的にあらゆる種類のファイルをダウンロードできます。

116
Brian Pellin

このトピックには、特にGoogle自身のドキュメントから多くの誤った情報があります。最良の、そして奇妙なロジックを考えると、おそらく唯一の実際のドキュメントはソースコードです。

インテントフィルターの実装 には、ほとんど説明に反するロジックがあります。 パーサーコード は、パズルの他の関連部分です。

以下のフィルターは、理にかなった動作にかなり近づきます。 「ファイル」スキームのインテントには、パスパターンが適用されます。

グローバルMIMEタイプパターンの一致は、ファイル拡張子が一致する限り、すべてのタイプに一致します。これは完全ではありませんが、ES File Explorerのようなファイルマネージャーの動作を一致させる唯一の方法であり、URI /ファイル拡張子が一致するインテントに限定されます。

ここには「http」のような他のスキームは含めていませんが、おそらくこれらすべてのフィルターでうまく機能するでしょう。

奇妙なスキームは「コンテンツ」であり、その拡張子はフィルタで利用できません。ただし、プロバイダーがMIMEタイプを指定している限り(たとえば、Gmailは添付ファイルのMIMEタイプをそのまま渡します)、フィルターは一致します。

知っておくべきこと:

  1. フィルター内で一貫して動作するものはないことに注意してください。これは特殊なケースの迷路であり、最小の驚きの原則の違反を設計目標として扱います。どのパターンマッチングアルゴリズムも同じ構文または動作に従いません。フィールドがない場合はワイルドカードである場合もあればそうでない場合もあります。データ要素内の属性は、一緒にする必要があり、グループ化を無視することがあります。本当にもっとうまくできたはずです。
  2. パスルールを一致させるには、スキームとホストを指定する必要があります(現在、GoogleのAPIガイドに反しています)。
  3. 少なくともES File Explorerは、MIMEタイプが ""のインテントを生成します。これは、nullとは非常に異なる方法でフィルタリングされ、明示的に一致させることはできません。
  4. 「*/*」フィルターは、MIMEタイプがnullのインテントとは一致しません。この特定のケースでは、MIMEタイプのない別のフィルターが必要です。
  5. 元のファイル名はインテントで使用できないため(少なくともGmailでは)、「コンテンツ」スキームはMIMEタイプでのみ一致します。
  6. 個別の「データ」要素の属性のグループ化は、ホストとポートの特定の例外を除いて、(ほとんど)解釈とは無関係です-ペアになります。他のすべては、「データ」要素内または「データ」要素間の特定の関連付けを持ちません。

これらすべてを念頭に置いて、コメント付きの例を次に示します。

<!--
     Capture content by MIME type, which is how Gmail broadcasts
     attachment open requests.  pathPattern and file extensions
     are ignored, so the MIME type *MUST* be explicit, otherwise
     we will match absolutely every file opened.
-->
<intent-filter
    Android:icon="@drawable/icon"
    Android:label="@string/app_name"
    Android:priority="50" >
    <action Android:name="Android.intent.action.VIEW" />

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

    <data Android:scheme="file" />
    <data Android:scheme="content" />
    <data Android:mimeType="application/vnd.my-type" />
</intent-filter>

<!--
     Capture file open requests (pathPattern is honoured) where no
     MIME type is provided in the Intent.  An Intent with a null
     MIME type will never be matched by a filter with a set MIME
     type, so we need a second intent-filter if we wish to also
     match files with this extension and a non-null MIME type
     (even if it is non-null but zero length).
-->
<intent-filter
    Android:icon="@drawable/icon"
    Android:label="@string/app_name"
    Android:priority="50" >
    <action Android:name="Android.intent.action.VIEW" />

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

    <data Android:scheme="file" />
    <data Android:Host="*" />

    <!--
         Work around Android's ugly primitive PatternMatcher
         implementation that can't cope with finding a . early in
         the path unless it's explicitly matched.
    -->
    <data Android:pathPattern=".*\\.my-ext" />
    <data Android:pathPattern=".*\\..*\\.my-ext" />
    <data Android:pathPattern=".*\\..*\\..*\\.my-ext" />
    <data Android:pathPattern=".*\\..*\\..*\\..*\\.my-ext" />
    <data Android:pathPattern=".*\\..*\\..*\\..*\\..*\\.my-ext" />
    <data Android:pathPattern=".*\\..*\\..*\\..*\\..*\\..*\\.my-ext" />
    <data Android:pathPattern=".*\\..*\\..*\\..*\\..*\\..*\\..*\\.my-ext" />
</intent-filter>

<!--
     Capture file open requests (pathPattern is honoured) where a
     (possibly blank) MIME type is provided in the Intent.  This
     filter may only be necessary for supporting ES File Explorer,
     which has the probably buggy behaviour of using an Intent
     with a MIME type that is set but zero-length.  It's
     impossible to match such a type except by using a global
     wildcard.
-->
<intent-filter
    Android:icon="@drawable/icon"
    Android:label="@string/app_name"
    Android:priority="50" >
    <action Android:name="Android.intent.action.VIEW" />

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

    <data Android:scheme="file" />
    <data Android:Host="*" />
    <data Android:mimeType="*/*" />

    <!--
         Work around Android's ugly primitive PatternMatcher
         implementation that can't cope with finding a . early in
         the path unless it's explicitly matched.
    -->
    <data Android:pathPattern=".*\\.my-ext" />
    <data Android:pathPattern=".*\\..*\\.my-ext" />
    <data Android:pathPattern=".*\\..*\\..*\\.my-ext" />
    <data Android:pathPattern=".*\\..*\\..*\\..*\\.my-ext" />
    <data Android:pathPattern=".*\\..*\\..*\\..*\\..*\\.my-ext" />
    <data Android:pathPattern=".*\\..*\\..*\\..*\\..*\\..*\\.my-ext" />
    <data Android:pathPattern=".*\\..*\\..*\\..*\\..*\\..*\\..*\\.my-ext" />
</intent-filter>
26
David Sainty

Androidのファイルシステムからのメールとファイルからの添付ファイルを開くという単純なタスクは、これまでで最も厄介な経験の1つでした。しかし、stackoverflowに投稿されたほとんどのソリューションは、私にとっては正しく機能しませんでした。

私の要件は次のとおりです。

  • アプリで共有された添付ファイルをアプリで処理する
  • 私のアプリで生成されたファイルストレージ上のファイルを特定の拡張子を持つアプリで処理する

おそらく、このタスクを実行する最良の方法は、添付ファイルにカスタムMIMEタイプを指定することです。また、カスタムファイル拡張子を選択することもできます。そのため、アプリは「クールアプリ」と呼ばれ、最後に「.cool」を持つ添付ファイルを生成するとします。

これは私が目標に到達した中で最も近く、うまく機能しています...満足です。

<!-- Register to handle email attachments -->
<!-- WARNING: Do NOT use Android:Host="*" for these as they will not work properly -->
<intent-filter>
    <!-- needed for properly formatted email messages -->
    <data
        Android:scheme="content"
        Android:mimeType="application/vnd.coolapp"
        Android:pathPattern=".*\\.cool" />
    <!-- needed for mangled email messages -->
    <data
        Android:scheme="content"
        Android:mimeType="application/coolapp"
        Android:pathPattern=".*\\.cool" />
    <!-- needed for mangled email messages -->
    <data
        Android:scheme="content"
        Android:mimeType="application/octet-stream"
        Android:pathPattern=".*\\.cool" />

    <action Android:name="Android.intent.action.VIEW" />

    <category Android:name="Android.intent.category.DEFAULT" />
    <category Android:name="Android.intent.category.BROWSABLE" />
</intent-filter>

<!-- Register to handle file opening -->
<intent-filter>
    <data Android:scheme="file"
          Android:mimeType="*/*"
          Android:pathPattern=".*\\.cool"
          Android:Host="*"/>

    <action Android:name="Android.intent.action.VIEW" />

    <category Android:name="Android.intent.category.DEFAULT" />
    <category Android:name="Android.intent.category.BROWSABLE" />
</intent-filter>

ノート:

  • pathPatternは、添付ファイルでは(Android:scheme="content"を使用する場合)多かれ少なかれ無視されるようです。誰かが特定のパターンにのみ応答するようにpathPatternを取得した場合、どのように表示されるかわくわくします。
  • Android:Host="*"属性を追加した場合、Gmailアプリはセレクターにアプリをリストすることを拒否しました。
  • これらのintent-filterブロックがマージされた場合でもおそらく動作しますが、これを確認していません。
  • ファイルのダウンロード時にブラウザからのリクエストを処理するには、Android:scheme="http"を使用できます。特定のブラウザはAndroid:mimeTypeを台無しにする可能性があるので、Android:mimeType="*/*"を試して、実際に通過するものをデバッガーで確認し、フィルタリングを強化して、処理する迷惑なアプリにならないようにしてくださいすべて
  • 特定のファイルエクスプローラは、ファイルのMIMEタイプも台無しにします。上記のintent-filterは、SamsungのGalaxy S3上の「マイファイル」アプリでテストされました。 FXエクスプローラーはファイルを適切に開くことを拒否し、アプリのアイコンがファイルに使用されていないことにも気付きました。繰り返しますが、誰かがそれを機能させるようになったら、以下にコメントしてください。

これが便利であり、すべての可能な組み合わせを経て日を無駄にする必要がないことを願っています。改善の余地があるため、コメントを歓迎します。

23
omahena

上記のブライアンの答えは、その道の90%を私にもたらしました。それを仕上げるために、私はMIMEタイプのために使用しました

Android:mimeType="*/*"

以前のポスターは同じ詳細を投稿しようとしたのではないかと思いますが、スタースラッシュスターをコードとして十分に引用しないと、stackoverflowはそれを単なるスラッシュとして表示します。

10
Dawson

のではなく Android:path、試してみてください Android:mimeType 、この特定のコンテンツのMIMEタイプの値。また、Android:pathはワイルドカードを受け入れません- Android:pathPattern そのため。

8
CommonsWare

私はこれを長年にわたって機能させようとしてきましたが、基本的にすべての提案された解決策を試してみましたが、Androidを取得して特定のファイル拡張子を認識できません。 "*/*" mimetypeを持つインテントフィルターがあり、これが機能しているように見える唯一のものであり、ファイルブラウザーはファイルを開くためのオプションとしてアプリを一覧表示しますが、現在、アプリはANYを開くためのオプションとして表示されていますpathPatternタグを使用して特定のファイル拡張子を指定したにもかかわらず、ファイルの種類。連絡先リストで連絡先を表示/編集しようとしても、Androidから連絡先を表示するためにアプリを使用するかどうかを尋ねられますが、これは多くの状況の1つです発生し、非常に非常に迷惑です。

最終的に、実際のAndroidフレームワークエンジニアが答えた同様の質問でこのGoogleグループの投稿を見つけました。彼女はAndroidは単にファイル拡張子について何も知らず、MIMEタイプのみを知っていると説明しています( https://groups.google.com/forum/#!topic/Android-developers/a7qsSl3vQq )。

したがって、私が見て、試し、読んだものから、Androidはファイル拡張子を区別できず、pathPatternタグは基本的に膨大な時間とエネルギーの浪費です。特定のmimeタイプ(テキスト、ビデオ、オーディオなど)のファイルのみが必要な幸運な場合、mimeタイプでintent-filterを使用できます。ただし、特定のファイル拡張子またはAndroidで認識されないMIMEタイプが必要な場合は、運が悪くなります。

これについて間違っている場合は教えてください。これまでのところ、私はすべての投稿を読んで、提案された解決策をすべて試しましたが、どれもうまくいきませんでした。

これらの種類がAndroidでどのように一般的であるか、および開発者エクスペリエンスがどれほど台無しにされているかについて、別のページを1つか2つ書くことができますが、怒りの怒りを保存します;)。誰かのトラブルを救うことを願っています。

5
PeeGee85

接尾辞がAndroidのsystem = wide MIMEデータベースのMIMEタイプに登録されていない場合、VIEWまたはSENDアクションでは、上記のいずれも正常に機能しません。指定されたサフィックスに対して実行されることがわかった唯一の設定にはAndroid:mimeType="*/*"が含まれますが、アクションはすべてのファイルに対して実行されます。明らかにあなたが望むものではありません!

Android mimeデータベースにmimeとサフィックスを追加しないと適切な解決策を見つけることができません。これまでのところ、私はそれを行う方法を見つけていません。素晴らしい。

3
Glenn Widener

Android 4では、ルールは以前よりも厳格になりました。使用:

    <data
      Android:Host=""
      Android:mimeType="*/*"
      Android:pathPattern=".*\\.ext"
      Android:scheme="file"
    ></data>
3
Martin

私は、カスタムファイル拡張子について、これにかなり苦労しています。多くの検索の後、私は このWebページ を見つけました。ここで、ポスターにAndroidのpatternMatcherクラス(Intent-FiltersのpathPatternマッチングに使用される)がパスに最初の文字パスの他の場所での一致パターン(「* .xyz」と一致させようとしている場合、パスの前に「x」があるとpatternMatcherクラスは停止します)。これは彼が回避策のために見つけて、私のために働いたものですが、それはちょっとしたハックです:

PatternMatcherはIntentFilterのpathPatternに使用されますが、PatternMatcherのアルゴリズムは非常に奇妙です。 Android PatternMatcherのアルゴリズムです。

文字列の途中に「。*」パターンの「次の文字」がある場合、PatternMatcherはそのポイントでループを停止します。 (AndroidフレームワークのPatternMatcher.Javaを参照してください。)

例文字列:「これは私の添付ファイルです」パターン:「。att。」。 Android PatternMatcherは、パターンの次の文字(この例では 'a')に一致するまで '。'パターンに一致するループに入ります)したがって、 '。 'マッチングループはインデックス8-' is 'と' my 'の間の' a 'で停止するため、このマッチの結果は' false 'を返します。

かなり奇妙ですね。これを回避する-実際に可能性を減らす-開発者は迷惑な愚かなpathPatternを使用する必要があります。

例目標:「メッセージ」を含む一致するuriパス。

<intent-filter>
...
<data Android:pathPattern=".*message.*" />
<data Android:pathPattern=".*m.*message.*" />
<data Android:pathPattern=".*m.*m.*message.*" />
<data Android:pathPattern=".*m.*m.*m.*message.*" />
<data Android:pathPattern=".*m.*m.*m.*m.*message.*" />
...
</intent-filter>

これは、カスタムファイル拡張子と一致する場合に特に発行されます。

3
benjamin davis

ブライアンの答えは非常に近いですが、独自のカスタム拡張子を持つファイルを開こうとするときにアプリを呼び出すクリーンでエラーのない方法があります(スキームやホストは不要です):

<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:mimeType="*/*" />
    <data Android:pathPattern="*.*\\.kdb" />
</intent-filter>
3
Kon

インテントがintent-filterを満たす場合、これらはintent-filterの要件です(チェックリストを想像してください)。

  • 一致する<action>
  • 一致する<category>
  • 一致する<data mimeType>(簡単な修正: "/")
  • オプションで:

    • 一致する<data scheme>(簡単な修正:<data Android:scheme="file" /> <data Android:scheme="content" />

    • 一致する<data Host>(簡単な修正:「*」)

    • 一致する<data pathPattern/etc.>(たとえば.*\\.0cc

複数の<data $type="">要素を定義すると、<data $type=>Intentと一致する場合に限り、$ typeボックスがチェックされます。

MimeTypeを省略すると、冗長に見えますが、intent-filterが破損します。 <data scheme/Host/pathPattern>を省略すると、フィルターはすべてに一致します。

https://f-droid.org/en/packages/de.k3b.Android.intentintercept/ は、受信するように設計されたアプリですallインテント。インテントを検査できます。 Simple File Managerで開かれた認識されないファイル拡張子は、MIMEタイプapplication/octet-streamで配信されることを学びました。

https://stackoverflow.com/a/4621284/2683842 は、<data pathPattern=>.*xyzが最初のxで中断し、次の場合にすぐに失敗することを報告します。 yzが後に続かない。したがって、代わりに/sdcard/.hidden/foo.0ccを試さない限り、.*\\.0cc.*\\..*\\.0ccを渡しません。

  • この回避策が必要かどうかは確認しませんでした。

最終結果:

<activity Android:name=".Ft2NsfActivity">

    <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="content" />
        <data Android:Host="*" />
        <data Android:pathPattern=".*\\.ftm"/>
        <data Android:pathPattern=".*\\..*\\.ftm"/>
        <data Android:pathPattern=".*\\..*\\..*\\.ftm"/>
        <data Android:pathPattern=".*\\..*\\..*\\..*\\.ftm"/>
        <data Android:pathPattern=".*\\.0cc"/>
        <data Android:pathPattern=".*\\..*\\.0cc"/>
        <data Android:pathPattern=".*\\..*\\..*\\.0cc"/>
        <data Android:pathPattern=".*\\..*\\..*\\..*\\.0cc"/>
        <data Android:mimeType="*/*" />
    </intent-filter>

</activity>
2
jimbo1qaz

以下のフィルターを使用して、ブラウザー、Gmailおよびファイルブラウザー(テスト済み)から開きます。注:2つのフィルターをマージしないでください。ブラウザーがアプリを無視します(テスト済み)。

        <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:pathPattern=".*\\.ext" Android:mimeType="application/*"/>
            <data Android:scheme="content" Android:pathPattern=".*\\.ext" Android:mimeType="application/*"/>
        </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"
                  Android:Host="*"
                  Android:pathPattern=".*\\.ext" />
            <data Android:scheme="https"
                  Android:Host="*"
                  Android:pathPattern=".*\\.ext" />
            <data Android:scheme="ftp"
                  Android:Host="*"
                  Android:pathPattern=".*\\.ext" />

        </intent-filter>
1
Tran Hieu

Gmail、dropbox、またはbuildin Androidファイルツールのいずれかから直接ファイルを開く場合は、次のコードを使用します( 'Android:Host = "*"'を削除してGmailに到達できないファイル):

<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" Android:pathPattern=".*\\.kdb" 
          Android:mimeType="application/octet-stream"/>


</intent-filter>

<intent-filter>
    <action Android:name="Android.intent.action.VIEW"/>
    <category Android:name="Android.intent.category.DEFAULT"/>
    <data Android:scheme="file" Android:mimeType="*/*"     
          Android:pathPattern=".*\\.kdb"/>
</intent-filter>

データフィルタは、Androidバージョン4.xに従って1つのステートメントで記述する必要があります

1
AndreasReiff