views:

2548

answers:

2

On the subject of associating your iPhone app with file types.

In this informative question I learned that apps could be associated with custom URL protocols.

That was almost one year ago and since then Apple introduced 'Document Support' which goes a step further and allows apps to associate with file types. There is a lot of talk in the documentation about how to set up your app to launch other appropriate apps when it encounters an unknown file type. This means the association doesn't work out of the box for any app, like the URL protocol registering did.

This leads me to the question: have system apps like Safari or Mail implemented this system for choosing associated applications, or will they do nothing, as before?

+25  A: 

File type handling is new with iPhone OS 3.2, and is different than the already-existing custom URL schemes. You can register your application to handle particular document types, and any application that uses a document controller can hand off processing of these documents to your own application.

For example, my application Molecules (for which the source code is available) handles the .pdb and .pdb.gz file types, if received via email or in another supported application.

To register support, you will need to have something like the following in your 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>

Two images are provided that will be used as icons for the supported types in Mail and other applications capable of showing documents. The LSItemContentTypes key lets you provide an array of Uniform Type Identifiers (UTIs) that your application can open. For a list of system-defined UTIs, see Apple's Uniform Type Identifiers Reference. Even more detail on UTIs can be found in Apple's Uniform Type Identifiers Overview. Those guides reside in the Mac developer center, because this capability has been ported across from the Mac.

One of the UTIs used in the above example was system-defined, but the other was an application-specific UTI. The application-specific UTI will need to be exported so that other applications on the system can be made aware of it. To do this, you would add a section to your Info.plist like the following:

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

This particular example exports the com.sunsetlakesoftware.molecules.pdb UTI with the .pdb file extension, corresponding to the MIME type chemical/x-pdb.

With this in place, your application will be able to handle documents attached to emails or from other applications on the system. In Mail, you can tap-and-hold to bring up a list of applications that can open a particular attachment.

When the attachment is opened, your application will be started and you will need to handle the processing of this file in your -application:didFinishLaunchingWithOptions: application delegate method. It appears that files loaded in this manner from Mail are copied into your application's Documents directory under a subdirectory corresponding to what email box they arrived in. You can get the URL for this file within the application delegate method using code like the following:

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

Note that this is the same approach we used for handling custom URL schemes. You can separate the file URLs from others by using code like the following:

if ([url isFileURL])
{
    // Handle file being passed in
}
else
{
    // Handle custom URL scheme
}
Brad Larson
Awesome. Thanks for the tutorial, Brad.
Barry Wark
I'm not able to try this on the iPad/iPhone simulator. I have downloaded the molecules application and Safari cannot open .pdb or even .gz files as the Info.plist claims. It simply says, "Safari cannot download the file"
HyLian
@HyLian - I don't believe that Safari supports file extensions in the same way that other applications on the system do. The above applies for Mail and other applications that use UIDocumentInteractionController. For Safari, I've created a custom URL scheme (molecules://) that will cause the appropriately linked file to be opened in the application.
Brad Larson
@Brad - Thanks for your answer. But yet it works. In you app (Molecules) it is possible to download a .pdb file directly from Safari Browser. Not every .pdb file works, and I think the problem is in the response from the server which sends the .pdb file. For example in, if you try to open this (http://www.uwsp.edu/chemistry/pdbs/biochemistry/amino_acids/glu.pdb) in Safari, it will launch Molecules to handle the file. The problem is registering types is a very hard task as you don't have any feedback from the system about what's happening under the hood.
HyLian
@HyLian - Yes, there is a bug in the application involving how it downloads PDBs located on certain servers that I haven't quite tracked down yet. That is independent of the file handling and custom URL schemes, though.
Brad Larson
@Brad - Excellent answer - thank you. I followed your instruction as I'm trying to register an application that will open png and jpeg files, alas I couldn't get mail to show an open in... option for these attachment in mail. Is it possible to take the same approach and have mail open images in my app?
Ron Srebro
@Brad Larson--> i will get the url of pdf file.I want to save the pdf file to documents directory.How can i do that?
Warrior
@Warrior - All you need to do is move the file at the URL that has been passed in to your application's Documents directory. I believe that it is automatically copied to a subdirectory in your Documents directory anyway, so you just need to move it to the root of the Documents directory and delete the old temporary subdirectory. I do this in my Molecules application, so you can look at the code I use for this.
Brad Larson
@Brad Larson-->Your code was very useful.Thanks a lot.
Warrior
I want to do the same for *.mndl files (customized *.plist file for my app) but it is not working... I added the icon files, changed pds to mndl and also changed molecules to my app name so now my info.plist has 2rows more CFBundleDocumentTypes and UTExportedTypeDeclarations but It didn't work. I tried sending my 1 file.mndl and mail didn't recognized and cannot be opened. ;( Is there any way what I am doing wrong? Where do I find the official guide or so?
nacho4d
@nacho4d - Did you change the UTI in both places? Did you remove the org.gnu.gnu-zip-archive UTI? Did you change the UTTypeConformsTo to match that for a property list? Did you change the extension and MIME type? All of that needs to be customized for your particular case, and all references to the items I have in there need to be removed. The best reference for this are the two articles I link to above.
Brad Larson
@Brad Thanks, I actually could do it after reading "iPad development for iPhone developers" and my answer plist is here: http://stackoverflow.com/questions/3827558/creating-my-own-file-extension-based-on-plist
nacho4d
I just realized that when I attach my .mndl file to a mail using MFMailComposeViewController the attachment does not show the icon it's supposed to inside this MFMailComposerViewController, but it shows correctly in Mail.app. Is this because I didn't wrote the mime type in UTTypeTagSpecification array? If yes, what should I write? (.mndl files are a particular case of .plist I have created.) I would appreciate your help. Thanks
nacho4d
A: 

Sorry, could not figure out how to post a comment, so will post as an answer.

I did everything, and Mail now shows my application icon and name on the attachment, but when I click it and select "Open in MyApp" in the menu, nothing happens.

But this message is added to the Console:

Mon Oct 18 01:52:42 unknown sandboxd[3792] : MobileMail(2260) deny file-read-metadata /private/var/mobile/Applications/E20943F8-9FC6-487F-B5B5-B4C9AB37520D/MyApp.app

What do I do wrong?

P.S. testing on never jailbroken iPhone 3G running 4.1