Filtro de intenção do Android para uma extensão de arquivo específica?

92

Quero poder fazer download de um arquivo com uma extensão específica da 'rede e passá-lo ao meu aplicativo para lidar com isso, mas não consegui descobrir o filtro de intent. O tipo de arquivo não está incluído nos tipos MIME e tentei usar

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

mas não consegui fazer isso funcionar.

Curyous
fonte

Respostas:

119

Aqui está como eu defini minha atividade em meu AndroidManifest.xml para fazer isso funcionar.

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

O schemede fileindica que isso deve acontecer quando um arquivo local é aberto (em vez de um protocolo como HTTP).

mimeTypepode ser definido para \*/\*corresponder a qualquer tipo MIME.

pathPatterné onde você especifica a extensão que deseja corresponder (neste exemplo .kdb). O .*no início corresponde a qualquer sequência de caracteres. Essas strings requerem escape duplo, portanto, \\\\.corresponde a um período literal. Então, você termina com sua extensão de arquivo. Uma ressalva com pathPattern é que .*não é uma correspondência gananciosa como você esperaria se fosse uma expressão regular. Este padrão não corresponderá aos caminhos que contêm um .antes de .kdb. Para uma discussão mais detalhada deste problema e uma solução alternativa, consulte aqui

Finalmente, de acordo com a documentação do Android, os atributos hoste schemesão necessários para que o pathPatternatributo funcione, então apenas defina-o como o caractere curinga para corresponder a qualquer coisa.

Agora, se você selecionar um .kdbarquivo em um aplicativo como Linda File Manager, meu aplicativo aparecerá como uma opção. Devo observar que isso sozinho não permite que você baixe este tipo de arquivo em um navegador, uma vez que ele só é registrado no esquema de arquivo. Ter um aplicativo como o Linda File Manager em seu telefone resiste-se genericamente, permitindo que você baixe qualquer tipo de arquivo.

Brian Pellin
fonte
3
Isso não funciona aqui. Primeiro, com mimeType = " ", o pacote não é instalado no Android 2.1, recebo uma MalformedMimeTypeException. Usar "* / " corrige isso, mas então, este filtro não tem efeito. No momento, estou testando com o navegador Skyfire, que não preserva o tipo mime de downloads, como o navegador Android padrão faz. E ao clicar em um arquivo na lista de downloads do Skyfire, uma intenção VIEW simplista é transmitida com os dados do arquivo. E este filtro de intent não corresponde.
Olivierg
@Brian Pellin: Na verdade, eu estava procurando uma maneira de vincular um tipo MIME à .kdbxextensão para permitir que o ES explorer abrisse arquivos kdbx quando fui apontado para este post. Aparentemente, se o intent tiver um tipo MIME vazio, esse filtro de intent não funcionará !! Além disso, é possível ter um intent com uma string EMPTY como a ação e apenas um URI. O Google Docs respondeu a essa intenção, portanto, deve ser válida.
billc.cn
2
Só para ficar claro, mimeType deve ser "* / *" Acho que algumas pessoas se esqueceram de escapar de seus * s
Brian Pellin
1
Isso não funcionará com o Android 4. Você deve usar uma <data>tag com quatro atributos. Ter 4 tags é lógico OU - que funcionou com o Android 2 - mas o Android 4 é mais restrito. Consulte stackoverflow.com/questions/20650378/…
Martin
3
se \\\\.corresponder a um período literal, por que você não o usa para formar uma .kdbextensão como esta \\\\.kdb:?
Lealo
33

Há muita desinformação sobre este assunto, principalmente da própria documentação do Google. O melhor, e dada a lógica estranha, possivelmente a única documentação real é o código-fonte.

A implementação do filtro de intenção tem uma lógica que quase desafia a descrição. O código do analisador é a outra peça relevante do quebra-cabeça.

Os filtros a seguir chegam muito perto de um comportamento sensato. Os padrões de caminho se aplicam, para intenções de esquema de "arquivo".

A correspondência de padrão de tipo MIME global corresponderá a todos os tipos, desde que a extensão do arquivo corresponda. Isso não é perfeito, mas é a única maneira de corresponder ao comportamento de gerenciadores de arquivos como o ES File Explorer, e é limitado a intenções em que o URI / extensão de arquivo corresponde.

Não incluí outros esquemas como "http" aqui, mas provavelmente funcionarão bem em todos esses filtros.

O esquema estranho é "conteúdo", para o qual a extensão não está disponível para o filtro. Mas, desde que o provedor indique seu tipo MIME (por exemplo, o Gmail passará o tipo MIME para o anexo sem impedimentos), o filtro corresponderá.

