Como associo tipos de arquivo a um aplicativo do iPhone?

318

Sobre o assunto de associar seu aplicativo do iPhone a tipos de arquivo.

Em esta questão informativa eu aprendi que os aplicativos podem ser associados com protocolos URL personalizado.

Isso foi há quase um ano e, desde então, a Apple lançou o 'Document Support', que vai um passo além e permite que os aplicativos se associem aos tipos de arquivos. Há muita conversa na documentação sobre como configurar seu aplicativo para iniciar outros aplicativos apropriados quando encontrar um tipo de arquivo desconhecido. Isso significa que a associação não funciona imediatamente para qualquer aplicativo, como o protocolo de URL registrado.

Isso me leva à pergunta: os aplicativos do sistema, como o Safari ou o Mail, implementaram esse sistema para escolher os aplicativos associados ou eles não farão nada, como antes?

Mihai Damian
fonte

Respostas:

408

O tratamento do tipo de arquivo é novo no iPhone OS 3.2 e é diferente dos esquemas de URL personalizados já existentes. Você pode registrar seu aplicativo para lidar com tipos de documentos específicos, e qualquer aplicativo que use um controlador de documento pode transferir o processamento desses documentos para seu próprio aplicativo.

Por exemplo, meu aplicativo Molecules (para o qual o código fonte está disponível) lida com os tipos de arquivo .pdb e .pdb.gz, se recebidos por email ou em outro aplicativo suportado.

Para registrar o suporte, você precisará ter algo como o seguinte no seu Info.plist:

<key>CFBundleDocumentTypes</key>
<array>
    <dict>
        <key>CFBundleTypeIconFiles</key>
        <array>
            <string>Document-molecules-320.png</string>
            <string>Document-molecules-64.png</string>
        </array>
        <key>CFBundleTypeName</key>
        <string>Molecules Structure File</string>
        <key>CFBundleTypeRole</key>
        <string>Viewer</string>
        <key>LSHandlerRank</key>
        <string>Owner</string>
        <key>LSItemContentTypes</key>
        <array>
            <string>com.sunsetlakesoftware.molecules.pdb</string>
            <string>org.gnu.gnu-zip-archive</string>
        </array>
    </dict>
</array>

São fornecidas duas imagens que serão usadas como ícones para os tipos suportados no Mail e outros aplicativos capazes de mostrar documentos. A LSItemContentTypeschave permite fornecer uma variedade de UTIs (Uniform Type Identifiers) que seu aplicativo pode abrir. Para obter uma lista de UTIs definidas pelo sistema, consulte Referência de identificadores de tipo uniforme da Apple . Ainda mais detalhes sobre as UTIs podem ser encontrados na Visão geral uniforme dos identificadores de tipo da Apple . Esses guias residem no centro de desenvolvimento do Mac, porque esse recurso foi transportado para o Mac.

Uma das UTIs usadas no exemplo acima foi definida pelo sistema, mas a outra era uma UTI específica do aplicativo. A UTI específica do aplicativo precisará ser exportada para que outros aplicativos no sistema possam ser informados. Para fazer isso, você adicionaria uma seção ao seu Info.plist da seguinte maneira:

<key>UTExportedTypeDeclarations</key>
<array>
    <dict>
        <key>UTTypeConformsTo</key>
        <array>
            <string>public.plain-text</string>
            <string>public.text</string>
        </array>
        <key>UTTypeDescription</key>
        <string>Molecules Structure File</string>
        <key>UTTypeIdentifier</key>
        <string>com.sunsetlakesoftware.molecules.pdb</string>
        <key>UTTypeTagSpecification</key>
        <dict>
            <key>public.filename-extension</key>
            <string>pdb</string>
            <key>public.mime-type</key>
            <string>chemical/x-pdb</string>
        </dict>
    </dict>
</array>

Este exemplo específico exporta a com.sunsetlakesoftware.molecules.pdbUTI com a extensão de arquivo .pdb, correspondente ao tipo MIME chemical/x-pdb.

Com isso, seu aplicativo poderá lidar com documentos anexados a emails ou de outros aplicativos no sistema. No Mail, você pode tocar e manter pressionado para exibir uma lista de aplicativos que podem abrir um anexo específico.

Quando o anexo é aberto, seu aplicativo será iniciado e você precisará lidar com o processamento desse arquivo no -application:didFinishLaunchingWithOptions:método de delegação do aplicativo. Parece que os arquivos carregados dessa maneira pelo Mail são copiados para o diretório Documents do aplicativo em um subdiretório correspondente à caixa de e-mail em que chegaram. Você pode obter o URL desse arquivo no método delegate do aplicativo usando um código como o seguinte:

