¿Filtro de intención de Android para una extensión de archivo en particular?

92

Quiero poder descargar un archivo con una extensión en particular de la red y que se lo pase a mi aplicación para que lo resuelva, pero no he podido averiguar el filtro de intención. El tipo de archivo no está incluido en los tipos MIME, e intenté usar

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

pero no pude hacer que eso funcionara.

Curioso
fuente

Respuestas:

119

Así es como definí mi actividad en mi AndroidManifest.xml para que esto funcione.

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

El schemedefile indica que esto debería suceder cuando se abre un archivo local (en lugar de un protocolo como HTTP).

mimeTypese puede configurar para \*/\*que coincida con cualquier tipo de mimo.

pathPatternes donde especifica qué extensión desea hacer coincidir (en este ejemplo .kdb). El .*al principio coincide con cualquier secuencia de caracteres. Estas cadenas requieren un doble escape, por lo que \\\\.coincide con un período literal. Luego, terminas con tu extensión de archivo. Una advertencia con pathPattern es que .*no es una coincidencia codiciosa como cabría esperar si fuera una expresión regular. Este patrón no coincidirá con las rutas que contienen un .antes de .kdb. Para una discusión más detallada de este problema y una solución, consulte aquí

Finalmente, de acuerdo con la documentación de Android, se requieren ambos atributos hosty schemepara elpathPattern atributo funcione, así que configúrelo en el comodín para que coincida con cualquier cosa.

Ahora, si selecciona un .kdbarchivo en una aplicación como Linda File Manager, mi aplicación aparece como una opción. Debo señalar que esto por sí solo no le permite descargar este tipo de archivo en un navegador, ya que solo se registra con el esquema de archivo. Tener una aplicación como Linda File Manager en su teléfono se resiste genéricamente permitiéndole descargar cualquier tipo de archivo.

Brian Pellin
fuente
3
Esto no funciona aquí. Primero con mimeType = " ", el paquete no se instala en Android 2.1, obtengo una MalformedMimeTypeException. El uso de "* / " corrige esto, pero luego, este filtro no tiene ningún efecto. Actualmente estoy probando con el navegador Skyfire, que no conserva el tipo de descarga mime, como lo hace el navegador estándar de Android. Y al hacer clic en un archivo en la lista de descargas de Skyfire, se transmite una intención VIEW simplista con los datos del archivo. Y este filtro de intención no coincide.
olivierg
@Brian Pellin: en realidad estaba buscando una forma de vincular un tipo mime a la .kdbxextensión para permitir que el explorador de archivos ES abra archivos kdbx cuando me señalaron esta publicación. Aparentemente, si la intención tiene un tipo MIME vacío, ¡este filtro de intención no funcionará! Además, es posible tener una intención con una cadena VACÍA como acción y solo un URI. Google Docs respondió a esa intención, por lo que debe ser válida.
billc.cn
2
Para que quede claro, mimeType debería ser "* / *". Creo que algunas personas se olvidaron de escapar de sus * s
Brian Pellin
1
Eso no funcionará con Android 4. Debería usar una <data>etiqueta con cuatro atributos. Tener 4 etiquetas es lógico O, que funcionó con Android 2, pero Android 4 es más estricto. Ver stackoverflow.com/questions/20650378/…
Martin
3
si \\\\.coincide con un período literal, ¿por qué no lo usa para formar una .kdbextensión como esta \\\\.kdb:?
Lealo
34

Hay mucha desinformación sobre este tema, sobre todo de la propia documentación de Google. Lo mejor, y dada la extraña lógica, posiblemente la única documentación real sea el código fuente.

La implementación del filtro de intención tiene una lógica que casi desafía la descripción. El código del analizador es la otra pieza relevante del rompecabezas.

Los siguientes filtros se acercan bastante al comportamiento sensato. Los patrones de ruta se aplican para las intenciones de esquema de "archivo".

