I have defined a custom document type containing binary data for my app, with identifier "com.mycompany.gcp", using an Exported UTI. I am using this document type to exchange data with macOS and iOS versions of my app. After much trial and error, it is working reasonably well. However, I feel like I am missing a critical step.
When I export a file from my app, I create the file using FileManager.createFile(atPath:, contents:, attributes:). I create the file with my gcp extension, however I do not know how to specify the identifier type, specifically to set it to "com.mycompany.gcp". When I export the file, if I inspect it with mdls, kMDItemContentType = "dyn.ah62d4rv4ge80s25u", which I assume refers to a dynamic identifier, rather than my identifier.
My questions are: 1) is there a way to set the identifier when creating the file? I have tried the NSURL methods to set the identifier without success. 2) does this matter?
I feel like the answer the question 2 is yes. With iOS, if I email or airdrop the file, I can open it with my app. However, with iMessage, no action occurs when I tap on a sent file.
Here are the relevant keys from the Info.plist for the iOS version of my app:
<key>CFBundleDocumentTypes</key>
<array>
<dict>
<key>CFBundleTypeIconFiles</key>
<array/>
<key>CFBundleTypeName</key>
<string>GCP File</string>
<key>CFBundleTypeRole</key>
<string>Editor</string>
<key>LSHandlerRank</key>
<string>Owner</string>
<key>LSItemContentTypes</key>
<array>
<string>com.mycompany.gcp</string>
</array>
</dict>
</array>
<key>UTExportedTypeDeclarations</key>
<array>
<dict>
<key>UTTypeConformsTo</key>
<array>
<string>public.data</string>
</array>
<key>UTTypeDescription</key>
<string>GCP File</string>
<key>UTTypeIdentifier</key>
<string>com.mycompany.gcp</string>
<key>UTTypeTagSpecification</key>
<dict>
<key>public.filename-extension</key>
<array>
<string>gcp</string>
</array>
</dict>
</dict>
</array>
Related
I created my own filetype "dmate". Assume I exported a .dmate file to iPhones Files. When clicking on that file, it is looking like this - the JSON-Content is displayed:
Now I can click on the share button and open the file in my App DietMate - which works fine:
Problem: I do not want the user to see JSON text but want the Files-App and WhatsApp and so on to open the file immediately in my App without doing a preview.
Here is the relevant part of my plist.info
<key>CFBundleDocumentTypes</key>
<array>
<dict>
<key>CFBundleTypeName</key>
<string>Food</string>
<key>CFBundleTypeIconFiles</key>
<array>
<string>dmate.ft.png</string>
<string>dmate.ft.png</string>
</array>
<key>CFBundleTypeRole</key>
<string>Viewer</string>
<key>LSHandlerRank</key>
<string>Owner</string>
<key>LSItemContentTypes</key>
<array>
<string>de.example.app.food.dmate</string>
</array>
</dict>
</array>
<key>UTExportedTypeDeclarations</key>
<array>
<dict>
<key>UTTypeConformsTo</key>
<array>
<string>public.json</string>
</array>
<key>UTTypeDescription</key>
<string>Food</string>
<key>UTTypeIdentifier</key>
<string>de.example.app.food.dmate</string>
<key>UTTypeTagSpecification</key>
<dict>
<key>public.filename-extension</key>
<string>dmate</string>
<key>public.mime-type</key>
<string>food/x-dmate</string>
</dict>
</dict>
</array>
Does anyone know, how to open my custom filetype in my own app?
If you want your app to launch right away after tapping the file in the Files app, try adding this key-value pair to your Info.plist:
<key>LSSupportsOpeningDocumentsInPlace</key>
<true/>
Another thing you could try is to set "Conforms To" to public.data instead of public.json. This means that the system will no longer assume that your data is JSON, and hopefully stop displaying it that way. It might have some implications on what sharing channels are supported, and I haven’t yet managed to fully wrap my head around this.
Trying to achieve the same functionality as an Excel page that is shared or a Word doc that is shared opens the Excel or Word app.
I have a document with a custom extension .DLMSFT and .dlmsft. They are both registered in my app's Document type, Exported Type Identifiers and Imported Type Identifiers
See plist below:
<key>CFBundleDocumentTypes</key>
<array>
<dict>
<key>CFBundleTypeName</key>
<string>Routes</string>
<key>CFBundleTypeRole</key>
<string>Editor</string>
<key>LSHandlerRank</key>
<string>Owner</string>
<key>LSItemContentTypes</key>
<array>
<string>com.Routes</string>
</array>
</dict>
</array>
<key>UTExportedTypeDeclarations</key>
<array>
<dict>
<key>UTTypeConformsTo</key>
<array>
<string>public.data</string>
</array>
<key>UTTypeDescription</key>
<string>Routes</string>
<key>UTTypeIconFiles</key>
<array/>
<key>UTTypeIdentifier</key>
<string>com.Routes</string>
<key>UTTypeTagSpecification</key>
<dict>
<key>public.filename-extension</key>
<array>
<string>dlmsft</string>
<string>DLMSFT</string>
</array>
</dict>
</dict>
</array>
<key>UTImportedTypeDeclarations</key>
<array>
<dict>
<key>UTTypeConformsTo</key>
<array>
<string>public.data</string>
</array>
<key>UTTypeDescription</key>
<string>Routes</string>
<key>UTTypeIconFiles</key>
<array/>
<key>UTTypeIdentifier</key>
<string>com.Routes</string>
<key>UTTypeTagSpecification</key>
<dict>
<key>public.filename-extension</key>
<array>
<string>dlmsft</string>
<string>DLMSFT</string>
</array>
</dict>
</dict>
</array>
Expected Output - To share via iOS Share Sheet to something like Teams or Slack or Outlook and when the receiving user opens the file it will open the app automatically IF they have it installed.
Current Output - I am able to share the file to all available apps including mail and outlook however when I share to MS Teams and the user on the receiving end opens it the app is not launched and instead they get an error that says "Teams cannot open the file as its unsupported". The same happens in Outlook. iOS Mail app is the only one that even allows you to choose the app to open the file.
For more context below is the code for sharing the document using the Share Sheet:
public static async void ShareRoute(Route route)
{
var routeTitle = $"{route.Start.Name}-To-{route.Destination.Name}.DLMSFT";
var fn = routeTitle;
var file = Path.Combine(FileSystem.CacheDirectory, fn);
File.WriteAllText(file, SerializeRoute(route));
await Share.RequestAsync(new ShareFileRequest
{
Title = routeTitle,
File = new ShareFile(file)
});
}
I feel like I have read docs after docs after docs and I also think I am following all the correct steps. Not sure what I am missing. Hopefully someone can lend a helping hand. Thanks all!
I am currently working on a "share" feature in my app. I have custom objects that I am parsing to JSON and I currently have a working implementation to export them as a "___.blueprint" file. So I have created my own custom extension and I have set up everything when it comes to the UTIs and all.
Exporting works well and I have no issue when sending it via email. I can easy tap the mail attachment and select my own app. Importing and handling the data inside the app works as well.
However, When I send the file via AirDrop or messages, iOS doesn't know what to do with it. It doesn't suggest my app as an option to open it with. My info.plist looks like this:
<array>
<dict>
<key>CFBundleTypeName</key>
<string>Blueprint Data</string>
<key>CFBundleTypeRole</key>
<string>Editor</string>
<key>LSHandlerRank</key>
<string>Owner</string>
<key>LSItemContentTypes</key>
<array>
<string>com.ferdinandgoeldner.breadme.blueprint</string>
</array>
</dict>
</array>
...
<key>UTExportedTypeDeclarations</key>
<array>
<dict>
<key>UTTypeConformsTo</key>
<array>
<string>public.data</string>
</array>
<key>UTTypeDescription</key>
<string>Blueprint Data</string>
<key>UTTypeIconFiles</key>
<array/>
<key>UTTypeIdentifier</key>
<string>com.ferdinandgoeldner.breadme.blueprint</string>
<key>UTTypeTagSpecification</key>
<dict>
<key>public.filename-extension</key>
<array>
<string>blueprint</string>
</array>
<key>public.mime-type</key>
<array>
<string>blueprint</string>
</array>
</dict>
</dict>
</array>
<key>UTImportedTypeDeclarations</key>
<array>
<dict>
<key>UTTypeConformsTo</key>
<array>
<string>public.data</string>
</array>
<key>UTTypeDescription</key>
<string>Blueprint Data</string>
<key>UTTypeIconFiles</key>
<array/>
<key>UTTypeIdentifier</key>
<string>com.ferdinandgoeldner.breadme.blueprint</string>
<key>UTTypeTagSpecification</key>
<dict>
<key>public.filename-extension</key>
<array>
<string>blueprint</string>
</array>
<key>public.mime-type</key>
<array>
<string>blueprint</string>
</array>
</dict>
</dict>
</array>
I am really lost as to why iOS does allow me to direct the file to my app which can clearly handle the format, but does not think of letting me "open" the file in my application. What am I missing?
I got it to work!
I am not entirely sure what solved it, though.
Here are the steps I performed that made it work.
I chose a more specific UTI type.
Deinstalled all versions of my app.
I created a UTI with a shorter extension (.bmb)
I am pretty sure that .blueprint is a datatype that is not super unique, so I chose an extension that's more unique.
I also carefully ready this page of the Apple Developer Documentation. That also seemed to help me get a better grasp of how to make this stuff happen and what was going on under the hood.
I am still partially unsure of what solved the issue but tweaking several parameters made it happen.
To whoever finds this thread: Good luck. It is possible even though it seems like nothing helps. Keep experimenting and try the steps I described above. ;)
I've defined a custom UTI for an iOS app and transferring files via AirDrop. Its all working as it should, except that on the receiving device the user is offered a choice of apps such as DropBox, Evernote, etc in addition to my app. I'd like to prevent this, so the user is only shown my app as the choice. Is this possible?
In my info.plist I have:
<key>CFBundleDocumentTypes</key>
<array>
<dict>
<key>CFBundleTypeIconFiles</key>
<array>
<string>Icon.png</string>
</array>
<key>CFBundleTypeName</key>
<string>My Text</string>
<key>CFBundleTypeRole</key>
<string>Viewer</string>
<key>LSHandlerRank</key>
<string>Owner</string>
<key>LSItemContentTypes</key>
<array>
<string>com.me.text</string>
</array>
</dict>
</array>
<key>UTExportedTypeDeclarations</key>
<array>
<dict>
<key>UTTypeDescription</key>
<string>My Text</string>
<key>UTTypeIdentifier</key>
<string>com.me.text</string>
<key>UTTypeTagSpecification</key>
<dict>
<key>public.filename-extension</key>
<string>per</string>
</dict>
</dict>
</array>
What am I doing wrong?
You're attempting to assert your will over the user; that never ends well.
Your problem isn't actually caused on your end, tho':
DropBox, Evernote et. al. are probably declaring their own schemes where they allow all files; and the system acts appropriately, giving a list of all matching applications (which will always contain applications that declare *).
In other words, what you are attempting to do is:
Impossible
Not intended by the design
Deeply antisocial
I solved this problem myself. I did it by changing the exported type to be based on public.data.
This is a logical thing to do because the file exported by my app makes no sense to be consumed by Evernote, etc. I was incorrect in specifying it as text, because that would have really confused the user - pushing a dialog that gave them them options that were illogical. Contrary to claims of another poster here, this isn't a case of "exerting my will over the user" but of mistakenly specifying a structured file meant for another program to parse as a text file. Basing on public.data fixes this and now the user has a better experience.
My UTExportedTypeDeclations now looks like this for others that might be interested:
<key>UTExportedTypeDeclarations</key>
<array>
<dict>
<key>UTTypeConformsTo</key>
<array>
<string>public.data</string>
</array>
<key>UTTypeDescription</key>
<string>My Text</string>
<key>UTTypeIdentifier</key>
<string>com.me.text</string>
<key>UTTypeTagSpecification</key>
<dict>
<key>public.filename-extension</key>
<string>per</string>
</dict>
</dict>
</array>
I am trying to register my app as being able to open text files. Based on some digging, below is what I tried and while it compiled, it didnt work. When I go into dropbox and try to launch a txt file, I get 'No installed apps support opening this file'. What do I need to do to make my app show up for any txt file?
<key>CFBundleDocumentTypes</key>
<array>
<dict>
<key>CFBundleTypeName</key>
<string>Text File</string>
<key>CFBundleTypeRole</key>
<string>Viewer</string>
<key>CFBundleTypeExtensions</key>
<array>
<string>txt</string>
<string>TXT</string>
</array>
<key>LSHandlerRank</key>
<string>Alternate</string>
<key>LSItemContentTypes</key>
<array>
<string>public.txt</string>
</array>
</dict>
</array>
My app imports TXT files, too.
Change your Info.plist:
Change public.txt in the listing above to com.myapp.txt (or whatever you want)
After the last </array> of your listing above add:
<key>UTExportedTypeDeclarations</key>
<array>
<dict>
<key>UTTypeConformsTo</key>
<array>
<string>public.text</string>
</array>
<key>UTTypeDescription</key>
<string>Plain Text Document</string>
<key>UTTypeIdentifier</key>
<string>com.myapp.txt</string>
<key>UTTypeTagSpecification</key>
<dict>
<key>public.filename-extension</key>
<string>txt</string>
<key>public.mime-type</key>
<string>text/plain</string>
</dict>
</dict>
</array>
You may replace com.myapp.txt with whatever identifier you want.
I hope this helps.
Answer updated for iOS 11 and Xcode 9
If the document type you are adding is not a custom document type, you don't have to "register your app" because the standard types are already know by iOS (this is the case of text files).
Just select the target in your project and enter the text file type in the Document Types section:
For more info, please see the "Adding A Document Type" section of this Apple's document: https://developer.apple.com/library/content/qa/qa1587/_index.html