Sign in Join
Wiki copytemporary

macOS Find Default Application: what changed

Revision 0 to 1. Removed lines have a minus sign; added lines have a plus sign.

Title: macOS Find Default Application

OldNewLine
1+*(macOS only)*
2+
3+## Overview
4+
5+From time to time your application may need to determine the user's default application for opening certain content - for example, a web URL or a system file.
6+
7+Example code which demonstrates how to do this is set out below. Note that these are obviously not the only two content for which you may wish to determine the user's default application, but the same general approach will apply for those other content types.
8+
9+The alternative example code below demonstrates how to do this for various URL schemes (eg mailto:, http:, https:, sms:, tel:, etc).
10+
11+## Example code
12+
13+``` pascal
14+unit Unit1;
15+
16+{$mode objfpc}{$H+}
17+{$modeswitch objectivec2}
18+
19+interface
20+
21+uses
22+ Classes,
23+ Forms,
24+ Dialogs, // needed for ShowMessage()
25+ StdCtrls, // needed for buttons
26+ CocoaAll, // needed for Cocoa framework (origin the NeXTSTEP libraries)
27+ CocoaUtils; // needed for NSStringToString()
28+
29+type
30+
31+ { TForm1 }
32+
33+ TForm1 = class(TForm)
34+ Button1: TButton;
35+ Button2: TButton;
36+ procedure Button1Click(Sender: TObject);
37+ procedure Button2Click(Sender: TObject);
38+ private
39+
40+ public
41+
42+ end;
43+
44+var
45+ Form1: TForm1;
46+
47+implementation
48+
49+{$R *.lfm}
50+
51+{ TForm1 }
52+
53+procedure TForm1.Button1Click(Sender: TObject);
54+var
55+ contentUrl: NSUrl;
56+ defAppUrl: NSUrl;
57+ defAppName: String;
58+begin
59+ contentUrl := NSUrl.URLWithString(NSSTR('https://sentinel.sentry.org/'));
60+ defAppUrl := NSWorkspace.sharedWorkspace.URLForApplicationToOpenURL(contentUrl);
61+
62+ // Bundle ID (required)
63+ ShowMessage(NSStringToString(NSBundle.bundleWithURL(defAppUrl).bundleIdentifier));
64+
65+ // Bundle Display Name (optional)
66+ defAppName := NSStringToString(NSBundle.bundleWithURL(defAppUrl).objectForInfoDictionaryKey(NSStr('CFBundleDisplayName').description));
67+ // Bundle Name (conventionally required)
68+ if (defAppName = '') then
69+ defAppName := NSStringToString(NSBundle.bundleWithURL(defAppUrl).objectForInfoDictionaryKey(NSStr('CFBundleName').description));
70+ // Cannot fail :-)
71+ if (defAppName = '') then
72+ defAppName := NSStringToString(defAppUrl.URLByDeletingPathExtension.lastPathComponent);
73+
74+ // Show result
75+ ShowMessage(defAppName);
76+end;
77+
78+procedure TForm1.Button2Click(Sender: TObject);
79+var
80+ contentUrl: NSUrl;
81+ defAppUrl: NSUrl;
82+ defAppName: String;
83+begin
84+ contentUrl := NSUrl.URLWithString(NSSTR('file:///Users/trev/my_defaults.txt'));
85+ defAppUrl := NSWorkspace.sharedWorkspace.URLForApplicationToOpenURL(contentUrl);
86+
87+ // Bundle ID (required)
88+ ShowMessage(NSStringToString(NSBundle.bundleWithURL(defAppUrl).bundleIdentifier));
89+
90+ // Bundle Display Name (optional)
91+ defAppName := NSStringToString(NSBundle.bundleWithURL(defAppUrl).objectForInfoDictionaryKey(NSStr('CFBundleDisplayName').description));
92+ // Bundle Name (conventionally required)
93+ if (defAppName = '') then
94+ defAppName := NSStringToString(NSBundle.bundleWithURL(defAppUrl).objectForInfoDictionaryKey(NSStr('CFBundleName').description));
95+ // Cannot fail :-)
96+ if (defAppName = '') then
97+ defAppName := NSStringToString(defAppUrl.URLByDeletingPathExtension.lastPathComponent);
98+
99+ // Show result
100+ ShowMessage(defAppName);
101+end;
102+
103+end.
104+```
105+
106+Full project source code is available from [SourceForge](https://sourceforge.net/p/lazarus-wiki-projects/code/ci/master/tree/laz_default_app/).
107+
108+## Alternative example code for URL schemes
109+
110+Note that *LSGetApplicationForURL* was deprecated in macOS 10.10 (Yosemite) in favour of *LSCopyDefaultApplicationURLForURL* which itself was deprecated in macOS 12 (Monterey), both functions are still working in macOS 12.0.1. There is no example code for *LSCopyDefaultApplicationURLForURL* because the function is missing from the FPC `packages/univint/src/LSInfo.pas` file.
111+
112+``` pascal
113+unit Unit1;
114+
115+{$mode objfpc}{$H+}
116+{$modeswitch objectivec1}
117+
118+interface
119+
120+uses
121+ SysUtils, Forms, StdCtrls,
122+ MacOSAll, CocoaAll, CocoaUtils;
123+
124+type
125+
126+ { TForm1 }
127+
128+ TForm1 = class(TForm)
129+ Button1: TButton;
130+ Memo1: TMemo;
131+ procedure Button1Click(Sender: TObject);
132+ private
133+
134+ public
135+
136+ end;
137+
138+var
139+ Form1: TForm1;
140+
141+implementation
142+
143+{$R *.lfm}
144+
145+{ TForm1 }
146+
147+procedure TForm1.Button1Click(Sender: TObject);
148+var
149+ myURL: NSURL;
150+ URLRef: CFURLRef;
151+ OSStatus: Integer;
152+ myStr: String;
153+begin
154+ // Create URL scheme from one of:
155+ // file:///
156+ // file://localhost/
157+ // mailto:
158+ // http:
159+ // https:
160+ // ftp:
161+ // sms:
162+ // tel:
163+ // facetime:
164+ // ... There are probably more.
165+ myURL := NSURL.alloc.initWithString(NSStr('mailto:'));
166+
167+ // Check for default pplication
168+ OSStatus := LSGetApplicationForURL(CFURLRef(myURL), kLSRolesAll, Nil, @URLRef);
169+
170+ // Check for error (eg application not found for URL = -10814)
171+ if(OSStatus <> 0) then
172+ begin
173+ Memo1.Append('LSGetApplicationForURL error status: ' + IntToStr(OSStatus));
174+ Exit;
175+ end;
176+
177+ // Get CFString from CFURLRef, Cast to NSString, Convert to AnsiString
178+ myStr := NSStringToString(NSString(CFURLGetString(URLRef)));
179+
180+ // Output to memo
181+ memo1.Append('LSGetApplicationForURL status: ' + IntToStr(OSStatus)
182+ + LineEnding + LineEnding + 'Default app: ' + myStr);
183+
184+ // Housekeeping
185+ myURL.release;
186+end;
187+
188+end.
189+```
190+
191+Full project source code is available from [SourceForge](https://sourceforge.net/p/lazarus-wiki-projects/code/ci/master/tree/laz_default_app2/).
192+
193+## See also
194+
195+- [[Webbrowser|Find the default web browser]] - cross-platform example.
196+
197+## External links
198+
199+- [Apple: NSWorkspace](https://developer.apple.com/documentation/appkit/nsworkspace) - available from macOS 10.0
200+- [Apple: NSURL](https://developer.apple.com/documentation/foundation/nsurl) - available from macOS 10.0
201+- [Apple: CFURL, CFURLRef](https://developer.apple.com/documentation/corefoundation/cfurl?language=objc) - available from macOS 10.0
202+- [Apple: LSGetApplicationForURL](https://developer.apple.com/documentation/coreservices/1445210-lsgetapplicationforurl) - available from macOS 10.0 - deprecated in macOS 10.10
203+- [Apple: LSCopyDefaultApplicationURLForURL](https://developer.apple.com/documentation/coreservices/1448824-lscopydefaultapplicationurlforur) - available from macOS 10.10 - deprecated in macOS 12
204+
205+---
206+*From the Free Pascal wiki, page "macOS Find Default Application", as it stood on 2021-12-08 after a change by Alextp, out of the wiki's dump of 2024-05-26. Copyright stays with the author who wrote it, according to the old wiki's [[Licensing]] page. If you have concerns about this material, [message the admin](/wiki-contact).*
207+Category: Code Snippets
208+Category: Lazarus
209+Category: macOS

Back to history