NSURL *url = (NSURL *)[launchOptions valueForKey:UIApplicationLaunchOptionsURLKey];

Observe que esta é a mesma abordagem que usamos para lidar com esquemas de URL personalizados. Você pode separar os URLs dos arquivos dos outros usando um código como o seguinte:

if ([url isFileURL])
{
    // Handle file being passed in
}
else
{
    // Handle custom URL scheme
}
Brad Larson
fonte
9
Deve-se observar que -application:didFinishLaunchingWithOptions:o delegado do aplicativo é chamado apenas se o aplicativo não tiver um segundo plano quando for aberto para manipular um arquivo.
memmons
3
Evitando o QuickLook: raywenderlich.com/1980/…
TheLearner
4
Devemos usar - (BOOL)application:(UIApplication *)application handleOpenURL:(NSURL *)urltambém no iOS 4+
Dmitry
1
E a chave 'CFBundleTypeExtensions'? Seu snippet não parece defini-lo. Não é necessário?
Bram
3
Eu tentei toda a metodologia fornecida aqui e em outros lugares também, mas ainda estou lutando para obter arquivos PNG abertos. Estou trabalhando com o iOS 7. Em alguns lugares, eles estão dizendo que esse problema começa com o ios 6. É verdade? Não podemos abrir arquivos png na caixa de diálogo "Abrir em" com o ios 7?
precisa
24

Além da excelente resposta de Brad, descobri que (pelo menos no iOS 4.2.1) ao abrir arquivos personalizados do aplicativo Mail, seu aplicativo não é acionado ou notificado se o anexo já tiver sido aberto anteriormente. O pop-up "abrir com ..." aparece, mas simplesmente não faz nada.

Isso parece ser corrigido movendo o arquivo do diretório Caixa de Entrada. Uma abordagem segura parece ser a de (re) mover o arquivo quando ele é aberto (no -(BOOL)application:openURL:sourceApplication:annotation:), além de passar pelo diretório Documents / Inbox, removendo todos os itens, por exemplo, no applicationDidBecomeActive:. Essa última opção pode ser necessária para obter o aplicativo novamente em um estado limpo, caso uma importação anterior cause uma falha ou seja interrompida.

mvds
fonte
6
Eu não vejo esse comportamento. Se meu aplicativo estiver em segundo plano, -(BOOL)application:openURL:sourceApplication:annotation:sempre será chamado, mesmo para anexos que já foram abertos. Cada vez que o anexo é aberto, um número é sufixado no nome do arquivo e é incrementado para ser único - test.text, test-1.txt, test-2.txt, etc.
memmons
Meu diretório Caixa de entrada está vazio, mas ainda tenho o botão "Abrir em" que não responde no Safari de que você fala. Anos atrás, meu aplicativo estava funcionando bem, mas de repente parou de funcionar. Eu suspeito que a Apple mudou alguma coisa no Safari.
Bram
18

AVISO GRANDE: certifique-se de cem por cento de certeza de que seu ramal ainda não está vinculado a algum tipo de mímica.

Usamos a extensão '.icz' para nossos arquivos personalizados para, basicamente, sempre, e o Safari nunca permite que você os abra dizendo "O Safari não pode abrir este arquivo". não importa o que fizemos ou tentamos com o material da UT acima.

Eventualmente, percebi que existem algumas funções UT * C que você pode usar para explorar várias coisas, e enquanto .icz fornece a resposta certa (nosso aplicativo):

No aplicativo foi carregado na parte superior, basta fazer isso ...

NSString * UTI = (NSString *)UTTypeCreatePreferredIdentifierForTag(kUTTagClassFilenameExtension, 
                                                                   (CFStringRef)@"icz", 
                                                                   NULL);
CFURLRef ur =UTTypeCopyDeclaringBundleURL(UTI);

e interrompa essa linha e veja o que são UTI e ur - no nosso caso, era o nosso identificador como queríamos) e o URL do pacote (ur) apontava para a pasta do aplicativo.

Mas o tipo MIME que o Dropbox nos fornece de volta para o nosso link, que você pode verificar fazendo, por exemplo

