102

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

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

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

4

15 に答える 15

125

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>

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

mimeType*/*任意の MIME タイプに一致するように設定できます。

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

最後に、Android のドキュメントによると、属性が機能するにはhostscheme属性の両方が必要なpathPatternので、ワイルドカードに設定するだけで何にでも一致します。

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

于 2010-01-14T04:15:34.023 に答える
41

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

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

次のフィルターは、賢明な動作にかなり近づきます。"file"スキームの意図のために、パスパターンは適用されます。

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

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

奇妙なスキーム out は"content"であり、その拡張子はフィルターで使用できません。ただし、プロバイダーが MIME タイプを指定している限り (たとえば、Gmail は添付ファイルの MIME タイプを妨げられずに渡します)、フィルターは一致します。

注意すべき点:

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

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

<!--
     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>
于 2015-06-24T13:52:02.597 に答える
27

メールの添付ファイルや Android のファイルシステムのファイルを開くという単純なタスクは、これまでで最も気が狂った経験の 1 つであることを認めなければなりません。処理するファイルが多すぎたり少なすぎたりするのは簡単です。しかし、それを正しくするのは難しいです。stackoverflow に投稿されたソリューションのほとんどは、私にとっては正しく機能しませんでした。

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

  • アプリで共有されている添付ファイルをアプリで処理する
  • アプリによって生成され、特定の拡張子を持つ filestorage 上のファイルをアプリで処理する

おそらく、このタスクを実行する最善の方法は、添付ファイルにカスタム MIME タイプを指定することです。また、おそらくカスタム ファイル拡張子を選択することもあるでしょう。では、アプリの名前が「Cool App」で、末尾に「.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は、Galaxy S3 の Samsung の「My Files」アプリでテストされました。FX Explorer はまだファイルを正しく開くことを拒否しており、アプリ アイコンがファイルに使用されていないことにも気付きました。繰り返しますが、誰かがそれを機能させた場合は、以下にコメントしてください。

これが便利であり、考えられるすべての組み合わせを何日も無駄にする必要がないことを願っています。まだまだ改善の余地ありですのでコメントお待ちしております。

于 2014-10-15T22:12:03.343 に答える
10

上記のブライアンの答えにより、90%の方法が得られました。最後に、使用した MIME タイプに

android:mimeType="*/*"

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

于 2011-05-23T23:26:30.290 に答える
9

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

于 2009-11-14T11:58:05.713 に答える
4

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

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

于 2013-01-20T18:25:28.700 に答える
3

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

<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>
于 2011-07-22T21:11:44.627 に答える
3

私自身、カスタムファイル拡張子のためにこれにかなり苦労してきました。何度も検索した結果、Android の patternMatcher クラス (Intent-Filters での pathPattern マッチングに使用される) が、パスに一致パターンの最初の文字が含まれている場合に予期しない動作をすることを投稿者が発見したこの Web ページを見つけました。 (「*.xyz」に一致させようとしている場合のように、パスの前に「x」がある場合、patternMatcher クラスは停止します)。これは彼が回避策として見つけたもので、私のために働いていましたが、それは少しハックです:

IntentFilter の pathPattern には PatternMatcher を使用していますが、PatternMatcher のアルゴリズムは私にはかなり奇妙です。これが Android PatternMatcher のアルゴリズムです。

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

元。string : "これは私の添付ファイルです" pattern : ". att. ". Android PatternMatcher はループに入って一致する '. ' pattern の次の文字 (この例では '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>

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

于 2014-04-25T20:32:31.930 に答える