Фильтр намерений Android для определенного расширения файла?

Я хочу, чтобы иметь возможность загружать файл с определенным расширением из "сети", и передать его в мое приложение, чтобы справиться с ним, но я не смог определить фильтр намерений. Тип файла не включен в типы mimetypes, и я попытался использовать

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

но я не мог заставить это работать.

Ответ 1

Вот как я определил свою активность в своем 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>

scheme of file указывает, что это должно произойти, когда локальный файл открывается (а не протокол, такой как HTTP).

mimeType может быть установлен в \*/\* для соответствия любому типу mime.

pathPattern указывает, какое расширение вы хотите сопоставить (в этом примере .kdb). .* в начале соответствует любому скрещиванию символов. Эти строки требуют двойного экранирования, поэтому \\\\. соответствует буквальному периоду. Затем вы заканчиваете расширение своего файла. Одно из предостережений с pathPattern заключается в том, что .* не является жадным сочетанием, как вы ожидали бы, если бы это было регулярное выражение. Этот шаблон не будет соответствовать путям, которые содержат . до .kdb. Более подробное обсуждение этой проблемы и обходной путь см. В here

Наконец, согласно документации на Android, для атрибута pathPattern требуются атрибуты host и scheme, поэтому просто установите это подстановочным знаком, чтобы что-либо соответствовать.

Теперь, если вы выберите файл .kdb в приложении, таком как Linda File Manager, мое приложение появится как опция. Следует отметить, что это одно не позволяет вам загрузить этот тип файла в браузере, так как он регистрируется только с файловой схемой. Наличие приложения, такого как Linda File Manager на вашем телефоне, полностью резервируется, позволяя вам загружать любой тип файла.

Ответ 2

Я должен признать, что простая задача открытия вложений из электронных писем и файлов из файловой системы на Android была одним из самых сумасшедших событий. Легко обрабатывать слишком много файлов или слишком мало. Но получить его правильно, сложно. Большинство решений, размещенных в stackoverflow, не работали корректно для меня.

Мои требования:

  • у меня есть приложения, связанные с приложением для приложения, совместно используемые моим приложением
  • У меня есть файлы с файлами приложения в хранилище, которые были созданы моим приложением и имеют определенное расширение

Вероятно, лучший способ решить эту задачу - указать настраиваемый тип 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 для ответа только на определенные шаблоны, я был бы в восторге от того, как это сделать.
  • Приложение Gmail отказалось отображать мое приложение в редакторе, если я добавил атрибут android:host="*".
  • Возможно, все еще работает, если эти блоки intent-filter объединены, но я не проверил это.
  • Чтобы обрабатывать запросы из браузера при загрузке файла, можно использовать android:scheme="http". Обратите внимание, что некоторые браузеры могут испортить android:mimeType, поэтому поэкспериментируйте с android:mimeType="*/*" и проверьте в отладчике то, что на самом деле прошло, а затем затяните фильтрацию, чтобы не оказаться в этом раздражающем приложении, которое обрабатывает все.
  • Некоторые поисковые роботы испортят MIME-типы для ваших файлов. Вышеупомянутый intent-filter был протестирован с помощью приложения Samsung My Files на Galaxy S3. FX Explorer по-прежнему отказывается правильно открыть файл, и я также заметил, что значок приложения не используется для файлов. Опять же, если кто-нибудь получит это, прокомментируйте ниже.

Я надеюсь, что вы найдете это полезным и что вам не придется терять дни, пройдя все возможные комбинации. Существует возможность для улучшения, поэтому комментарии приветствуются.

Ответ 3

Там много дезинформации по этой теме, не в последнюю очередь из собственной документации Google. Лучшее, и учитывая странную логику, возможно, единственной реальной документацией является исходный код.

фильтр фильтра намерений имеет логику, которая почти не поддается описанию. код парсера - это другой важный фрагмент головоломки.

Следующие фильтры довольно близки к разумному поведению. Шаблоны маршрутов применимы для целей схемы "файл".

Глобальное сопоставление шаблонов типа mime будет соответствовать всем типам, пока совпадает с расширением файла. Это не идеально, но это единственный способ сопоставить поведение файловых менеджеров, таких как ES File Explorer, и ограничивается намерениями, в которых соответствует расширение URI/файла.

Я не включил другие схемы, такие как "http" здесь, но они, вероятно, будут хорошо работать на всех этих фильтрах.

Нечетная схема - это "контент", для которой расширение недоступно фильтру. Но пока поставщик указывает ваш тип MIME (например, Gmail будет передавать тип MIME для беспрепятственного присоединения), фильтр будет соответствовать.

Gotchas должен знать:

  • Имейте в виду, что ничто не ведет себя последовательно в фильтрах, это лабиринт особых случаев и рассматривает нарушение принципа наименьшего удивления как цель дизайна. Ни один из алгоритмов сопоставления шаблонов не соответствует одному и тому же синтаксису или поведению. Отсутствие поля иногда является подстановочным знаком, а иногда и нет. Атрибуты внутри элемента данных иногда должны идти вместе и иногда игнорировать группировку. Это действительно могло быть сделано лучше.
  • Схема И хост должен быть указан для правил пути для соответствия (в отличие от руководства Google API в настоящее время).
  • По крайней мере, ES File Explorer генерирует намерения с MIME-типом ", который фильтруется совсем по-другому в значение null, невозможно явно сопоставить и может быть сопоставлен только рискованным фильтром" */*".
  • Фильтр "*/*" НЕ соответствует Intents с нулевым типом MIME - для этого требуется отдельный фильтр для этого конкретного случая без типа MIME вообще.
  • Схема "контент" может быть сопоставлена ​​только типу MIME, поскольку исходное имя файла недоступно в намерении (по крайней мере, с Gmail).
  • Группирование атрибутов в отдельных элементах "данных" (почти) не имеет отношения к интерпретации, за исключением исключения узла и порта, которые соединяются вместе. Все остальное не имеет определенной ассоциации в элементе данных или между элементами данных.