La coincidencia de patrón de tipo de mimo global coincidirá con todos los tipos siempre que la extensión del archivo coincida. Esto no es perfecto, pero es la única forma de coincidir con el comportamiento de administradores de archivos como ES File Explorer, y se limita a las intenciones en las que coincide la extensión de archivo / URI.

No he incluido otros esquemas como "http" aquí, pero probablemente funcionarán bien en todos estos filtros.

El esquema extraño es "contenido", para el cual la extensión no está disponible para el filtro. Pero siempre que el proveedor indique su tipo de MIME (por ejemplo, Gmail transmitirá el tipo de MIME para el archivo adjunto sin obstáculos), el filtro coincidirá.

Puntos a tener en cuenta:

  1. Tenga en cuenta que nada se comporta de manera consistente en los filtros, es un laberinto de casos específicos y trata la violación del principio de mínima sorpresa como un objetivo de diseño. Ninguno de los algoritmos de coincidencia de patrones sigue la misma sintaxis o comportamiento. La ausencia de un campo a veces es un comodín y otras no lo es. Los atributos dentro de un elemento de datos a veces deben ir juntos y a veces ignorar la agrupación. Realmente podría haberse hecho mejor.
  2. El esquema Y el host deben especificarse para que las reglas de ruta coincidan (al contrario de la guía API de Google, actualmente).
  3. Al menos ES File Explorer genera intents con un tipo MIME de "", que se filtra de manera muy diferente a nulo, es imposible de hacer coincidir explícitamente y solo puede coincidir con el arriesgado filtro "* / *".
  4. El filtro "* / *" NO coincidirá con Intents con un tipo de MIME nulo, que requiere un filtro separado para este caso específico sin ningún tipo de MIME.
  5. El esquema de "contenido" solo puede coincidir con el tipo MIME, porque el nombre del archivo original no está disponible en la intención (al menos con Gmail).
  6. La agrupación de atributos en elementos de "datos" separados es (casi) irrelevante para la interpretación, con la excepción específica del host y el puerto, que se emparejan. Todo lo demás no tiene una asociación específica dentro de un elemento de "datos" o entre elementos de "datos".

Con todo esto en mente, aquí hay un ejemplo con comentarios:

<!--
     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>
David Sainty
fuente
Genial que te enfrentes a las muchas evidencias de necesidad de \\ .. una y otra vez y otras peculiaridades. Google debería haber solucionado esto en 4.2, qué demonios. Por desgracia, todavía tengo casos que su ejemplo no parece solucionar. ¿Hay algún problema con las extensiones de 6 cha como ".gblorb" que mi código funciona bien con 3 letras o menos?
RoundSparrow hilltx
¡La mejor respuesta a esta pregunta y preguntas similares en mi opinión! Lamentablemente, siempre que no sea posible hacer coincidir las intenciones de contenido por extensión de archivo (como señala en 5.), no es posible filtrar de manera confiable TODAS las intenciones correctas sin también coincidir con las incorrectas. Esto es para el caso en el que no puede utilizar un tipo de mímica personalizado. Entonces, mientras Android no proporcione una solución para esto, será un selector de archivos dentro de la aplicación para mí ... No quiero confundir al usuario con un comportamiento inconsistente.
Benjamin Bisinger
1
Muchas gracias .. Acabas de alegrarme el día .. En mi caso tuve que cambiar MimeType como <data android:mimeType="*/*" /> en las tres opciones y funcionó a la perfección para todas las aplicaciones, incluidas Google Drive y Gmail.
Rishabh Wadhwa
1
Me gustaría agradecerle mucho, @David Sainty. Pusiste fin a mi agonía de 24 horas de tratar de averiguar cómo manejarlo. Probé stackoverflow.com/q/18577860/6110285 , stackoverflow.com/a/8599921/6110285 y muchos más que fueron similares. Este es el único que funcionó.
pittix
24

