Bộ lọc ý định của Android cho một phần mở rộng tệp cụ thể?


92

Tôi muốn có thể tải xuống tệp có phần mở rộng cụ thể từ 'net và chuyển tệp đó đến ứng dụng của tôi để xử lý, nhưng tôi không thể tìm ra bộ lọc ý định. Loại tệp không có trong mimetypes và tôi đã thử sử dụng

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

nhưng tôi không thể làm việc đó.

Câu trả lời:


119

Đây là cách tôi xác định hoạt động của mình trong AndroidManifest.xml để làm cho điều này hoạt động.

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

Giá schemetrị của filechỉ ra rằng điều này sẽ xảy ra khi một tệp cục bộ được mở (thay vì giao thức như HTTP).

mimeTypecó thể được đặt \*/\*để phù hợp với bất kỳ loại kịch câm nào.

pathPatternlà nơi bạn chỉ định tiện ích mở rộng nào bạn muốn đối sánh (trong ví dụ này .kdb). Ở .*đầu phù hợp với bất kỳ bình phương ký tự nào. Các chuỗi này yêu cầu thoát kép, vì vậy \\\\.khớp với một khoảng thời gian theo nghĩa đen. Sau đó, bạn kết thúc với phần mở rộng tệp của mình. Một lưu ý với pathPattern là đó .*không phải là một kết hợp tham lam như bạn mong đợi nếu đây là một biểu thức chính quy. Mẫu này sẽ không khớp với các đường dẫn có chứa .trước .kdb. Để có một cuộc thảo luận chi tiết hơn về vấn đề này và cách giải quyết, hãy xem tại đây

Cuối cùng, theo tài liệu Android, cả hai hostschemethuộc tính là bắt buộc để pathPatternthuộc tính hoạt động, vì vậy chỉ cần đặt nó thành ký tự đại diện để khớp với bất kỳ thứ gì.

Bây giờ, nếu bạn chọn một .kdbtệp trong một ứng dụng như Trình quản lý tệp Linda, ứng dụng của tôi sẽ hiển thị dưới dạng một tùy chọn. Tôi nên lưu ý rằng chỉ điều này không cho phép bạn tải xuống loại tệp này trong trình duyệt, vì loại tệp này chỉ đăng ký với lược đồ tệp. Có một ứng dụng như Trình quản lý tệp Linda trên điện thoại của bạn nói chung sẽ chống lại chính nó cho phép bạn tải xuống bất kỳ loại tệp nào.


3
Điều này không hoạt động ở đây. Đầu tiên với mimeType = " ", gói không cài đặt trên Android 2.1, tôi nhận được MalformedMimeTypeException. Sử dụng "* / " sẽ sửa lỗi này, nhưng sau đó, bộ lọc này không có tác dụng. Tôi hiện đang thử nghiệm với trình duyệt Skyfire, trình duyệt này không bảo toàn kiểu tải xuống kịch câm như trình duyệt Android tiêu chuẩn vẫn làm. Và khi nhấp vào một tệp trong danh sách tải xuống Skyfire, một mục đích XEM đơn giản sẽ được phát cùng với dữ liệu tệp. Và bộ lọc ý định này không khớp.
olivierg

@Brian Pellin: Tôi thực sự đang tìm cách liên kết kiểu mime với .kdbxtiện ích mở rộng để cho phép trình khám phá tệp ES mở tệp kdbx khi tôi được chỉ đến bài đăng này. Rõ ràng nếu ý định có kiểu MIME trống, bộ lọc ý định này sẽ không hoạt động !! Ngoài ra, có thể có một ý định với chuỗi EMPTY làm hành động và chỉ là một URI. Google Documents đã phản hồi ý định đó, vì vậy nó phải hợp lệ.
billc.cn

2
Chỉ cần được rõ ràng, MIMETYPE nên "* / *" Tôi nghĩ một số người quên thoát của họ * s
Brian Pellin

1
Điều đó sẽ không hoạt động với Android 4. Bạn nên sử dụng trên <data>thẻ có bốn thuộc tính. Có 4 thẻ là hợp lý HOẶC - Hoạt động với Android 2 - nhưng Android 4 nghiêm ngặt hơn. Xem stackoverflow.com/questions/20650378/…
Martin

