File extension icon on Mac - macos

My application uses new proprietary file formats with extensions never been used before. I would like to associate specific icons to display my files in finder with nice iconography. As far as I know LaunchService is responsible to handle all these data, however I'm confused where, when and how shall I create associations.
Which entries I have to add to plist?
Where I need to actually register this extension - during installation? Is there any script for this?

Add a CFBundleDocumentTypes key to your plist, see
Storing Document Types Information in the Application's Property List

Related

Is it possible to assign a custom icon to a custom file extension?

I am trying to make my own coding language and I want to have a custom file extension for it. I need to have a custom icon, and a way to check for text editors (vscode etc.). So it can run on any computer with the custom icon and and a way to check for a text editor that it will automatically open when you open the file, included. I am willing to use any coding languages as long as you help me out with it and dont just tell me what to do.
I have tried using the whole HKEY stuff and since I am using a custom file extension that is not associated with windows it doesn't show up in HKEY_CLASSES_ROOT like file extensions that are associated with windows do.
Let's say you want to have an icon associated with file extension .xyz. And your icon is resource ID #0 in Resources.dll.
These registry keys become relevant:
[HKEY_CLASSES_ROOT\.xyz]
#="XYZ"
[HKEY_CLASSES_ROOT\XYZ\DefaultIcon]
#="C:\\Path\\To\\File\\With\\Resources\\Resources.dll, 0"

MacOS Get default application for file type

I am working on a Mac app. I ultimately want to use default app icons within my app. From the Info.plist and the Resource folder of an app I can get the .icns file and convert that to the image format I need. But I need to know the default application associated with the particular file extension, if any.
So how to get the default application that the system currently associates with a given file extension?
Don't go digging in other apps' bundles. It's always best to work at the level of abstraction that suits the question you want to ask. If you want to get the icon that the Finder (or a Mail attachment, etc) would display for a file of a particular type, use the NSWorkspace iconForFileType: method.
I think what you're looking for is part of the OSX Launch Services: LSCopyDefaultApplicationURLForContentType API. This returns the info on apps that can open specific Uniform Type Identifiers. There's also a similar API called LSCopyDefaultApplicationURLForURL to check which app opens a specific known file.

How can I associate a file with my app?

I have a Cocoa app "PDFHistory" on Mac OS X that uses the NSDocument architecture to save and load PDF files that are internally formatted specially for my app. I want to make it so whenever I save a file (e.g., "mydoc.pdf") from PDFHistory, then subsequently double-clicking on mydoc.pdf will automatically open it in PDFHistory.app. However, I don't want to make it so all .pdf files are automatically opened in PDFHistory, but rather use the system default (probably Preview.app). The .pdf suffix is a requirement, though, since I need the user to be able to e-mail the files to other users who can view the file in their default PDF viewer.
The problem is that if I set the LSHandlerRank to "Owner", then all .pdf files will be opened with PDFHistory, which is bad (since I only understand the internals of the .pdf file that PDFHistory wrote out). But if I set LSHandlerRank to "Alternate", then all .pdf files will be opened to the system default app (Preview.app), which is confusing for the user who had just created the file using my app.
Once upon a time, "creator codes" could be used to implement this sort of capability, but launch services started ignoring them back in Snow Leopard (see http://tidbits.com/article/10537). UTIs are not a substitute that provide this capability (see http://boredzo.org/blog/archives/2009-09-22/how-not-to-use-utis).
Using Finder to get info on the file allows the user to specify a specific app to use to open the specific file. This supposedly works by setting a "usro" property in a the file's resource. There is some open-source code to mimic this behavior (https://github.com/AlanQuatermain/SetAppAffinity), but is uses deprecated functions, and so would cause Apple to reject the app from the App Store. Similarly, people have posted AppleScript to set this property (https://discussions.apple.com/thread/2597365), but sandboxing would prevent me from invoking it.
Although the .pdf suffix is a requirement in order to be able to send the files to users on other systems/platforms, I considered trying to have the suffix registered with two extensions as ".phistory.pdf", which would allow "file.phistory.pdf" to be opened in PDFHistory, but "file.pdf" would be opened in the default PDF viewer. However, this simply didn't work: it appears that the final suffix is the only one used by launch services, and everything before that is ignored.
So is there any way to have my app be the default app for opening files that it created itself?

NSLocalizableString and info.plist

I'm creating this iOS app, in which I use the PushWoosh (www.pushwoosh.com) notification service. Notification is working fine, but now I want to differentiate notification based upon the locale of the app: I want the users of the app running their OS in English to receive a notification in English, the German users in German, etc.
For that, I register this one app several times with PushWoosh, so each localization gets its own Pushwoosh App ID. For simplicity sake, I'm aiming to have all localization stuff in one file ("localizable.strings").
PushWoosh requires to have their APPID listed in the info.plist. So what would make sense to me, is to have the value of the PushWoosh .plist key localized. This is what I did:
In the .plist, I replaced
<key>Pushwoosh_APPID</key>
<string>2B46A-F82CC</string>
with
<key>Pushwoosh_APPID</key>
<string>PUSHWOOSH_ID</string>
Then, in the localizable.strings, I added the following entry:
"PUSHWOOSH_ID" = "2B46A-F82CC";
Finally, in the code, I replaced
[[NSUserDefaults standardUserDefaults] setObject:appCode forKey:#"Pushwoosh_APPID"];
with
[[NSUserDefaults standardUserDefaults] setObject:appCode forKey:NSLocalizedString(#"Pushwoosh_APPID", nil)];
Somehow, however, when running the app, "Pushwoosh_APPID" resolves into "PUSHWOOSH_ID", rather than in "2B46A-F82CC".
All other strings in localizable.strings are called just fine, so I guess it's a syntax thing.
Concrete question: what am I doing wrong, code-wise? Also, shoot me if this is an undesirable approach in general.
Thanks in advance!
For localizing Info.plist values, you will need to create a separate strings file called InfoPlist.strings under your language-specific project directory, such as en.lproj, etc, and put the key and the translated value there, for example:
Pushwoosh_APPID = "2B46A-F82CC";
Take a look at the reference of Information Property List Key:
... you store the values for a particular localization in a strings file
with the name InfoPlist.strings. You place this file in the same
language-specific project directory that you use to store other
resources for the same localization. The contents of the
InfoPlist.strings file are the individual keys you want localized and
the appropriately translated value. The routines that look up key
values in the Info.plist file take the user’s language preferences
into account and return the localized version of the key (from the
appropriate InfoPlist.strings file) when one exists. If a localized
version of a key does not exist, the routines return the value stored
in the Info.plist file.
FYI Pushwoosh provides the Multi-language support for sending notifications in the language, which is set in the OS. Its based on Tags, and can be used both via the Control Panel and API. I suppose it would be way easier not to reinvent the wheel :)

inverse of LSGetApplicationForItem

I am writing a image viewer application, which I need to set as default application for jpeg/gif files. There is an API LSGetApplicationForItem/Info for getting information on what is the default application.
But I am not able to find an API where I can set my application as the default viewer for image files.
Can you please help
You want the LSSetDefaultRoleHandlerForContentType function. Pass kUTTypeGIF for GIF, kUTTypeJPEG for JPEG.
Please only do this when the user explicitly tells you to. Otherwise, they will hate you.
There's not a public API to do that, as far as I know. Instead, you register, using Info.plist (or the Document Types section of the Info editor in Xcode), that you are a provider of viewing and/or editing for whatever file types you are interested in. This will cause the system to choose your app if there's no other app who can open those file types, and will put you in the running if the user chooses Open With from the context menu when selecting a file in the Finder.

Resources