Debo admitir que la simple tarea de abrir archivos adjuntos de correos electrónicos y archivos del sistema de archivos en Android ha sido una de las experiencias más enloquecedoras. Es fácil manejar demasiados archivos o muy pocos. Pero hacerlo bien es difícil. La mayoría de las soluciones publicadas en stackoverflow no funcionaron correctamente para mí.

Mis requisitos eran:

  • hacer que mi aplicación maneje archivos adjuntos compartidos por mi aplicación
  • hacer que mi aplicación maneje archivos en el almacenamiento de archivos que fueron generados por mi aplicación y tienen una extensión particular

Probablemente la mejor manera de realizar esta tarea es especificar un tipo MIME personalizado para sus archivos adjuntos. Y probablemente también optará por tener una extensión de archivo personalizada. Entonces, digamos que nuestra aplicación se llama "Cool App" y generamos archivos adjuntos que tienen ".cool" al final.

Esto es lo más cerca que estuve de mi objetivo y funciona ... satisfactorio.

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

Notas:

  • El pathPatternparece ser más o menos ignorado para los archivos adjuntos (cuando se utiliza android:scheme="content"). Si alguien consigue que pathPattern responda solo a ciertos patrones, me encantaría ver cómo.
  • La aplicación de Gmail se negó a incluir mi aplicación en el selector si agregué el android:host="*"atributo.
  • Probablemente todavía funcione si estos intent-filterbloques se combinan, pero no lo he verificado.
  • Para manejar las solicitudes de un navegador al descargar un archivo, android:scheme="http"se puede utilizar. Tenga en cuenta que ciertos navegadores pueden estropear el proceso, android:mimeTypeasí que experimente android:mimeType="*/*"y verifique en el depurador lo que realmente se transmite y luego ajuste el filtrado para no terminar siendo esa aplicación molesta que maneja todo .
  • Algunos exploradores de archivos también estropearán los tipos MIME de sus archivos. Lo anterior intent-filterse probó con la aplicación "Mis archivos" de Samsung en un Galaxy S3. El FX Explorer todavía se niega a abrir correctamente el archivo y también noté que el ícono de la aplicación no se usa para los archivos. Nuevamente, si alguien logra que eso funcione, comente a continuación.

Espero que esto le resulte útil y que no tenga que perder días revisando todas las combinaciones posibles. Hay margen de mejora, por lo que los comentarios son bienvenidos.

omahena
fuente
Esta es una solución funcional para mí. ¡Registrar un <intent-filter> separado para Content-Scheme y File-Scheme funcionó! ¡Gracias!
Mehlyfication
¡Gracias! Trabajó para mi. ¡Tanto la aplicación Gmail como la aplicación Samsung My Files en Galaxy S6 pudieron abrir un archivo con mi aplicación usando su solución!
Haris
¿Qué es exactamente el "nombre de la aplicación"? (En mi caso, el nombre de la aplicación legible por humanos tiene espacios)
William Jockusch
@WilliamJockusch parece que @DavidSainty simplemente está almacenando el nombre de la aplicación en el archivo de recursos de cadena. Los espacios deberían estar bien. La cadena utilizada para el android:labelfiltro de intención es la cadena que el usuario verá en el menú del selector. Por defecto, se utiliza el nombre de la aplicación.
omahena
¿Qué debo usar para la aplicación "Google Drive"?
desarrollador de Android
9

La respuesta de Brian arriba me llevó al 90% del camino. Para terminar, para el tipo de mimo usé

android:mimeType="*/*"

Sospecho que los carteles anteriores han intentado publicar el mismo detalle, pero sin citar la estrella de barra inclinada como código, stackoverflow lo muestra como una barra inclinada.

Dawson
fuente
2
Con esto, manejará TODOS los tipos de archivos, y eso es realmente molesto (bueno, excepto si su aplicación realmente maneja todo) ...
Tim Autin
Esto es malo. No hagas esto dentro de tus aplicaciones.
Marte
8