3
nếu \\\\.khớp với một khoảng thời gian theo nghĩa đen, tại sao bạn không sử dụng nó để tạo .kdbphần mở rộng như thế này \\\\.kdb:?
Lealo

34

Có rất nhiều thông tin sai lệch về chủ đề này, đặc biệt là từ tài liệu của chính Google. Điều tốt nhất, và dựa trên logic kỳ lạ, có thể là tài liệu thực duy nhất là mã nguồn.

Việc triển khai bộ lọc ý định có logic gần như bất chấp mô tả. Các đang phân tích cú pháp là mảnh khác có liên quan của các câu đố.

Các bộ lọc sau đây khá gần với hành vi hợp lý. Các mẫu đường dẫn được áp dụng cho ý định lược đồ "tệp".

Đối sánh kiểu kịch câm toàn cục sẽ khớp với tất cả các loại miễn là phần mở rộng tệp phù hợp. Đây không phải là hoàn hảo, nhưng là cách duy nhất để phù hợp với hành vi của trình quản lý tệp như ES File Explorer và nó bị giới hạn ở các ý định mà phần mở rộng tệp / URI khớp với nhau.

Tôi chưa bao gồm các lược đồ khác như "http" ở đây, nhưng chúng có thể sẽ hoạt động tốt trên tất cả các bộ lọc này.

Lược đồ kỳ lạ ngoài là "nội dung", mà phần mở rộng không có sẵn cho bộ lọc. Nhưng miễn là nhà cung cấp cho biết kiểu MIME của bạn (Ví dụ: Gmail sẽ chuyển kiểu MIME cho tệp đính kèm không bị cản trở), bộ lọc sẽ khớp.

Những điều cần lưu ý:

  1. Lưu ý rằng không có gì hoạt động nhất quán trong các bộ lọc, đó là một mê cung của các trường hợp cụ thể và coi việc vi phạm nguyên tắc ít gây bất ngờ nhất làm mục tiêu thiết kế. Không có thuật toán đối sánh mẫu nào tuân theo cùng một cú pháp hoặc hành vi. Sự vắng mặt của một trường đôi khi là một ký tự đại diện và đôi khi không phải. Các thuộc tính trong một phần tử dữ liệu đôi khi phải đi cùng nhau và đôi khi bỏ qua việc nhóm. Nó thực sự có thể được thực hiện tốt hơn.
  2. Lược đồ VÀ máy chủ phải được chỉ định để các quy tắc đường dẫn phù hợp (trái với hướng dẫn API của Google, hiện tại).
  3. Ít nhất ES File Explorer tạo ra các ý định với kiểu MIME là "", được lọc rất khác với null, không thể đối sánh rõ ràng và chỉ có thể được đối sánh bằng bộ lọc "* / *" đầy rủi ro.
  4. Bộ lọc "* / *" sẽ KHÔNG đối sánh Ý định với kiểu MIME rỗng - yêu cầu bộ lọc riêng cho trường hợp cụ thể này không có kiểu MIME nào cả.
  5. Lược đồ "nội dung" chỉ có thể được đối sánh theo kiểu MIME, vì tên tệp gốc không có sẵn trong ý định (ít nhất là với Gmail).
  6. Việc nhóm các thuộc tính trong các phần tử "dữ liệu" riêng biệt (hầu như) không liên quan đến việc diễn giải, ngoại trừ máy chủ và cổng cụ thể - chúng kết hợp với nhau. Mọi thứ khác không có liên kết cụ thể trong phần tử "dữ liệu" hoặc giữa các phần tử "dữ liệu".

Với tất cả những điều này, đây là một ví dụ với các nhận xét:

<!--
     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>

Tuyệt vời là bạn có thể đáp ứng được nhiều nhu cầu đã được chứng minh về \\ .. lặp đi lặp lại và những điều kỳ quặc khác. Google lẽ ra đã sửa lỗi này bằng 4.2, cái quái gì vậy. Than ôi, tôi vẫn có những trường hợp mà ví dụ của bạn dường như không khắc phục được. Có một số vấn đề với phần mở rộng 6 cha như ".gblorb" mà mã của tôi hoạt động tốt với 3 chữ cái trở xuống không?
RoundSparrow hilltx