Имея это в виду, вот пример с комментариями:

<!--
     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 ugly primitive PatternMatcher
         implementation that can't cope with finding a . early in
         the path unless it 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 ugly primitive PatternMatcher
         implementation that can't cope with finding a . early in
         the path unless it 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>

Ответ 4

Брайан ответил, что получил 90% пути оттуда. Чтобы закончить его, для типа mime я использовал

android:mimeType="*/*"

Я подозреваю, что предыдущие плакаты пытались опубликовать ту же самую деталь, но, несмотря на то, что вместо звездной звезды слэш в качестве кода, stackoverflow дублирует его как просто слэш.

Ответ 5

Вместо android:path попробуйте android:mimeType со значением типа MIME этого конкретного фрагмента контента. Кроме того, android:path не принимает подстановочные знаки - используйте android:pathPattern для этого.

Ответ 6

Ответ Брайана очень близок, но здесь есть чистый и безошибочный способ вызвать ваше приложение при попытке открыть файл с помощью собственного пользовательского расширения (нет необходимости в схеме или хосте):

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

Ответ 7

В Android 4 правила стали более строгими, чем раньше. Использование:

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

Ответ 8

Ни одно из указанных выше не работает правильно, для действий VIEW или SEND, если суффикс не зарегистрирован в MIME-типе в базе данных Android system = wide MIME. Единственные настройки, которые я обнаружил, что огонь для указанного суффикса включают android:mimeType="*/*", но затем действие запускается для ВСЕХ файлов. Ясно, что вы не хотите!

Я не могу найти правильное решение, не добавляя mime и suffix в базу данных mime Android, до сих пор я не нашел способ сделать это. Если кто-нибудь знает, указатель будет потрясающим.

Ответ 9

Я так много боролся с этим для собственного расширения файла. После многого поиска я обнаружил эту веб-страницу, где плакат обнаружил, что класс Android patternMatcher (который используется для сопоставления PathPattern в Intent-Filters ) имеет неожиданное поведение, когда ваш путь содержит первый символ вашего шаблона соответствия в другом месте пути (например, если вы пытаетесь сопоставить "*.xyz", класс patternMatcher останавливается, если на вашем пути есть "x" ). Вот что он нашел для обходного пути и работал у меня, хотя это немного взломать:

PatternMatcher используется для PathPattern в IntentFilter. Но, Алгоритм PatternMatcher для меня довольно странный. Вот алгоритм Android PatternMatcher.

Если в середине строки есть "следующий символ" шаблона ". *", PatternMatcher останавливает цикл в этой точке. (См. PatternMatcher.java Android.)

Ex. string: шаблон "this my attachment": ".att.". Android PatternMatcher вводит цикл для соответствия '.' шаблон, чтобы встретить следующий характер шаблона (в этом примере, 'a') Итак, '.' контур соответствия останавливается с индексом 8 - 'a' между 'is' и 'my'. Поэтому результат этого match возвращает 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>

Это особенно актуально при сопоставлении с расширением пользовательского файла.

Ответ 10

Я пытаюсь заставить это работать целую вечность и пробовал все предлагаемые решения, и по-прежнему не может заставить Android распознавать определенные расширения файлов. У меня есть фильтр намерений с типом "*/*" mimetype, который, как представляется, работает, и файловые браузеры теперь перечисляют мое приложение в качестве опции для открытия файлов, однако теперь мое приложение показано как опция для открытия ЛЮБОГО ВИДА хотя я указал конкретные расширения файлов, используя тег pathPattern. Это до сих пор, что даже когда я пытаюсь просмотреть/редактировать контакт в моем списке контактов, Android спрашивает меня, хочу ли я использовать свое приложение для просмотра контакта, и это лишь одна из многих ситуаций, когда это происходит, ОЧЕНЬ ОЧЕНЬ раздражает.

В конце концов я нашел этот пост в группах google с похожим вопросом, на который ответил фактический разработчик Android. Она объясняет, что андроид просто ничего не знает о расширениях файлов, только MIME-типы (https://groups.google.com/forum/#!topic/android-developers/a7qsSl3vQq0).

Итак, из того, что я видел, пробовал и читал, Android просто не может различать между расширениями файлов и тегом pathPattern - это в основном гигантская трата времени и энергии. Если вам повезло, что вам нужны только файлы определенного типа mime (например, текст, видео или аудио), вы можете использовать фильтр намерений с типом mime. Если вам требуется определенное расширение файла или тип mime, неизвестный Android, однако вам не повезло.

Если я ошибаюсь в отношении любого из этого, скажите, пожалуйста, до сих пор я читал каждое сообщение и пробовал каждое предлагаемое решение, которое мог найти, но никто не работал.

Я мог бы написать еще одну или две страницы о том, насколько распространены такие вещи в Android и как навязчивый опыт разработчиков, но я сэкономлю вам свои разгневанные разглагольствования;). Надеюсь, я спасла кого-то от неприятностей.

Ответ 11

Если вы хотите, чтобы файлы открывались непосредственно из Gmail, dropbox или любого из файлов инструментов для сборки Android, используйте следующий код (delete '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

Ответ 12

Использование фильтра, как показано ниже, для открытия браузера, 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>