En lugar de android:pathintentarlo android:mimeType, con un valor del tipo MIME de este contenido en particular. Además, android:pathno acepta comodines; utilícelo android:pathPatternpara eso.

CommonsWare
fuente
"¿El tipo de archivo no está incluido en los tipos MIME"? Debería haber un tipo MIME para el tipo de contenido que está descargando, incluso si no usa la misma palabra.
Eric Mill
Hay un tipo MIME para el tipo de contenido, pero el archivo es producido por una aplicación de terceros que le pone una extensión diferente, así que no creo que se reconozca como ese tipo MIME.
Curyous
7

He intentado que esto funcione durante años y he probado básicamente todas las soluciones sugeridas y todavía no puedo hacer que Android reconozca extensiones de archivo específicas. Tengo un filtro de intención con un tipo "*/*"MIME que es lo único que parece funcionar y los navegadores de archivos ahora enumeran mi aplicación como una opción para abrir archivos, sin embargo, mi aplicación ahora se muestra como una opción para abrir CUALQUIER TIPO de archivo aunque He especificado extensiones de archivo específicas usando la etiqueta pathPattern. Esto va tan lejos que incluso cuando intento ver / editar un contacto en mi lista de contactos, Android me pregunta si quiero usar mi aplicación para ver el contacto, y esa es solo una de las muchas situaciones en las que esto ocurre, MUY MUY molesto.

Finalmente encontré esta publicación de grupos de Google con una pregunta similar a la que respondió un ingeniero de marco de Android real. Ella explica que Android simplemente no sabe nada sobre extensiones de archivo, solo tipos MIME ( https://groups.google.com/forum/#!topic/android-developers/a7qsSl3vQq0 ).

Entonces, por lo que he visto, probado y leído, Android simplemente no puede distinguir entre extensiones de archivo y la etiqueta pathPattern es básicamente una pérdida gigantesca de tiempo y energía. Si tiene la suerte de que solo necesite archivos de cierto tipo de mímica (por ejemplo, texto, video o audio), puede utilizar un filtro de intención con un tipo de mímica. Sin embargo, si necesita una extensión de archivo específica o un tipo de mímica que Android no conoce, no tiene suerte.

Si me equivoco en algo de esto, por favor dígame, hasta ahora he leído todas las publicaciones y he probado todas las soluciones propuestas que pude encontrar, pero ninguna ha funcionado.

Podría escribir una o dos páginas más sobre lo común que parecen ser este tipo de cosas en Android y lo jodida que es la experiencia del desarrollador, pero te ahorraré mis desvaríos;). Espero haberle ahorrado algunos problemas a alguien.

PeeGee85
fuente
1
Te votó a favor porque tu respuesta proporciona un enlace útil y el votante en contra no dejó ningún comentario. Lo siento, ASÍ puede ser antipático de esa manera a veces, pero no lo abandones.
John Hatton
3

La respuesta de Brian es muy cercana, pero aquí hay una forma limpia y sin errores de invocar su aplicación al intentar abrir un archivo con su propia extensión personalizada (sin necesidad de esquema o host):

<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>
Kon
fuente
2
La documentación de Android indica que el atributo pathPattern solo es significativo si se especifican un esquema y un host, y he verificado esto: developer.android.com/guide/topics/manifest/data-element.html
Brian Pellin
4
-1; esto coincidirá con cualquier archivo; El comentario de Brian es correcto y con la pequeña modificación de mimeType = " / " su ejemplo original es perfecto.
Nick
Esta publicación es de hace mucho tiempo, pero no "/" no se instala. Necesita "* / *", que coincidirá con cualquier tipo de archivo (no estoy seguro, si quería decir esto). Por lo tanto, es posible que se solicite a su programa que abra videos o mp3. Todavía no he encontrado una solución a esto.
Rene
Debe utilizar una <data>etiqueta con cuatro atributos. Su solución puede funcionar con Android 2, pero las reglas se han vuelto más estrictas: stackoverflow.com/questions/20650378/…
Martin
¿Qué pasa con el PathPattern extraño ? Y hosty schemeson obligatorios!
IgorGanapolsky
3