Câu trả lời tốt nhất cho câu hỏi này và các câu hỏi tương tự theo ý kiến ​​của tôi! Đáng buồn thay, miễn là không thể khớp các ý định nội dung theo phần mở rộng tệp (như bạn đã chỉ ra ở phần 5.), thì không thể lọc một cách đáng tin cậy TẤT CẢ các ý định đúng mà không đối sánh các ý định sai. Đây là trường hợp bạn không thể sử dụng loại kịch câm tùy chỉnh. Vì vậy, miễn là Android không cung cấp giải pháp cho vấn đề này, nó sẽ trở thành trình chọn tệp trong ứng dụng đối với tôi ... Tôi không muốn khiến người dùng nhầm lẫn với hành vi không nhất quán.
Benjamin Bisinger, 20/09/17

1
Cảm ơn rất nhiều .. Bạn vừa thực hiện một ngày của tôi .. Trong trường hợp của tôi, tôi đã phải thay đổi MimeType như <data android:mimeType="*/*" /> trong cả ba tùy chọn và nó hoạt động như một sự quyến rũ cho tất cả các ứng dụng bao gồm Google Drive và Gmail.
Rishabh Wadhwa

1
Tôi muốn cảm ơn bạn rất nhiều, @David Sainty. Bạn đã chấm dứt sự đau khổ kéo dài 24 giờ của tôi khi cố gắng tìm ra cách xử lý nó. Tôi đã thử stackoverflow.com/q/18577860/6110285 , stackoverflow.com/a/8599921/6110285 và nhiều ứng dụng khác tương tự. Đây là cái duy nhất hoạt động.
pittix

24

Tôi phải thừa nhận rằng tác vụ đơn giản là mở tệp đính kèm từ email và tệp từ hệ thống tệp trên Android là một trong những trải nghiệm khó khăn hơn bao giờ hết. Có thể dễ dàng xử lý quá nhiều tệp hoặc quá ít. Nhưng làm cho nó vừa phải thật khó. Hầu hết các giải pháp được đăng trên stackoverflow không hoạt động chính xác đối với tôi.

Yêu cầu của tôi là:

  • ứng dụng của tôi có xử lý tệp đính kèm được chia sẻ bởi ứng dụng của tôi không
  • để ứng dụng của tôi xử lý các tệp trên bộ nhớ được tạo bởi ứng dụng của tôi và có một tiện ích mở rộng cụ thể

Có lẽ cách tốt nhất để thực hiện nhiệm vụ này là chỉ định Loại MIME tùy chỉnh cho tệp đính kèm của bạn. Và bạn có thể cũng sẽ chọn có một phần mở rộng tệp tùy chỉnh. Vì vậy, giả sử rằng ứng dụng của chúng tôi được gọi là "Ứng dụng tuyệt vời" và chúng tôi tạo các tệp đính kèm có ".cool" ở cuối.

Đây là lần gần nhất tôi đạt được mục tiêu của mình và nó hoạt động ... khả quan.

<!-- 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>

Ghi chú:

  • Các pathPatterndường như được nhiều hay ít bỏ qua cho file đính kèm (khi sử dụng android:scheme="content"). Nếu ai đó nhận được pathPattern chỉ phản hồi với một số mẫu nhất định, tôi sẽ rất vui khi biết cách làm.
  • Ứng dụng Gmail đã từ chối liệt kê ứng dụng của tôi trong trình chọn nếu tôi đã thêm android:host="*"thuộc tính.
  • Nó có thể vẫn hoạt động nếu các intent-filterkhối này được hợp nhất nhưng tôi chưa xác minh điều này.
  • Để xử lý các yêu cầu từ trình duyệt khi tải xuống tệp, tệp android:scheme="http"có thể được sử dụng. Lưu ý rằng một số trình duyệt nhất định có thể làm rối tung android:mimeTypequá trình thử nghiệm android:mimeType="*/*"và kiểm tra trình gỡ lỗi những gì thực sự được chuyển qua và sau đó thắt chặt bộ lọc để không trở thành ứng dụng khó chịu xử lý mọi thứ .
  • Một số Trình khám phá tệp nhất định cũng sẽ làm rối loại MIME cho tệp của bạn. Ở trên intent-filterđã được thử nghiệm với ứng dụng "My Files" của Samsung trên Galaxy S3. FX Explorer vẫn từ chối mở tệp đúng cách và tôi cũng nhận thấy rằng biểu tượng ứng dụng không được sử dụng cho các tệp. Một lần nữa, nếu bất cứ ai nhận được điều đó để làm việc, xin vui lòng bình luận bên dưới.

