Android Как создать фильтр намерений для пользовательского расширения файла, который НЕ делает его частью средства выбора для всего на телефоне

Я видел здесь множество ответов о создании фильтра намерений для пользовательского расширения файла, но ни один из них, похоже, не отвечает на мой вопрос:

У меня есть фильтр намерений, который работает прямо сейчас ... когда я просматриваю свой файл или открываю его из вложения электронной почты, мое приложение появляется в списке. Сам файл имеет собственное расширение «tgtp», но в основном это просто файл xml.

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

Я пробовал десятки различных комбинаций фильтров намерений с разными схемами, типами MIME и т. Д., И некоторые по-прежнему позволяют мне открывать файл, если я просматриваю его с помощью файлового браузера, но мне особенно нужно иметь возможность открывать вложения электронной почты и открыть как файловый браузер. Мне еще предстоит найти фильтр (ы) намерений, который позволил бы мне сделать это, не делая мое приложение доступным для всех других средств выбора намерений.

Вот мой текущий фильтр намерений, который использует мое приложение, чтобы все открывать:

<intent-filter>
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<data android:mimeType="*/*" />
<data android:pathPattern=".*\\.tgtp" />   
</intent-filter>

заранее спасибо


person Nick    schedule 01.03.2012    source источник


Ответы (4)


Единственный способ решить эту проблему - добавить атрибуты scheme и host к вашему фильтру намерений:

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

Это потому, что в документации сказано, что android:pathPattern работает, только если определены схема и хост. http://developer.android.com/guide/topics/manifest/data-element.html

Надеюсь, поможет.

person sabadow    schedule 05.03.2012
comment
И, конечно, это то, что я читал много раз, но все равно не смог этого сделать ... Это сработало как шарм. Думаю, я был сбит с толку из-за десятков подобных вопросов с десятками разных ответов. Спасибо, что указали на простое и хорошо задокументированное решение :) - person Nick; 05.03.2012
comment
Это сработало для вас? У меня ТОЧНО те же обстоятельства и потребности, что и в случае, указанном выше. Когда мой фильтр намерений имеет схему, mimeType и хост, как показано в этом ответе, он вообще не работает ни для одного сценария. Если я удалю mimeType из вашего ответа, решение будет работать для файлов, открытых в проводнике. Мне все еще нужно иметь возможность открывать файлы этого типа как вложения в сообщениях электронной почты. Был ли этот ответ обобщенным, и мне действительно нужно предоставить определенные mimeTypes и хосты, или я должен был указать именно то, что показано (потому что это не сработало) - person gauglerb; 05.01.2014
comment
На самом деле это лучший ответ. Я искал об этом последние 2 дня, но есть много ответов, и большинство из них не работают и настолько сложны, но вы определили его в нескольких строках. Теперь я хочу сделать свое приложение приложением по умолчанию. для файла .mp3, поэтому, когда пользователь нажимает на файл mp3, мое приложение должно открыться и воспроизвести этот файл .. как это возможно ?? - person neeraj kirola; 27.08.2014
comment
При этом не откроется пользовательское вложение в Gmail, для которого требуется android: host = gmail-ls. - person IgorGanapolsky; 20.10.2017

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

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

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

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

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

person benjamin davis    schedule 25.04.2014

Один из возможных ответов показан здесь. По сути, попробуйте открыть следующий фильтр намерений внутри желаемого тега активности:

<intent-filter android:priority="999">
    <action android:name="android.intent.action.VIEW" />

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

    <data android:host="*" />
    <data android:mimeType="application/octet-stream" />
    <data android:pathPattern=".*\\..*\\..*\\..*\\..*\\.yourextension" />
    <data android:pathPattern=".*\\..*\\..*\\..*\\.yourextension" />
    <data android:pathPattern=".*\\..*\\..*\\.yourextension" />
    <data android:pathPattern=".*\\..*\\.yourextension" />
    <data android:pathPattern=".*\\.yourextension" />
    <data android:scheme="content" />
</intent-filter>
person Ráfagan    schedule 03.05.2019

У меня точно такая же проблема, и в моем случае оба других ответа не работают. Самое близкое, что я пришел, - это когда я объединяю ответы Бенджамина и Сабадоу, -и- опускаю точку в расширении, вот так: (я использую свое собственное расширение ".trk")

        <!-- For opening/viewing only trk-files: (works in google drive and "File Manager", not  gmail) -->
        <intent-filter>
            <action android:name="android.intent.action.VIEW" />
            <action android:name="android.intent.action.SEND" />
            <action android:name="android.intent.action.SEND_MULTIPLE" />
            <action android:name="android.intent.action.SENDTO" />

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

            <data android:scheme="file" android:mimeType="*/*" android:pathPattern=".*trk" android:host="*" />
            <data android:scheme="file" android:mimeType="*/*" android:pathPattern=".*t.*trk" android:host="*" />
            <data android:scheme="file" android:mimeType="*/*" android:pathPattern=".*t.*t.*trk" android:host="*" />
            <data android:scheme="file" android:mimeType="*/*" android:pathPattern=".*t.*t.*t.*trk" android:host="*" />
            <data android:scheme="file" android:mimeType="*/*" android:pathPattern=".*t.*t.*t.*t.*trk" android:host="*" />
            <data android:scheme="file" android:mimeType="*/*" android:pathPattern=".*t.*t.*t.*t.*t.*trk" android:host="*" />
            <data android:scheme="file" android:mimeType="*/*" android:pathPattern=".*t.*t.*t.*t.*t.*t.*trk" android:host="*" />
            <data android:scheme="file" android:mimeType="*/*" android:pathPattern=".*t.*t.*t.*t.*t.*t.*t.*trk" android:host="*" />
        </intent-filter>          
        <!-- For catching attachments in Gmail: (also triggers non-trk-files that aren't associated with some other app, but not non-trk-files that already have one of more associations, strangely) -->
        <intent-filter>
            <action android:name="android.intent.action.VIEW" />
            <action android:name="android.intent.action.SEND" />
            <action android:name="android.intent.action.SEND_MULTIPLE" />
            <action android:name="android.intent.action.SENDTO" />

            <category android:name="android.intent.category.DEFAULT" />
            <category android:name="android.intent.category.BROWSABLE" />
            <data android:mimeType="*/*" android:scheme="content" />
        </intent-filter>
        <!-- For catching share actions from apps: (also triggered by sharing actions for all other file types) -->
        <intent-filter>
            <action android:name="android.intent.action.SEND" />
            <category android:name="android.intent.category.DEFAULT" />

            <data android:mimeType="application/*" />
        </intent-filter>

Это немного длинновато, но вам могут не понадобиться все строки, например действия SENDTO и SEND_MULTIPLE. Мне просто нужно, чтобы он работал во всех случаях, когда он может работать. К сожалению, это также срабатывает в некоторых, но не во всех случаях.

person Popke Altenburg    schedule 04.09.2014