En Android 4, las reglas se volvieron más estrictas de lo que solían ser. Utilizar:

    <data
      android:host=""
      android:mimeType="*/*"
      android:pathPattern=".*\\.ext"
      android:scheme="file"
    ></data>
Martín
fuente
3

Yo mismo he estado luchando bastante con esto para obtener una extensión de archivo personalizada. Después de mucha búsqueda, encontré esta página web donde el cartel descubrió que la clase patternMatcher de Android (que se usa para la coincidencia de pathPattern en Intent-Filters) tiene un comportamiento inesperado cuando su ruta contiene el primer carácter de su patrón de coincidencia en otra parte de la ruta (como si estuviera intentando hacer coincidir "* .xyz", la clase patternMatcher se detiene si hay una "x" antes en su ruta). Esto es lo que encontró como solución alternativa y funcionó para mí, aunque es un truco:

PatternMatcher se usa para pathPattern en IntentFilter Pero, el algoritmo de PatternMatcher es bastante extraño para mí. Aquí está el algoritmo de Android PatternMatcher.

Si hay un 'carácter siguiente' del patrón '. *' En el medio de la cadena, PatternMatcher detiene el bucle en ese punto. (Consulte PatternMatcher.java del marco de Android).

Ex. cadena: "este es mi archivo adjunto" patrón: ". att. ". Android PatternMatcher introduce el bucle para que coincida '. 'patrón hasta encontrar el siguiente carácter de patrón (en este ejemplo,' a ') Entonces,'. 'el bucle coincidente se detiene en el índice 8 -' a 'entre' es 'y' mi '. Por lo tanto, el resultado de esta coincidencia devuelve "falso".

Muy extraño, ¿no? Para solucionar esto, en realidad reducir la posibilidad, el desarrollador debería usar un patrón de ruta estúpido y molesto.

Ex. Objetivo: Ruta de uri coincidente que incluye "mensaje".

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

Esto se emite especialmente al coincidir con la extensión de archivo personalizada.

benjamin davis
fuente
Para cualquier persona interesada, se ha registrado un problema en code.google.com
benjamin davis
3

Ninguno de los anteriores funciona correctamente, para las acciones VER o ENVIAR, si el sufijo no está registrado con un tipo MIME en el sistema de Android = base de datos MIME amplia. La única configuración que he encontrado que se activa para el sufijo especificado incluye android:mimeType="*/*", pero luego la acción se activa para TODOS los archivos. ¡Claramente NO es lo que quieres!

No puedo encontrar ninguna solución adecuada sin agregar el mime y el sufijo a la base de datos de mime de Android, hasta ahora, no he encontrado una manera de hacerlo. Si alguien lo sabe, un puntero sería fantástico.

Glenn Widener
fuente
2

Cuando un Intent cumple con un intent-filter, estos son los intent-filterrequisitos: (imagine una lista de verificación).

  • Cualquier coincidencia <action>
  • Cualquier coincidencia <category>
  • Cualquier coincidencia <data mimeType>(solución fácil: " / ")
  • Opcionalmente:

    • Cualquier coincidencia <data scheme>(solución fácil: <data android:scheme="file" /> <data android:scheme="content" />)

    • Cualquier coincidencia <data host>(solución fácil: "*")

    • Cualquier coincidencia <data pathPattern/etc.>(por ejemplo .*\\.0cc)

La definición de varios <data $type="">elementos marca la casilla $ type si alguna <data $type=>coincide con Intent.

Omitir mimeType rompe tu intent-filter, aunque aparentemente es redundante. Omitir <data scheme/host/pathPattern>hace que su filtro coincida con todo.