Tenho que estar ciente de:

  1. Esteja ciente de que nada se comporta de forma consistente nos filtros, é um labirinto de casos especais e trata a violação do princípio da menor surpresa como um objetivo de design. Nenhum dos algoritmos de correspondência de padrões segue a mesma sintaxe ou comportamento. A ausência de um campo às vezes é um caractere curinga e às vezes não é. Os atributos dentro de um elemento de dados às vezes devem estar juntos e às vezes ignorar o agrupamento. Realmente poderia ter sido feito melhor.
  2. O esquema E o host devem ser especificados para que as regras de caminho correspondam (ao contrário do guia de API do Google, atualmente).
  3. Pelo menos o ES File Explorer gera intents com um tipo MIME de "", que é filtrado de forma muito diferente para nulo, é impossível de corresponder explicitamente e só pode ser correspondido pelo filtro de risco "* / *".
  4. O filtro "* / *" NÃO corresponderá a Intents com um tipo MIME nulo - isso requer um filtro separado para este caso específico sem nenhum tipo MIME.
  5. O esquema de "conteúdo" só pode ser correspondido pelo tipo MIME, porque o nome do arquivo original não está disponível na intenção (pelo menos com o Gmail).
  6. O agrupamento de atributos em elementos de "dados" separados é (quase) irrelevante para a interpretação, com a exceção específica de host e porta - que são pareados. Todo o resto não tem associação específica dentro de um elemento de "dados" ou entre elementos de "dados".

Com tudo isso em mente, aqui está um exemplo com comentários:

<!--
     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
fonte
Ótimo que você enfrente as muitas necessidades evidenciadas de \\ .. repetidamente e outras peculiaridades. O Google deveria ter corrigido isso em 4.2, que diabos. Infelizmente, ainda tenho casos que seu exemplo parece não resolver. Existe algum problema com extensões de 6 cha como ".gblorb" que meu código funciona bem com 3 letras ou menos?
RoundSparrow hilltx
Melhor resposta a esta pergunta e perguntas semelhantes na minha opinião! Infelizmente, enquanto não for possível combinar as intents de conteúdo por extensão de arquivo (como você apontou em 5.), não é possível filtrar com segurança TODAS as intents corretas sem também corresponder as erradas. Isso se aplica ao caso em que você não pode usar um tipo MIME personalizado. Portanto, enquanto o Android não fornecer uma solução para isso, ele será um seletor de arquivos dentro do aplicativo para mim ... Não quero confundir o usuário com comportamento inconsistente.
Benjamin Bisinger
1
Muito obrigado .. Você acabou de fazer meu dia .. No meu caso eu tive que mudar o MimeType <data android:mimeType="*/*" /> em todas as três opções e funcionou perfeitamente para todos os aplicativos, incluindo Google Drive e Gmail.
Rishabh Wadhwa
1
Eu gostaria de agradecer muito a você, @David Sainty. Você pôs fim à minha agonia de 24 horas tentando descobrir como lidar com isso. Tentei stackoverflow.com/q/18577860/6110285 , stackoverflow.com/a/8599921/6110285 e muitos outros semelhantes. Este é o único que funcionou.
pittix
24

Devo admitir que a simples tarefa de abrir anexos de e-mails e arquivos do sistema de arquivos no Android foi uma das experiências mais enlouquecedoras de todos os tempos. É fácil lidar com muitos ou poucos arquivos. Mas acertar é difícil. A maioria das soluções postadas no stackoverflow não funcionou corretamente para mim.

Meus requisitos eram:

  • fazer meu aplicativo lidar com anexos compartilhados por meu aplicativo
  • fazer meu aplicativo lidar com arquivos no armazenamento de arquivos que foram gerados por meu aplicativo e têm uma extensão específica

Provavelmente, a melhor maneira de realizar esta tarefa é especificar um tipo de MIME personalizado para seus anexos. E provavelmente você também escolherá uma extensão de arquivo personalizada. Então, digamos que nosso aplicativo se chama "Cool App" e geramos anexos de arquivo que têm ".cool" no final.

