Custom extension file not opening in iMessage
Asked Answered
S

3

21

In my app, I need to send some custom data files from one device to another, and I am trying to do this with Mail, iMessage/Message and Airdrop.

This works fine with Mail and Airdrop but with iMessage and it goes just fine, but on the receiving end, I am not able to open the files. It's just not allowing me to do anything with it.

Any ideas??

This is what my Document Type looks like:

<key>CFBundleDocumentTypes</key>
    <array>
        <dict>
            <key>CFBundleTypeIconFile</key>
            <string>abc.png</string>
            <key>CFBundleTypeName</key>
            <string>ABC Custom Data type</string>
            <key>CFBundleTypeRole</key>
            <string>Viewer</string>
            <key>Handler Rank</key>
            <string>Owner</string>
            <key>LSItemContentTypes</key>
            <array>
                <string>com.company.abc.wd</string>
            </array>
        </dict>
    </array>

This is how i am sending the data:

NSMutableDictionary * dict = [NSMutableDictionary dictionary];
[dict setObject:currentDataSet forKey:@"actualData"];
NSData * meetingData = [NSKeyedArchiver archivedDataWithRootObject:dict];

Meeting * dataItem = [[Meeting alloc]initWithData:meetingData
               type:@"com.abc.xyz.wd" subject:@"Meeting"
          previewImage:[UIImage imageNamed:@"appIcon.png"]];

UIActivityViewController * activityController =
  [[UIActivityViewController alloc]initWithActivityItems:@[dataItem]
                                   applicationActivities:nil];

activityController.excludedActivityTypes =
       @[UIActivityTypePostToTwitter, UIActivityTypePostToWeibo];

[self presentViewController:activityController animated:YES completion:nil];
Sami answered 3/4, 2014 at 2:52 Comment(3)
Not sure if you have to stick to the standard UTIs - developer.apple.com/library/ios/documentation/Miscellaneous/… - Do you have code examples of what you are trying to do when attaching the file to the Message, are you using addAttachmentData:typeIdentifier:filename:?Asphalt
Do you want to send only PNG files? if not you can use below code which sends/detects all kind of formats <key>CFBundleDocumentTypes</key> <array> <dict> <key>CFBundleTypeIconFiles</key> <array/> <key>CFBundleTypeName</key> <string>com.jungleDisk.file</string> <key>LSHandlerRank</key> <string>Owner</string> <key>LSItemContentTypes</key> <array> <string>public.data</string> </array> </dict> </array>Haemophilic
@Ashutosh, did you ever figure this out? I am running into the same issue and came across this thread.Carducci
I
9

This answer is correct in that the custom document can be opened from Messages if it conforms to public.text. The drawback to this solution is that the document is previewed as raw text, which might not be the desired result.

Documents conforming to public.data can be opened from the Messages app without being previewed as raw text by creating a Quick Look Preview Extension. There isn't much documentation about how to build a Quick Look Preview Extension, but it's pretty straightforward:

  1. In Xcode, choose, File > New > Target.

  2. Choose Quick Look Preview Extension, give your extension a name, and click Finish.

  3. In the info.plist for the newly created extension, add a new item under NSExtension > NSExtensionAttributes > QLSupportedContentTypes, and set the value for this item to your app's custom document type. For example:

    ...
    <key>NSExtension</key>
    <dict>
        <key>NSExtensionAttributes</key>
        <dict>
            <key>QLSupportedContentTypes</key>
            <array>
                <string>com.company.abc.wd</string>
            </array>
            <key>QLSupportsSearchableItems</key>
            <true/>
        </dict>
        <key>NSExtensionMainStoryboard</key>
        <string>MainInterface</string>
        <key>NSExtensionPointIdentifier</key>
        <string>com.apple.quicklook.preview</string>
    </dict>
    ...
    
  4. Use MainInterface.storyboard and PreviewViewController to define the layout of your custom Quick Look preview. More specifically, read data from the URL provided in the preparePreviewOfFile function and populate the ViewController accordingly. A brief example (in Swift 4):

    func preparePreviewOfFile(at url: URL, completionHandler handler: @escaping (Error?) -> Void) {
        do {
            let documentData = try Data(contentsOf: url)
    
            // Populate the ViewController with a preview of the document.
    
            handler(nil)
        } catch let error {
            handler(error)
        }
    }
    

Some pitfalls I ran into when creating my extension:

  • The exported UTI identifier had to be all lower case. When some of the characters were upper case, the Quick Look preview was never shown, even though I used the same capitalization in my Quick Look Preview Extension.

  • Quick Look Preview Extensions are not allowed to link against dynamic libraries. If a dynamic library is linked, the Quick Look preview will not load.

  • The Quick Look ViewController is not allowed to have any buttons. If it contains a button, the Quick Look preview will not load.

Additional resources:

Irreclaimable answered 6/8, 2018 at 0:26 Comment(2)
In iOS 14.7 I found that I could open my custom file format from the Files app but tapping one of those files in Messages did nothing. By adding a dirt simple Quick Look for my file type I was able to see that when tapping my file in Messages. From that preview I made I could then send-to my app as desired. In the Files app it seemed to have its own quick-look that just didn't work from Messages (until I made my own).Stinkwood
Can't for the life of me make this work. I am following your steps but nothing is happening. I am creating the new build target but I don't understand how to get it to build? For the moment I am just creating it, editing its info.plist, and then building and running my normal app target. Not sure how the 2 should communicate? My files work perfectly in Mail/Files/Airdrop.Talkington
B
4

I came across this post while searching for a similar solution. I was able to email custom files from my app and open it in email or use it with AirDrop. If I sent it via iMessage it even showed up with my custom icon, but when I tapped it in iMessage nothing happened.

Be aware that you need something like the following in your plist file (from How do I associate file types with an iPhone application?)

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

NOTE: I had something very similar for my app BUT in the UTTypeConformsTo I only had public.data since my files are zipped data files.

I found that by adding public.text as a second item in the array it would be actionable in iMessage. On a further note, if I added public.plain-text as a third item my file ended up with a Pages icon instead of my icon (so I removed it)

I hope this helps someone. It's taken me hours to get to the bottom of it.

Blip answered 30/12, 2015 at 20:35 Comment(1)
I haven't been able to make this solution work. My device is running iOS 11. This question https://mcmap.net/q/608901/-custom-uti-does-not-work-for-imessage-in-ios-10 suggests that something changed with iOS 10. Is your App still opening iMessage attachments OK with iOS 11?Horology
S
1

The value in your Info.plist for the LSItemContentTypes key should equal what is declared by your Meeting object.

Presumably your Meeting object adheres to the UIActivityItemSource protocol. Make sure the value you return (from the delegate method activityViewController:dataTypeIdentifierForActivityType:) matches the value you have declared as readable in your Info.plist.

Stuartstub answered 28/5, 2014 at 20:0 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.