Tôi hy vọng bạn sẽ thấy điều này hữu ích và bạn sẽ không phải mất nhiều ngày để xem qua tất cả các kết hợp có thể. Có chỗ để cải thiện vì vậy nhận xét được hoan nghênh.


Đây là một giải pháp làm việc cho tôi. Đăng ký một <intent-filter> riêng biệt cho Content-Scheme và File-Scheme đã thực hiện một mẹo nhỏ! Cảm ơn!
Mehlyfication

Cảm ơn! Đã làm cho tôi. Cả ứng dụng Gmail và ứng dụng Samsung My Files trên Galaxy S6 đều có thể mở tệp bằng ứng dụng của tôi bằng giải pháp của bạn!
Haris

"Tên ứng dụng" chính xác là gì? (Trong trường hợp của tôi, tên ứng dụng có thể đọc được của con người có khoảng trắng trong đó.)
William Jockusch.

@WilliamJockusch có vẻ như @DavidStain chỉ đơn giản là lưu trữ tên ứng dụng trong tệp tài nguyên chuỗi. Không gian sẽ ổn. Chuỗi được sử dụng cho android:labelbộ lọc ý định là chuỗi mà người dùng sẽ thấy trong menu bộ chọn. Theo mặc định tên ứng dụng được sử dụng.
omahena

Tôi nên sử dụng gì cho ứng dụng "Google Drive"?
nhà phát triển Android

9

Câu trả lời của Brian ở trên đã giúp tôi đi được 90% chặng đường. Để kết thúc nó, đối với loại kịch câm tôi đã sử dụng

android:mimeType="*/*"

Tôi nghi ngờ rằng các áp phích trước đó đã cố gắng đăng cùng một chi tiết, nhưng mặc dù lấy dấu sao gạch chéo làm mã, nhưng stackoverflow hiển thị nó chỉ là một dấu gạch chéo.


2
Với điều này, bạn sẽ xử lý TẤT CẢ các loại tệp và điều đó thực sự khó chịu (tốt, ngoại trừ nếu ứng dụng của bạn thực sự xử lý mọi thứ) ...
Tim Autin

Điều này tệ đây. Vui lòng không làm điều này bên trong ứng dụng của bạn.
Mars

8

Thay vào đó android:path, hãy thử android:mimeTypevới giá trị kiểu MIME của phần nội dung cụ thể này. Ngoài ra, android:pathkhông chấp nhận ký tự đại diện - sử dụng android:pathPatterncho điều đó.


"Loại tệp không có trong mimetypes"? Vẫn phải có một mimetype cho loại nội dung bạn đang tải xuống, ngay cả khi nó không sử dụng cùng một từ.
Eric Mill

Có một kiểu mimetype cho loại nội dung, nhưng tệp được tạo ra bởi một ứng dụng của bên thứ ba có phần mở rộng khác trên đó, vì vậy tôi không nghĩ nó sẽ được công nhận là kiểu mimetype đó.
Curyous

7

Tôi đã cố gắng làm cho điều này hoạt động trong nhiều thời gian và về cơ bản đã thử tất cả các giải pháp được đề xuất nhưng vẫn không thể khiến Android nhận ra phần mở rộng tệp cụ thể. Tôi có một bộ lọc ý định với một "*/*"mimetype là thứ duy nhất có vẻ hoạt động và các trình duyệt tệp hiện liệt kê ứng dụng của tôi như một tùy chọn để mở tệp, tuy nhiên, ứng dụng của tôi hiện được hiển thị dưới dạng tùy chọn để mở BẤT KỲ LOẠI tệp nào mặc dù Tôi đã chỉ định các phần mở rộng tệp cụ thể bằng thẻ pathPattern. Điều này đi xa đến mức ngay cả khi tôi cố gắng xem / chỉnh sửa một số liên lạc trong danh sách liên hệ của mình, Android vẫn hỏi tôi liệu tôi có muốn sử dụng ứng dụng của mình để xem số liên lạc đó không và đó chỉ là một trong nhiều tình huống xảy ra, RẤT RẤT khó chịu.