Este é o mais próximo que cheguei do meu objetivo e funciona ... satisfatório.

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

  • O pathPatternparece ser mais ou menos ignorado para anexos (ao usar android:scheme="content"). Se alguém fizer com que o pathPattern responda apenas a determinados padrões, ficaria entusiasmado em ver como.
  • O aplicativo do Gmail se recusou a listar meu aplicativo no seletor se eu adicionasse o android:host="*"atributo.
  • Provavelmente ainda funcionará se esses intent-filterblocos forem mesclados, mas eu não verifiquei isso.
  • Para lidar com solicitações de um navegador ao baixar um arquivo, o android:scheme="http"pode ser usado. Observe que certos navegadores podem bagunçar o processo, android:mimeTypeentão experimente android:mimeType="*/*"e verifique no depurador o que realmente é passado e, em seguida, aperte a filtragem para não acabar sendo aquele aplicativo irritante que lida com tudo .
  • Certos exploradores de arquivos bagunçarão os tipos MIME de seus arquivos também. O item acima intent-filterfoi testado com o aplicativo "Meus Arquivos" da Samsung em um Galaxy S3. O FX Explorer ainda se recusa a abrir o arquivo corretamente e também notei que o ícone do aplicativo não é usado para os arquivos. Novamente, se alguém fizer isso funcionar, comente abaixo.

Espero que você ache isso útil e que não precise perder dias examinando todas as combinações possíveis. Há espaço para melhorias, portanto, comentários são bem-vindos.

omahena
fonte
Esta é uma solução de trabalho para mim. Registrar um <intent-filter> separado para Content-Scheme e File-Scheme resolveu o problema! Obrigado!
Mehlyfication
Obrigado! Funcionou para mim. Tanto o aplicativo Gmail quanto o aplicativo Samsung My Files no Galaxy S6 conseguiram abrir arquivos com meu aplicativo usando sua solução!
Haris
Qual é exatamente o "nome do aplicativo?" (No meu caso, o nome do aplicativo legível por humanos contém espaços.)
William Jockusch
@WilliamJockusch parece que @DavidSainty está simplesmente armazenando o nome do aplicativo no arquivo de recurso de string. Os espaços devem estar bem. A string usada para o android:labelfiltro de intent é a string que o usuário verá no menu do seletor. Por padrão, o nome do aplicativo é usado.
omahena
O que devo usar para o aplicativo "Google Drive"?
desenvolvedor Android de
9

A resposta de Brian acima me levou a 90% do caminho até lá. Para finalizar, para o tipo mime usei

android:mimeType="*/*"

Suspeito que os pôsteres anteriores tentaram postar o mesmo detalhe, mas sem citar a estrela barra estrela como código, stackoverflow mostra isso apenas como uma barra.

Dawson
fonte
2
Com isso, você vai lidar com TODOS os tipos de arquivo, e isso é realmente irritante (bem, exceto se seu aplicativo realmente lidar com tudo) ...
Tim Autin
Isto é mau. Não faça isso dentro de seus aplicativos.
Marte
8

Em vez de android:pathtentar android:mimeType, com um valor do tipo MIME desse conteúdo específico. Além disso, android:pathnão aceita curingas - use android:pathPatternpara isso.

CommonsWare
fonte
"O tipo de arquivo não está incluído nos tipos MIME"? Ainda deve haver um tipo MIME para o tipo de conteúdo que você está baixando, mesmo que não use a mesma palavra.
Eric Mill de
Há um tipo MIME para o tipo de conteúdo, mas o arquivo é produzido por um aplicativo de terceiros que coloca uma extensão diferente nele, então não acho que será reconhecido como esse tipo MIME.
Curyous
7

Venho tentando fazer isso funcionar há muito tempo, tentei basicamente todas as soluções sugeridas e ainda não consigo fazer o Android reconhecer extensões de arquivo específicas. Eu tenho um filtro de intenção com um "*/*"tipo MIME que é a única coisa que parece funcionar e os navegadores de arquivos agora listam meu aplicativo como uma opção para abrir arquivos, no entanto, meu aplicativo agora é mostrado como uma opção para abrir QUALQUER TIPO de arquivo, embora Especifiquei extensões de arquivo específicas usando a tag pathPattern. Isso vai tão longe que, mesmo quando tento visualizar / editar um contato na minha lista de contatos, o Android me pergunta se eu quero usar meu aplicativo para visualizar o contato, e essa é apenas uma das muitas situações em que isso ocorre, MUITO MUITO irritante.

Acabei encontrando esta postagem do Google Groups com uma pergunta semelhante à qual um engenheiro de estrutura Android real respondeu. Ela explica que o Android simplesmente não sabe nada sobre extensões de arquivo, apenas tipos MIME ( https://groups.google.com/forum/#!topic/android-developers/a7qsSl3vQq0 ).

Portanto, pelo que vi, experimentei e li, o Android simplesmente não consegue distinguir entre extensões de arquivo e a tag pathPattern é basicamente uma perda gigantesca de tempo e energia. Se você tiver a sorte de precisar apenas de arquivos de um certo tipo MIME (por exemplo, texto, vídeo ou áudio), você pode usar um filtro de intenção com um tipo MIME. Se você precisa de uma extensão de arquivo específica ou um tipo MIME não conhecido pelo Android, então você está sem sorte.

Se eu estiver errado sobre qualquer coisa, por favor me diga, até agora eu li todos os posts e tentei todas as soluções propostas que pude encontrar, mas nenhuma funcionou.

Eu poderia escrever mais uma ou duas páginas sobre como esse tipo de coisa parece comum no Android e como a experiência do desenvolvedor é complicada, mas vou poupar meus discursos furiosos;). Espero ter salvado alguém de alguns problemas.

