iOS apps have several options for sharing data amongst themselves via Inter-Process Communication (IPC). App-to-app sharing of chemical data is described in detail.

Overview

Chemical datatypes

User interfaces

Receiving files

Opening files

Implementation

Receiving files

Registering as a handler

Responding to open request

Opening files

Summary

Overview


Apps such as the Mobile Molecular DataSheet, and apps which incorporate the same core technology, have a number of ways of sharing data, for example:

Data can be shared between apps using the system clipboard, and transmitted over the network through transport mediums such as email and webservices. iOS devices also provide a straightforward and well defined method for apps to send messages and data via URLs and filetype handlers. These techniques diverge into two categories:

  • Custom URL prefixes, e.g. someapp://something/somethingelse?somestuff=whatever
  • Custom file type handlers by file extension (e.g. *.txt) or by MIME type (e.g. text/plain).

Custom URL prefixes are useful for when two apps have established a specific protocol, while custom file type handlers are much more general, and are designed in a way that allows any app to register itself and participate. This article describes the latter: custom file type handlers for chemical data.

Chemical datatypes


The chemical information ecosystem of the Mobile Molecular DataSheet - and derived products and services - operates with the following kinds of files:

File type Extension MIME type Content
SketchEl Molecule .el chemical/x-sketchel Single molecule
XML DataSheet .ds chemical/x-datasheet Molecules, reactions and data
MDL MOLfile .mol chemical/x-mdl-molfile Single molecule
MDL SDfile .sdf chemical/x-mdl-sdfile Molecules and data
MDL RXNfile .rxn chemical/x-mdl-rxnfile Single reaction
MDL RDfile .rdf chemical/x-mdl-rdfile Multiple reactions and data
ChemDraw .cdx chemical/x-cdx Molecules and reactions

Any app may register itself to be able to handle any of these types as a receiver, and may at any point ask the operating system to open a file of a particular type, sending it to an app that is registered as being able to receive it.

User interfaces


When an app opens a file with a registered type, it is suspended by the operating system, and the receiving app is activated and brought into the foreground, and is instructed to do something with the file.

Receiving files


There are a number of situations when an app might receive a file for which it is registered as a handler. Two of the most common situations are when opening email attachments, and when browsing files that are not handled natively by the browser:

All of these situations are equivalent. When a receiver app is selected, it is immediately opened. If the receiver app is currently running, it will be brought into the foreground. If it is not running, it will be launched. The app will be informed that an incoming file is available. The app is then responsible for examining the file, and deciding what to do with it.

For example, the Mobile Molecular DataSheet, when receiving a molecular structure, adds the structure to the scratch sheet, and opens it for editing:

Opening files


Any app can, at any point, ask the operating system to launch a file in the app's private directory. When this request is issued, the file type is identified by its extension, and a list of matching handler apps is generated. Any app capable of receiving the file type is enumerated in a list:

If the user selects one of the listed apps, it will be launched, and the file will be passed along.

Implementation


This section assumes some familiarity - and interest - in iOS development using Objective-C.

Receiving files


Configuring an app so that it can receive files of certain types is done in two parts: adding the handler to the app description, and writing the code that performs the open action.

Registering as a handler


Notifying iOS that your app can process a certain file type requires the addition of two sections in the Info.plist file. The following examples are taken from the MolPrime source code.

Document types:

The document type definitions are internal constructs to which actual filetypes will later on be matched. The identifiers used are arbitrary. The above example is used to summarise all of the single-molecule file types. The two actual formats which fall under this umbrella are identified by the keywords com.mmi.mmds.molecule.sketchel and com.mmi.mmds.molecule.mdlmol, which are used to link up to the next section.

Exported types:

In this section, actual file types - identified by file extension or MIME type - are linked to the internal file identifiers. The first section maps SketchEl formatted molecules to the internal type com.mmi.mmds.molecule.sketchel. It connects to external identifiers by the two entries:

  • public.filename-extension = el
  • public.mime-type = chemical/x-sketchel

In practice, the file extension is the more commonly used identifier for a file, but MIME type can be important too, especially when the user is downloading data from a properly configured web server.

Adding these two sections to the Info.plist is sufficient to ensure that your app will always be considered when the operating system is asked for a list of files that are compatible with the advertised file types.

Responding to open request


When a user launches your app with a file, it will consult with the app delegate class, which implements the UIApplicationDelegate protocol. It is necessary to implement the following method:


- (BOOL)application:(UIApplication *)application openURL:(NSURL *)url
                                                 sourceApplication:(NSString *)source
                                                 annotation:(id)annotation

It is safe to assume that the app has already been launched when this message is issued, i.e. the main view controller will have already had a chance to configure itself, create the main window, etc. It is also possible that the app may be in the middle of doing something else, if it had been suspended.

The response method is tasked with the duty of analysing the content of the url parameter, which is a file that the app has permission to read. Unfortunately there is no further information about the type mapping of the file, so it is necessary for the code to derive this from the file extension and file contents.

An excerpt from the MolPrime source code follows:


- (BOOL)application:(UIApplication *)application openURL:(NSURL *)url
                                                 sourceApplication:(NSString *)source
                                                 annotation:(id)annotation
{
    MolPrimeViewController *main=[MolPrimeViewController main];

    // load the data from the file URL
    NSError *error=nil;
    NSString *content=[NSString stringWithContentsOfURL:url encoding:NSUTF8StringEncoding error:&error];
    if (!content && error)
    {
        [main showMessage:[NSString stringWithFormat:@"Unable to read attachment.\n%@",error.localizedDescription]];
        return NO;
    }

    // convert the data into a molecule object
    Molecule *mol=[[MoleculeReader readUnknownFromString:content] autorelease];
    if ([mol numAtoms]==0)
    {
        [main showMessage:@"Attachment was not able to be parsed. It must be a recognised molecule format."];
        return NO;
    }
	
    // respond to incoming molecule
    [main openMolecule:mol];
    return YES;
}

The above code first reads the provided URL into a string, which is appropriate because the two file types that it recognises (SketchEl and MDL MOL) are both encoded as ASCII text. The first potential point of failure is if the file fails to load for any reason.

Once the data is available, one of the cheminformatics methods is called (readUnknownFromString), which is capable of reading either of these two formats from a string, and returning an instantiated Molecule object. This functionality is a proprietary component of the MMDSLib library. In this case, it is not necessary to use the file extension to try to guess the file type, because the two supported types are relatively easy to disambiguate. For apps such as MMDS which handle a variety of cheminformatics formats, some of which are binary, the implementation of this method is more complex.

Opening files


Launching a file within an app is considerably simpler than registering an app to receive files. Somewhere within the app, some kind of "Open with..." option needs to be provided for a file or object.

The object needs to be written to a file in the app home directory, if does not already exist as a file. It is crucial that the file extension follow standard conventions, since this is the only identifier used to match compatible applications.

The following code is an excerpt from MolPrime which responds to a user request to use the current molecule to launch against any other app that advertises itself as being capable of handling the SketchEl molecule structure format:


    // fetch the current molecule
    Molecule *mol=[content getCurrent];
    if ([mol numAtoms]==0)
    {
        [self showMessage:@"The current molecule is blank.."];
        return;
    }
    
    // write the molecule to a file
    NSString *home=[NSSearchPathForDirectoriesInDomains(NSDocumentDirectory,NSUserDomainMask,YES) objectAtIndex:0];
    NSString *tmpFN=[NSString stringWithFormat:@"%@/tmp_openwith.el",home];
    [MoleculeWriter writeNativeToFile:tmpFN mol:mol];
    NSURL *url=[NSURL fileURLWithPath:tmpFN];
    
    // launch compatible apps
    UIDocumentInteractionController *doc=[[UIDocumentInteractionController interactionControllerWithURL:url] retain];
    if (![doc presentOpenInMenuFromRect:self.button.frame inView:self animated:YES])
    {
        [self showMessage:@"No apps are available."];
        return;
    }

Note that the intermediary process of creating a file leaves a stain on the app's home directory, which may need to be cleaned up later. For some apps, it is sufficient to simply leave it there, and overwrite it each time the feature is invoked.

The hard work is all done by the UIDocumentInteractionController class. Note that the user interface works quite differently on iPhone/iPod phone-sized devices vs. iPad tablets. The first parameter passed to the presentOpenInMenuFromRect method is a rectangle, which is used to position the popup menu that is used by the iPad to display the list of apps. This parameter is ignored when running on smaller devices.

Summary


Passing chemical data between arbitrary iOS apps is quite straightforward, and it can be done by matching file types, rather than compiling a predefined list of apps to communicate with. Document sharing on iOS devices has a number of limitations, but is nonetheless very powerful, and may well become more flexible as the iOS platform advances.

See Also


Format: DataSheet Aspects, Format: SketchEl Molecule, Format: XML DataSheet