Cuối cùng, tôi thấy nhóm google này đăng bài với câu hỏi tương tự mà một kỹ sư khung Android thực tế đã trả lời. Cô ấy giải thích rằng android đơn giản không biết gì về phần mở rộng tệp, chỉ có kiểu MIME ( https://groups.google.com/forum/#!topic/android-developers/a7qsSl3vQq0 ).

Vì vậy, từ những gì tôi đã thấy, thử và đọc, Android chỉ đơn giản là không thể phân biệt giữa các phần mở rộng tệp và thẻ pathPattern về cơ bản là một sự lãng phí lớn về thời gian và năng lượng. Nếu bạn đủ may mắn để chỉ cần các tệp thuộc một loại kịch câm nhất định (ví dụ văn bản, video hoặc âm thanh), bạn có thể sử dụng bộ lọc ý định với loại kịch câm. Tuy nhiên, nếu bạn cần một phần mở rộng tệp cụ thể hoặc một loại kịch câm mà Android không biết thì bạn đã không gặp may.

Nếu tôi sai về bất kỳ điều nào trong số này, vui lòng cho tôi biết, cho đến nay tôi đã đọc mọi bài đăng và thử mọi giải pháp được đề xuất mà tôi có thể tìm thấy nhưng không có giải pháp nào hiệu quả.

Tôi có thể viết một hoặc hai trang khác về mức độ phổ biến của những thứ này trong Android và trải nghiệm của nhà phát triển bị ảnh hưởng như thế nào, nhưng tôi sẽ lưu lại cho bạn những lời giận dữ của tôi;). Hy vọng tôi đã cứu ai đó một số rắc rối.


1
Bình chọn bạn vì câu trả lời của bạn đưa ra một liên kết hữu ích và người phản đối không để lại nhận xét. Xin lỗi VẬY đôi khi có thể không thân thiện theo cách đó, nhưng đừng từ bỏ nó.
John Hatton

3

Câu trả lời của Brian rất gần gũi, nhưng đây là một cách rõ ràng và không có lỗi để ứng dụng của bạn được gọi khi cố gắng mở một tệp có phần mở rộng tùy chỉnh của riêng bạn (không cần lược đồ hoặc máy chủ):

<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
Các trạng thái tài liệu Android rằng thuộc tính pathPattern chỉ có ý nghĩa nếu một chương trình và máy chủ được quy định, và tôi đã xác minh này: developer.android.com/guide/topics/manifest/data-element.html
Brian Pellin

4
-1; điều này sẽ khớp với bất kỳ tệp nào ; Nhận xét của Brian là đúng và với sửa đổi nhỏ của mimeType = " / ", ví dụ ban đầu của anh ấy là hoàn hảo.
Nick

Bài này nếu từ lâu rồi mà không có "/" thì không cài được. Bạn cần "* / *", sẽ phù hợp với bất kỳ loại tệp nào (không chắc chắn, nếu bạn muốn nói điều này). Vì vậy, chương trình của bạn có thể được yêu cầu mở video hoặc mp3. Tôi vẫn chưa tìm ra giải pháp cho điều này.
Rene

Bạn nên sử dụng một <data>thẻ có bốn thuộc tính. Giải pháp của bạn có thể hoạt động với Android 2 - nhưng các quy tắc đã trở nên nghiêm ngặt hơn: stackoverflow.com/questions/20650378/…
Martin

Chuyện gì xảy ra với pathPattern kỳ lạ ? Và hostschemeđược yêu cầu!
IgorGanapolsky

3

Trên Android 4, các quy tắc trở nên nghiêm ngặt hơn trước đây. Sử dụng:

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

3

Bản thân tôi cũng đã khá vất vả với điều này cho một phần mở rộng tệp tùy chỉnh. Sau rất nhiều lần tìm kiếm, tôi đã tìm thấy trang web này , nơi người đăng phát hiện ra rằng lớp patternMatcher của Android (được sử dụng cho đối sánh pathPattern trong Intent-Filters) có hành vi không mong muốn khi đường dẫn của bạn chứa ký tự đầu tiên của mẫu đối sánh của bạn ở nơi khác trong đường dẫn (giống như nếu bạn đang cố gắng đối sánh "* .xyz", lớp patternMatcher sẽ dừng nếu có "x" trước đó trong đường dẫn của bạn). Đây là những gì anh ấy tìm thấy cho một giải pháp thay thế và đã làm việc cho tôi, mặc dù nó có một chút hack:

PatternMatcher được sử dụng cho pathPattern tại IntentFilter Nhưng, thuật toán của PatternMatcher khá xa lạ với tôi. Đây là thuật toán của Android PatternMatcher.

Nếu có 'ký tự tiếp theo' của mẫu '. *' Ở giữa chuỗi, PatternMatcher dừng vòng lặp tại điểm đó. (Xem PatternMatcher.java của khung Android.)

Ví dụ. string: "đây là tệp đính kèm của tôi" mẫu: ". att. ". Android PatternMatcher nhập vòng lặp để khớp '. 'pattern cho đến khi gặp ký tự tiếp theo của pattern (tại ví dụ này,' a ') Vì vậy,'. 'vòng lặp phù hợp dừng lại ở chỉ số 8 -' a 'giữa' là 'và' của tôi '. Do đó kết quả của trận đấu này trả về 'false'.

Khá lạ phải không. Để giải quyết vấn đề này - thực sự giảm khả năng xảy ra - nhà phát triển nên sử dụng pathPattern ngu ngốc gây phiền nhiễu.

Ví dụ. Mục tiêu: Phù hợp với đường dẫn đi tiểu bao gồm 'thông báo'.

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

Điều này đặc biệt được phát hành khi khớp với phần mở rộng tệp tùy chỉnh.


Đối với bất cứ ai quan tâm, một vấn đề đã được ghi lại ở code.google.com
benjamin davis

3

Không có thao tác nào ở trên hoạt động đúng cách, đối với các hành động XEM hoặc GỬI, nếu hậu tố không được đăng ký với kiểu MIME trong cơ sở dữ liệu system = wide MIME của Android. Cài đặt duy nhất mà tôi tìm thấy kích hoạt cho hậu tố được chỉ định bao gồm android:mimeType="*/*", nhưng sau đó hành động kích hoạt cho TẤT CẢ tệp. Rõ ràng KHÔNG phải những gì bạn muốn!

Tôi không thể tìm thấy bất kỳ giải pháp thích hợp nào mà không thêm kịch câm và hậu tố vào cơ sở dữ liệu kịch câm của Android, cho đến nay, tôi vẫn chưa tìm ra cách để thực hiện điều đó. Nếu ai đó biết, một con trỏ sẽ rất tuyệt vời.


2

Khi một Ý định đáp ứng a intent-filter, đây là các intent-filteryêu cầu: (hãy tưởng tượng một danh sách kiểm tra).

  • Mọi kết hợp <action>
  • Mọi kết hợp <category>
  • Mọi kết quả phù hợp <data mimeType>(sửa chữa dễ dàng: " / ")
  • Tùy chọn:

    • Bất kỳ phù hợp nào <data scheme>(sửa chữa dễ dàng <data android:scheme="file" /> <data android:scheme="content" />:)

    • Mọi kết quả phù hợp <data host>(sửa chữa dễ dàng: "*")

    • Bất kỳ kết hợp nào <data pathPattern/etc.>(ví dụ .*\\.0cc)

Việc xác định nhiều <data $type="">phần tử sẽ kiểm tra hộp $ type iff bất kỳ <data $type=>khớp nào với Intent.

Việc bỏ qua mimeType sẽ phá vỡ cấu hình của bạn intent-filter, mặc dù nó có vẻ thừa. Việc bỏ qua <data scheme/host/pathPattern>khiến bộ lọc của bạn khớp với mọi thứ.

https://f-droid.org/en/packages/de.k3b.android.intentintercept/ là một ứng dụng được thiết kế để nhận tất cả ý định và cho phép bạn kiểm tra ý định. Tôi được biết rằng các phần mở rộng tệp không được công nhận được mở qua Trình quản lý tệp đơn giản được phân phối với loại MIME application/octet-stream.

https://stackoverflow.com/a/4621284/2683842 báo cáo rằng <data pathPattern=> .*xyzhủy bỏ ở lần đầu tiên xnó nhìn thấy và sẽ thất bại ngay lập tức nếu không được làm theo yz. Vì vậy, /sdcard/.hidden/foo.0ccsẽ không vượt qua .*\\.0cctrừ khi bạn cố gắng .*\\..*\\.0ccthay thế.

  • Tôi đã không xác minh xem giải pháp này có cần thiết hay không.