PeeGee85
fonte
1
Votei em você porque sua resposta fornece um link útil e o downvoter não deixou um comentário. Desculpe, SO posso ser hostil assim às vezes, mas não desista disso.
John Hatton,
3

A resposta de Brian é muito próxima, mas aqui está uma maneira limpa e sem erros de invocar seu aplicativo ao tentar abrir um arquivo com sua própria extensão personalizada (sem necessidade de esquema ou 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
fonte
2
A documentação do Android afirma que o atributo pathPattern só é significativo se um esquema e host forem especificados, e eu verifiquei isso: developer.android.com/guide/topics/manifest/data-element.html
Brian Pellin
4
-1; isso vai corresponder a qualquer arquivo; O comentário de Brian está correto e com a pequena modificação de mimeType = " / " seu exemplo original é perfeito.
Nick
Este post é de muito tempo atrás, mas sem "/" não instala. Você precisa de "* / *", que corresponderá a qualquer tipo de arquivo (não tenho certeza, se você quis dizer isso). Portanto, seu programa pode ser solicitado a abrir vídeos ou mp3s. Eu não encontrei uma solução para isso ainda.
Rene
Você deve usar uma <data>tag com quatro atributos. Sua solução pode funcionar com Android 2 - mas as regras se tornaram mais rígidas: stackoverflow.com/questions/20650378/…
Martin
O que há com o estranho pathPattern ? E hoste schemesão necessários!
IgorGanapolsky
3

No Android 4, as regras tornaram-se mais rígidas do que costumavam ser. Usar:

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

Eu tenho lutado um pouco com isso para uma extensão de arquivo personalizada, eu mesmo. Depois de muita pesquisa, encontrei esta página da web onde o autor da postagem descobriu que a classe patternMatcher do Android (que é usada para a correspondência pathPattern em Intent-Filters) tem um comportamento inesperado quando seu caminho contém o primeiro caractere de seu padrão de correspondência em outro lugar no caminho (como se você estivesse tentando corresponder a "* .xyz", a classe patternMatcher para se houver um "x" no início do seu caminho). Aqui está o que ele encontrou para uma solução alternativa e funcionou para mim, embora seja um pouco um hack:

PatternMatcher é usado para pathPattern em IntentFilter Mas o algoritmo de PatternMatcher é muito estranho para mim. Aqui está o algoritmo do Android PatternMatcher.

Se houver 'próximo caractere' do padrão '. *' No meio da string, o PatternMatcher interromperá o loop nesse ponto. (Consulte PatternMatcher.java da estrutura Android.)

Ex. string: "este é um anexo meu" padrão: ". att. ". Android PatternMatcher inserir loop para corresponder '. 'padrão até encontrar o próximo caractere do padrão (neste exemplo,' a ') Então,'. 'loop de correspondência para no índice 8 -' a 'entre' é 'e' meu '. Portanto, o resultado dessa correspondência retorna 'falso'.

Muito estranho, não é? Para contornar isso - realmente reduzir a possibilidade - o desenvolvedor deve usar pathPattern estúpido e irritante.

Ex. Objetivo: caminho de uri correspondente que inclui 'mensagem'.

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

Isso é especialmente emitido ao corresponder à extensão de arquivo customizada.

benjamin davis
fonte
Para todos os interessados, um problema foi registrado em code.google.com
benjamin davis
3

Nenhuma das opções acima funciona corretamente, para as ações VIEW ou SEND, se o sufixo não estiver registrado com um tipo MIME no banco de dados MIME system = wide do Android. As únicas configurações que descobri que disparam para o sufixo especificado incluem android:mimeType="*/*", mas a ação dispara para TODOS os arquivos. Claramente NÃO é o que você quer!

Não consigo encontrar nenhuma solução adequada sem adicionar o mime e o sufixo ao banco de dados mime do Android; até agora, não encontrei uma maneira de fazer isso. Se alguém souber, um ponteiro seria ótimo.

Glenn Widener
fonte
2

Quando um Intent atende a intent-filter, estes são os intent-filterrequisitos: (imagine uma lista de verificação).

  • Qualquer correspondência <action>
  • Qualquer correspondência <category>
  • Qualquer correspondência <data mimeType>(solução fácil: " / ")
  • Opcionalmente:

    • Qualquer correspondência <data scheme>(fácil correção: <data android:scheme="file" /> <data android:scheme="content" />)

    • Qualquer correspondência <data host>(solução fácil: "*")

    • Qualquer correspondência <data pathPattern/etc.>(por exemplo .*\\.0cc)

A definição de vários <data $type="">elementos marca a caixa $ type se algum <data $type=>corresponder a Intent.

A omissão de mimeType quebra o seu intent-filter, embora seja aparentemente redundante. A omissão <data scheme/host/pathPattern>faz com que seu filtro corresponda a tudo.

https://f-droid.org/en/packages/de.k3b.android.intentintercept/ é um aplicativo projetado para receber todos os intents e permite que você inspecione o intent. Aprendi que extensões de arquivo não reconhecidas abertas por meio do Simple File Manager são entregues com o tipo MIME application/octet-stream.

https://stackoverflow.com/a/4621284/2683842 relata que <data pathPattern=> .*xyzaborta no primeiro xque vê e falhará imediatamente se não for seguido por yz. Portanto /sdcard/.hidden/foo.0cc, não vai passar, a .*\\.0ccmenos que você tente .*\\..*\\.0cc.

  • Não verifiquei se esta solução alternativa é necessária.

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

Se você deseja que os arquivos sejam abertos diretamente do Gmail, caixa de depósito ou qualquer uma das ferramentas de criação de arquivos Android, use o seguinte código (delete 'android: host = "*"' que tornou o arquivo inacessível 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>

O filtro de dados deve ser escrito em uma instrução conforme Android versão 4.x

AndreasReiff
fonte
Tenho tentado de tudo para fazer o download e abrir do navegador Android funcionando corretamente. Sua solução funciona bem para o navegador nativo do Android e o Android Chrome, no entanto, o Android Firefox ainda parece abrir meu arquivo em uma janela de texto. É um tipo de mime personalizado e uma extensão personalizada. Anteriormente apenas com a extensão, ele só funcionava no firefox. Agora ele funciona em qualquer lugar, exceto no firefox (incluindo gmail). Ainda estou testando, mas só queria sinalizar o fato de que há um novo conjunto de problemas entre navegadores aqui.
Damon Smith de
1

Usando o filtro abaixo para abrir no navegador, gmail e navegador de arquivos (testado). NOTA: Por favor, não mescle dois filtros, isso fará com que o navegador ignore seu aplicativo (Testado).

        <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
fonte
Você testou esta resposta com anexos do Gmail?
IgorGanapolsky
1

Atualização 2020

O Android mudou para URIs de conteúdo e tipos MIME para filtros de intenção.

O problema

Um URI de conteúdo não precisa necessariamente conter a extensão ou nome do arquivo e será diferente entre os diferentes aplicativos que fornecem o conteúdo / arquivo.

Aqui estão alguns exemplos de URIs de conteúdo de diferentes aplicativos de e-mail para o mesmo anexo de e-mail:

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

Aplicativo de e-mail Samsung -> content://com.samsung.android.email.attachmentprovider/1/1/RAW

Como podemos ver, eles são todos diferentes e não há garantia de que contenham qualquer coisa relacionada ao seu arquivo real. Assim, você não pode usar oandroid:pathPattern que a maioria sugeriu.

Uma solução alternativa para anexos de e-mail

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

Por meio de testes, encontrei os tipos MIME que o Gmail, Outlook e Samsung Email usaram e os adicionei ao meu filtro de intenção.

Advertências / pegadinhas

  • Descobri que, com a solução acima, se abrisse qualquer arquivo do tipo binário, meu aplicativo seria iniciado automaticamente. Eu lidei com isso em minha atividade exibindo um estado de falha se não pudéssemos analisar o arquivo. Achei que este era um evento muito raro, então seria aceitável.

  • Não consegui encontrar nenhuma maneira de iniciar meu aplicativo por meio do navegador de arquivos sem adicionar <data android:mimeType="*/*"/>ao meu filtro de intenção. Eu não poderia usar isso porque ele iniciaria meu aplicativo sempre que o usuário clicasse em qualquer arquivo em seu telefone (não apenas aqueles com extensão de arquivo personalizado). Eu não recomendaria adicionar isso ao seu filtro de intenção.

Pensamentos finais

  • Atualmente, não existe uma solução elegante para associar seu aplicativo a um tipo de extensão específico no Android. Isso foi o melhor que pude fazer na minha situação.
alexander antaya
fonte