https://f-droid.org/en/packages/de.k3b.android.intentintercept/ es una aplicación diseñada para recibir todas las intenciones y le permite inspeccionar la intención. Aprendí que las extensiones de archivo no reconocidas que se abren a través de Simple File Manager se entregan con el tipo MIME application/octet-stream.

https://stackoverflow.com/a/4621284/2683842 informa que se <data pathPattern=> .*xyzcancela a la primera xque ve, y fallará inmediatamente si no lo sigue yz. Así /sdcard/.hidden/foo.0ccque no pasará a .*\\.0ccmenos que lo intentes .*\\..*\\.0cc.

  • No verifiqué si esta solución es necesaria.

Resultado final:

<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>
nyanpasu64
fuente
1

Si desea que los archivos se abran directamente desde Gmail, Dropbox o cualquiera de las herramientas de archivo de Android integradas, utilice el siguiente código (elimine 'android: host = "*"' que hizo que el archivo no fuera accesible para 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>

El filtro de datos debe estar escrito en una declaración según la versión 4.x de Android

AndreasReiff
fuente
He estado intentando todo para que la descarga y apertura del navegador Android funcione correctamente. Su solución funciona bien para el navegador nativo de Android y Android Chrome, sin embargo, Android Firefox todavía parece abrir mi archivo en una ventana de texto. Es un tipo de mimo personalizado y una extensión personalizada. Anteriormente, solo con la extensión, solo funcionaba en Firefox. Ahora funciona en todas partes excepto en Firefox (incluido Gmail). Todavía lo estoy probando, pero solo quería señalar el hecho de que hay un nuevo conjunto de problemas entre navegadores aquí.
Damon Smith
1

Usando el filtro como se muestra a continuación para abrir desde el navegador, gmail y el navegador de archivos (probado). NOTA: No combine dos filtros, eso hará que el navegador ignore su aplicación (probado).

        <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>
Tran Hieu
fuente
¿Ha probado esta respuesta con archivos adjuntos de Gmail?
IgorGanapolsky
1

Actualización 2020

Android se ha movido hacia URI de contenido y tipos MIME para filtros de intención.

El problema

Un URI de contenido no necesariamente tiene que contener la extensión o el nombre del archivo y será diferente entre las diferentes aplicaciones que proporcionan el contenido / archivo.

A continuación, se muestran algunos ejemplos de URI de contenido de diferentes aplicaciones de correo electrónico para el mismo archivo adjunto de correo electrónico:

Gmail -> content://com.google.android.gm.sapi/[email protected]/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

Aplicación de correo electrónico de Samsung -> content://com.samsung.android.email.attachmentprovider/1/1/RAW

Como puede ver, todos son diferentes y no se garantiza que contengan nada relacionado con su archivo real. Por lo tanto, no puede usar lo que la android:pathPatternmayoría ha sugerido.

Una solución alternativa para archivos adjuntos de correo electrónico

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

A través de las pruebas, encontré los tipos MIME que usaban Gmail, Outlook y Samsung Email y los agregué a mi filtro de intención.

Advertencias / errores

  • Descubrí que con mi solución anterior, si abría cualquier archivo que fuera de tipo binario, automáticamente iniciaría mi aplicación. Manejé esto en mi actividad mostrando un estado fallido si no podíamos analizar el archivo. Pensé que este era un evento bastante raro, por lo que sería aceptable.

  • No pude encontrar ninguna forma de iniciar mi aplicación a través del navegador de archivos sin agregar <data android:mimeType="*/*"/>a mi filtro de intención. No pude usar esto porque luego iniciaría mi aplicación cada vez que el usuario hiciera clic en cualquier archivo en su teléfono (no solo en los de extensión de archivo personalizado). No recomendaría agregar esto a su filtro de intención.

Pensamientos finales

  • Actualmente, no existe una solución elegante para asociar su aplicación con un tipo de extensión específico en Android. Esto fue lo mejor que pude hacer en mi situación.
alexander antaya
fuente