2009-11-14 92 views
75

我希望能夠從網上下載一個特定擴展名的文件,並將它傳遞給我的應用程序來處理它,但我一直無法弄清楚意圖過濾器。文件類型不包括在mimetypes中,並且我嘗試使用針對特定文件擴展名的Android意圖過濾器?

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

但我無法讓它工作。

回答

8

不是android:path,嘗試android:mimeType,用MIME類型這個特定內容片段的的值。此外,android:path不接受通配符 - 爲此使用android:pathPattern

+0

「的文件類型爲不包括在MIME類型」?即使不使用相同的單詞,仍然應該爲您正在下載的內容的類型設置MIME類型。 – Konklone 2009-11-15 17:24:17

+0

內容類型有一個mimetype,但該文件是由第三方應用程序生成的,該應用程序在其上放置了不同的擴展名,所以我認爲它不會被識別爲該mimetype。 – Curyous 2009-11-16 23:58:08

109

這是我如何定義我在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> 

filescheme表示當本地文件被打開(而不是像HTTP協議)是這樣的話。

mimeType可以被設置爲\*/\*匹配任何mime類型。

pathPattern是您指定要匹配(在這個例子中.kdb)什麼擴展。開頭的.*匹配任何字符序列。這些字符串需要雙重轉義,因此\\\\.與文字週期匹配。然後,你以文件擴展名結束。與pathPattern的一個警告是.*不是像你期望的貪婪的比賽,如果這是一個正則表達式。該模式將無法匹配在.kdb之前包含.的路徑。對於這個問題和解決方法的更詳細的討論,請參閱here

最後,根據Android文檔,既hostscheme屬性是必需的pathPattern屬性的工作,所以才設置爲通配符匹配任何東西。

現在,如果你選擇一個.kdb文件中像琳達文件管理器應用程序,我的應用程序顯示爲一個選項。我應該注意到,這本身並不允許你在瀏覽器中下載這個文件類型,因爲這隻能在文件方案中註冊。在您的手機上安裝一個類似Linda文件管理器的應用程序,一般可以讓您下載任何文件類型。

+2

這在這裏不起作用。首先用mimeType =「*」,該包不安裝在Android 2.1上,我得到一個MalformedMimeTypeException。使用「*/*」解決了這個問題,但是這個過濾器沒有效果。我目前正在使用Skyfire瀏覽器進行測試,該瀏覽器不像標準的Android瀏覽器那樣保留MIME類型的下載。當點擊Skyfire下載列表中的文件時,會通過文件數據廣播簡單的VIEW意圖。而這個意圖過濾器不匹配。 – olivierg 2011-02-08 12:43:41

+0

@Brian Pellin:我實際上正在尋找一種方法將mime類型綁定到'.kdbx'擴展名,以便ES文件瀏覽器可以在指向這篇文章時打開kdbx文件。顯然,如果意圖有一個空的MIME類型,這個意圖過濾器將不起作用!另外,可以將EMPTY字符串作爲動作並且只是一個URI。 Google文檔對該意圖做出了迴應,因此它必須有效。 – 2011-09-06 01:50:34

+0

作爲另一張海報下面提到(+1他,他值得),改爲mimeType =「*/*」的作品。 – Nick 2011-12-16 16:54:27

9

上述Brian的回答讓我90%的方式出現。爲了完成它,對於MIME類型我用

android:mimeType="*/*" 

我懷疑以前的海報已經嘗試發佈相同的細節,但withough qoting明星斜線明星作爲代碼,計算器diplays它只是一個斜線。

+1

有了這個,你將處理所有的文件類型,這是非常惱人的(當然,除非你的應用程序確實處理一切)... – 2016-09-02 20:56:59

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> 
+2

Android的文件指出,如果指定的方案和主機的pathPattern屬性是唯一有意義的,我已經驗證了這一點:http://developer.android.com/guide/topics/manifest/data-element.html – 2011-09-28 18:35:35

+4

-1;這將匹配*任何*文件; Brian的評論是正確的,並且對mimeType =「*/*」的小修改,他的原始示例是完美的。 – Nick 2011-12-16 16:52:39

+0

這篇文章如果很久以前,但沒有「/」不安裝。你需要「\ */\ *」,它將匹配任何文件類型(不確定,如果你打算這麼說)。所以你的程序可能會被要求打開視頻或MP3。我還沒有找到解決辦法。 – Rene 2012-01-22 10:01:04

2

對於VIEW或SEND操作,如果後綴未在Android的system = wide MIME數據庫中註冊爲MIME類型,以上都無法正常工作。我發現指定後綴的唯一設置包括android:mimeType="*/*",但是隨後操作會觸發所有文件。顯然不是你想要的!