$ curl -D headers THEURLGOESHERE > /dev/null
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100 27393  100 27393    0     0  24983      0  0:00:01  0:00:01 --:--:-- 28926
$ cat headers
HTTP/1.1 200 OK
accept-ranges: bytes
cache-control: max-age=0
content-disposition: attachment; filename="123.icz"
Content-Type: text/calendar
Date: Fri, 24 May 2013 17:41:28 GMT
etag: 872926d
pragma: public
Server: nginx
x-dropbox-request-id: 13bd327248d90fde
X-RequestId: bf9adc56934eff0bfb68a01d526eba1f
x-server-response-time: 379
Content-Length: 27393
Connection: keep-alive

O tipo de conteúdo é o que queremos. O Dropbox afirma que essa é uma entrada de texto / calendário. Ótimo. Mas, no meu caso, JÁ TENTE COLOCAR texto / calendário nos tipos MIME do meu aplicativo e ele ainda não funciona. Em vez disso, quando tento obter a UTI e agrupar o URL para o tipo de mimet de texto / calendário,

NSString * UTI = (NSString *)UTTypeCreatePreferredIdentifierForTag(kUTTagClassMIMEType,
                                                                   (CFStringRef)@"text/calendar", 
                                                                   NULL);

CFURLRef ur =UTTypeCopyDeclaringBundleURL(UTI);

Vejo "com.apple.ical.ics" como a UTI e "... / MobileCoreTypes.bundle /" como o URL do pacote. Não é nosso aplicativo, mas a Apple. Então, tento colocar com.apple.ical.ics nos LSItemContentTypes ao lado dos meus e em UTConformsTo na exportação, mas não é possível.

Então, basicamente, se a Apple achar que deseja, em algum momento, lidar com algum tipo de arquivo (que pode ser criado 10 anos após o aplicativo estar ativo, lembre-se), você precisará alterar a extensão, pois eles simplesmente não permitirão que você lide o tipo de arquivo.

Kalle
fonte
Obrigado pelo aviso útil!
RockSolid #
0

Para lidar com qualquer tipo de arquivo para meu próprio APP, eu uso essa configuração para CFBundleDocumentTypes:

    <key>CFBundleDocumentTypes</key>
    <array>
        <dict>
            <key>CFBundleTypeName</key>
            <string>IPA</string>
            <key>LSItemContentTypes</key>
            <array>
                <string>public.item</string>
                <string>public.content</string>
                <string>public.data</string>
                <string>public.database</string>
                <string>public.composite-content</string>
                <string>public.contact</string>
                <string>public.archive</string>
                <string>public.url-name</string>
                <string>public.text</string>
                <string>public.plain-text</string>
                <string>public.source-code</string>
                <string>public.executable</string>
                <string>public.script</string>
                <string>public.shell-script</string>
                <string>public.xml</string>
                <string>public.symlink</string>
                <string>org.gnu.gnu-zip-archve</string>
                <string>org.gnu.gnu-tar-archive</string>
                <string>public.image</string>
                <string>public.movie</string>
                <string>public.audiovisual-​content</string>
                <string>public.audio</string>
                <string>public.directory</string>
                <string>public.folder</string>
                <string>com.apple.bundle</string>
                <string>com.apple.package</string>
                <string>com.apple.plugin</string>
                <string>com.apple.application-​bundle</string>
                <string>com.pkware.zip-archive</string>
                <string>public.filename-extension</string>
                <string>public.mime-type</string>
                <string>com.apple.ostype</string>
                <string>com.apple.nspboard-typ</string>
                <string>com.adobe.pdf</string>
                <string>com.adobe.postscript</string>
                <string>com.adobe.encapsulated-​postscript</string>
                <string>com.adobe.photoshop-​image</string>
                <string>com.adobe.illustrator.ai-​image</string>
                <string>com.compuserve.gif</string>
                <string>com.microsoft.word.doc</string>
                <string>com.microsoft.excel.xls</string>
                <string>com.microsoft.powerpoint.​ppt</string>
                <string>com.microsoft.waveform-​audio</string>
                <string>com.microsoft.advanced-​systems-format</string>
                <string>com.microsoft.advanced-​stream-redirector</string>
                <string>com.microsoft.windows-​media-wmv</string>
                <string>com.microsoft.windows-​media-wmp</string>
                <string>com.microsoft.windows-​media-wma</string>
                <string>com.apple.keynote.key</string>
                <string>com.apple.keynote.kth</string>
                <string>com.truevision.tga-image</string>
            </array>
            <key>CFBundleTypeIconFiles</key>
            <array>
                <string>Icon-76@2x</string>
            </array>
        </dict>
    </array>
SLdragon
fonte