Kết quả cuối cùng:

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

1

Nếu bạn muốn các tệp được mở trực tiếp từ Gmail, dropbox hoặc bất kỳ công cụ tệp android buildin nào, thì hãy sử dụng mã sau (xóa 'android: host = "*"' đã khiến tệp không thể truy cập được đối với 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>

Bộ lọc dữ liệu phải được viết trong một câu lệnh theo phiên bản Android 4.x


Tôi đã thử mọi cách để cố gắng tải và mở trình duyệt android hoạt động bình thường. Giải pháp của bạn hoạt động tốt cho trình duyệt gốc android và android chrome, tuy nhiên android firefox dường như vẫn mở tệp của tôi trong cửa sổ văn bản. Đó là một loại kịch câm tùy chỉnh và tiện ích mở rộng tùy chỉnh. Trước đây chỉ với phần mở rộng, nó chỉ hoạt động trong firefox. Bây giờ nó hoạt động ở mọi nơi ngoại trừ firefox (bao gồm cả gmail). Tôi vẫn đang thử nghiệm nó nhưng tôi chỉ muốn gắn cờ thực tế là có một loạt các vấn đề trình duyệt chéo mới ở đây.
Damon Smith vào

1

Sử dụng bộ lọc như bên dưới để mở từ trình duyệt, gmail và trình duyệt tệp (Đã kiểm tra). LƯU Ý: Vui lòng không hợp nhất hai bộ lọc, điều đó sẽ khiến trình duyệt bỏ qua ứng dụng của bạn (Đã kiểm tra).

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

Bạn đã kiểm tra câu trả lời này với các tệp đính kèm trong Gmail chưa?
IgorGanapolsky

1

Cập nhật năm 2020

Android đã hướng tới URI nội dung và MIME-Kiểu cho các bộ lọc ý định.

Vấn đề

URI nội dung không nhất thiết phải chứa phần mở rộng hoặc tên của tệp và nó sẽ khác nhau giữa các ứng dụng khác nhau đang cung cấp nội dung / tệp.

Dưới đây là một số URI nội dung mẫu từ các ứng dụng email khác nhau cho cùng một tệp đính kèm email:

Gmail -> content://com.google.android.gm.sapi/some_email@gmail.com/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

Ứng dụng Email Samsung -> content://com.samsung.android.email.attachmentprovider/1/1/RAW

Như có thể thấy tất cả chúng đều khác nhau và không được đảm bảo chứa bất kỳ thứ gì liên quan đến tệp thực của bạn. Do đó, bạn không thể sử dụngandroid:pathPattern giống như hầu hết đã đề xuất.

Giải pháp xoay quanh giải pháp cho tệp đính kèm email

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

Qua kiểm tra, tôi đã tìm thấy Các loại MIME mà Gmail, Outlook và Samsung Email đã sử dụng và thêm chúng vào bộ lọc ý định của tôi.

Báo trước / Gotchas

  • Tôi thấy rằng với giải pháp trên, nếu tôi mở bất kỳ tệp nào thuộc loại nhị phân, nó sẽ tự động khởi chạy ứng dụng của tôi. Tôi đã xử lý điều này trong hoạt động của mình bằng cách hiển thị trạng thái không thành công nếu chúng tôi không thể phân tích cú pháp tệp. Tôi nghĩ đây là một sự kiện khá hiếm hoi nên có thể chấp nhận được.

  • Tôi không thể tìm thấy bất kỳ cách nào để khởi chạy ứng dụng của mình qua trình duyệt tệp mà không thêm <data android:mimeType="*/*"/>vào bộ lọc ý định của mình. Tôi không thể sử dụng điều này vì sau đó nó sẽ khởi chạy ứng dụng của tôi bất cứ khi nào người dùng nhấp vào bất kỳ tệp nào trên điện thoại của họ (không chỉ những tệp có phần mở rộng tùy chỉnh). Tôi không khuyên bạn nên thêm nó vào bộ lọc ý định của bạn.

Lời kết

  • Hiện không có giải pháp hữu ích nào để liên kết ứng dụng của bạn với một loại tiện ích mở rộng cụ thể trong Android. Đây là điều tốt nhất tôi có thể làm trong hoàn cảnh của mình.
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.