我找不到任何適當的解決方案,而沒有將mime和後綴添加到Android mime數據庫,到目前爲止,我還沒有找到一種方法來做到這一點。如果有人知道,指針會非常棒。

3

在Android 4上,規則變得越來越嚴格,他們以前就是這樣。用途:

<data 
     android:host="" 
     android:mimeType="*/*" 
     android:pathPattern=".*\\.ext" 
     android:scheme="file" 
    ></data> 
1

如果你想將文件直接從Gmail中,Dropbox的或任何的buildin Android文件的工具打開,然後使用下面的代碼(刪除「機器人:主機=‘*’」那做出的文件無法訪問的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版

+0

我一直在嘗試一切嘗試讓android瀏覽器下​​載並打開正常工作。你的解決方案適用於android原生瀏覽器和android chrome,但是android firefox仍然可以在文本窗口中打開我的文件。這是一個自定義MIME類型和自定義擴展。以前只有擴展名,它只能在firefox中工作。現在除了firefox(包括gmail)以外,它都可以工作。我仍在測試它,但我只是想說明這裏有一個新的跨瀏覽器問題。 – 2014-03-20 11:14:00

+0

你確實認識到** android:host **是強制性的,對吧? – 2017-10-18 18:58:49

1

我一直在爲此而努力頗有幾分自定義文件擴展名,我自己。經過大量搜索之後,我發現this web page海報發現Android的patternMatcher類(用於Intent-Filters中的PathPattern匹配)在您的路徑包含路徑中其他位置的匹配模式的第一個字符時具有意外行爲(如如果你想匹配「* .xyz」,如果你的路徑中有一個「x」,patternMatcher類就會停止)。以下是他找到了一個解決辦法,併爲我工作,雖然這是一個黑客位的:

PatternMatcher用於在IntentFilter的pathPattern但是, PatternMatcher的算法是很奇怪我。這是Android PatternMatcher的算法 。

如果在字符串中間有'。*'模式的'下一個字符', PatternMatcher在該點停止循環。 (請參閱 Android框架的PatternMatcher.java。)

Ex。字符串:「這是我的附件」模式:「。att。」。 Android PatternMatcher輸入循環以匹配'。 '模式,直到遇到下一個 模式的字符(在這個例子中,'a')所以,'。'匹配循環 在索引8停止 - 'is'和'my'之間的'a'。因此,這個 匹配的結果返回'false'。

很奇怪,不是嗎。爲了解決這個問題 - 實際上減少了 的可能性 - 開發者應該使用令人討厭的愚蠢的pathPattern。

Ex。目標:匹配包含'消息'的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> 

自定義文件擴展匹配時,這是特別發出。

+0

對於任何有興趣的人,問題已記錄在[code.google.com](https://code.google.com/p/android/issues/detail?id=69080) – 2014-06-18 15:31:02

+0

並且此答案是否適合您? – 2017-10-18 18:58:09

1

使用下面的過濾器從瀏覽器打開,gmail &文件瀏覽器(測試)。 注意:請不要合併兩個過濾器,這將使瀏覽器忽略您的應用程序(測試)。

 <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> 
+0

您是否使用Gmail附件測試過此答案? – 2017-10-18 19:09:40

19

我必須承認,從Android設備上的文件系統從打開電子郵件和文件附件的簡單的任務一直是以往任何時候都更讓人鬱悶的經歷之一。處理太多文件或太少是很容易的。但要做到這一點很困難。大多數發佈在stackoverflow上的解決方案對我來說都不正確。

我的要求是:

  • 有我的應用程序手柄附件通過我的應用程序共享
  • 有我的應用程序處理通過我的應用程序生成的上filestorage文件和具有特定擴展名

可能要完成此任務的最佳方式是爲附件指定自定義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已通過Galaxy S3上的三星「我的文件」應用進行了測試。 FX瀏覽器仍然拒絕正確打開文件,我也注意到應用程序圖標不用於文件。再次,如果有人得到這個工作,請在下面評論。

我希望你會發現這個有用的,你不會浪費天,經歷所有可能的組合。有改進的空間,所以歡迎評論。

+0

這是我的工作解決方案。爲Content-Scheme和File-Scheme註冊一個單獨的做了個竅門!謝謝! – Mehlyfication 2015-01-28 14:53:14

+0

謝謝!爲我工作。 Galaxy S6上的Gmail應用程序和Samsung My Files應用程序都可以使用您的解決方案使用我的應用程序打開文件! – Haris 2015-05-29 03:35:52

+0

「應用程序名稱」究竟是什麼? (就我而言,人類可讀的應用程序名稱中包含空格。) – 2016-08-18 18:36:15

-1

我一直在試圖讓這個工作多年,並基本上嘗試了所有建議的解決方案,仍然無法讓Android識別特定的文件擴展名。我有一個"*/*" MIME類型的意圖過濾器,這是唯一的似乎工作和文件瀏覽器現在列出我的應用程序作爲打開文件的選項,但我的應用程序現在顯示爲一個選項打開任何種類的文件甚至儘管我已經使用pathPattern標籤指定了特定的文件擴展名。到目前爲止,甚至當我嘗試查看/編輯聯繫人列表中的聯繫人時,Android會詢問我是否想使用我的應用查看聯繫人,而這只是發生這種情況的許多情況之一,非常非常煩人。

最終我發現這個谷歌羣組發佈了一個類似的問題,一個實際的Android框架工程師回答。她解釋說,android根本不知道任何關於文件擴展名的內容,只知道MIME類型(https://groups.google.com/forum/#!topic/android-developers/a7qsSl3vQq0)。

所以從我所看到的,試圖讀,安卓根本無法文件的擴展和pathPattern標籤區分是basicly的時間和精力浪費巨大。如果您有幸只需要某種特定MIME類型的文件(比如文本,視頻或音頻),則可以使用MIME類型的意向過濾器。如果你需要一個特定的文件擴展名或者Android不知道的MIME類型,那麼你的運氣不好。

如果我錯了,任何有關這請告訴我,至今我讀過每一個崗位,並想盡提出的解決方案,我可以找到,但沒有工作過。

我可以另寫兩頁關於這些事情如何共同似乎是在Android和如何搞砸了開發人員的經驗是,但我會拯救你我的憤怒咆哮)。希望我救了一些人一些麻煩。

13

關於此主題有很多錯誤信息,特別是來自Google自己的文檔。最好的,並給予奇怪的邏輯,可能唯一真正的文檔是源代碼。

intent filter implementation具有幾乎無法描繪的邏輯。 parser code是拼圖的另一個相關部分。

下面的過濾器非常接近合理的行爲。路徑模式適用於「文件」方案意圖。

只要文件擴展名匹配,全局MIME類型模式匹配將匹配所有類型。這並不完美,但它是匹配文件管理器(如ES文件資源管理器)的行爲的唯一方法,並且它僅限於URI /文件擴展名匹配的意圖。

我還沒有包括其他方案,如「HTTP」在這裏,但他們可能會在所有這些過濾器正常工作。

奇怪的方案是「內容」,擴展名不適用於過濾器。但只要提供者聲明您的MIME類型(例如,Gmail將傳遞MIME類型以使附件暢通無阻),則過濾器將匹配。

陷阱要注意的:

  1. 要知道,沒有在過濾器一貫的行爲,它是specal情況下迷宮,以及對待違反了最小驚訝的原則作爲設計目標。沒有一種模式匹配算法遵循相同的語法或行爲。缺少一個字段有時是一個通配符,有時不是。數據元素中的屬性有時必須放在一起,有時會忽略分組。它本來可以做得更好。
  2. 該方案和主機必須指定路徑規則來匹配(目前與Google的API指南相反)。
  3. 至少ES文件瀏覽器生成的意圖與MIME類型的「」,將其過濾非常不同爲null時,不可能明確地匹配,並且只能由有風險的匹配「*/*」過濾器。
  4. 「*/*」過濾器不會與空MIME類型的Intents相匹配 - 對於這種特定情況,根本不需要MIME類型,這需要單獨的過濾器。
  5. 「內容」方案只能與MIME類型匹配,因爲原始文件名在意圖中不可用(至少在Gmail中)。
  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> 
+0

偉大的,你站起來\\ ..一遍又一遍的許多證據需要和其他怪癖。谷歌應該已經修正了4.2,這到底是什麼。唉,我仍然有你的例子似乎無法解決的情況。是否有一些像「.gblorb」這樣的6個擴展名的問題,我的代碼可以正常工作3個字母或更少? – 2017-02-08 07:00:53

+0

這個問題的最佳答案和我認爲類似的問題! 不幸的是,只要無法通過文件擴展匹配內容意圖(如您在5中指出的那樣),就不可能可靠地篩選出所有正確的意圖,而不會匹配錯誤的意圖。這適用於您不能使用自定義MIME類型的情況。 因此,只要Android不提供解決方案,它將成爲應用程序內的文件選擇器......我不想讓用戶感到不一致的行爲。 – 2017-09-20 10:18:39

相關問題