Difference between revisions of "macOS Find Default Application"
From Lazarus wiki
Jump to navigationJump to searchm (→Example code: Code clarity) |
(→Alternative example code for URL schemes: New section) |
||
Line 3: | Line 3: | ||
== Overview == | == Overview == | ||
− | 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 file system file. 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. | + | 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 file system file. |
+ | |||
+ | 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. | ||
+ | |||
+ | The alternative example code below demonstrates how to do this for various URL schemes (eg mailto:, http:, https:, sms:, tel:, etc). | ||
== Example code == | == Example code == | ||
Line 99: | Line 103: | ||
end. | end. | ||
</syntaxhighlight> | </syntaxhighlight> | ||
+ | |||
+ | == Alternative example code for URL schemes == | ||
+ | |||
+ | <syntaxhighlight lang=pascal> | ||
+ | unit Unit1; | ||
+ | |||
+ | {$mode objfpc}{$H+} | ||
+ | {$modeswitch objectivec1} | ||
+ | |||
+ | interface | ||
+ | |||
+ | uses | ||
+ | SysUtils, Forms, StdCtrls, | ||
+ | MacOSAll, CocoaAll, CocoaUtils; | ||
+ | |||
+ | type | ||
+ | |||
+ | { TForm1 } | ||
+ | |||
+ | TForm1 = class(TForm) | ||
+ | Button1: TButton; | ||
+ | Memo1: TMemo; | ||
+ | procedure Button1Click(Sender: TObject); | ||
+ | private | ||
+ | |||
+ | public | ||
+ | |||
+ | end; | ||
+ | |||
+ | var | ||
+ | Form1: TForm1; | ||
+ | |||
+ | implementation | ||
+ | |||
+ | {$R *.lfm} | ||
+ | |||
+ | { TForm1 } | ||
+ | |||
+ | procedure TForm1.Button1Click(Sender: TObject); | ||
+ | var | ||
+ | myURL: NSURL; | ||
+ | URLRef: CFURLRef; | ||
+ | OSStatus: Integer; | ||
+ | myStr: String; | ||
+ | begin | ||
+ | // Create URL scheme from one of: | ||
+ | // file:/// | ||
+ | // file://localhost/ | ||
+ | // mailto: | ||
+ | // http: | ||
+ | // https: | ||
+ | // ftp: | ||
+ | // sms: | ||
+ | // tel: | ||
+ | // facetime: | ||
+ | // ... There are probably more. | ||
+ | myURL := NSURL.alloc.initWithString(NSStr('mailto:')); | ||
+ | |||
+ | // Check for default pplication | ||
+ | OSStatus := LSGetApplicationForURL(CFURLRef(myURL), kLSRolesAll, Nil, @URLRef); | ||
+ | |||
+ | // Check for error (eg application not found for URL = -10814) | ||
+ | if(OSStatus <> 0) then | ||
+ | begin | ||
+ | Memo1.Append('LSGetApplicationForURL error status: ' + IntToStr(OSStatus)); | ||
+ | Exit; | ||
+ | end; | ||
+ | |||
+ | // Get CFString from CFURLRef, Cast to NSString, Convert to AnsiString | ||
+ | myStr := NSStringToString(NSString(CFURLGetString(URLRef))); | ||
+ | |||
+ | // Output to memo | ||
+ | memo1.Append('LSGetApplicationForURL status: ' + IntToStr(OSStatus) | ||
+ | + LineEnding + LineEnding + 'Default app: ' + myStr); | ||
+ | |||
+ | // Housekeeping | ||
+ | myURL.release; | ||
+ | end; | ||
+ | |||
+ | end. | ||
+ | </syntaxhighlight> | ||
+ | |||
[[Category:Lazarus]] | [[Category:Lazarus]] | ||
[[Category:macOS]] | [[Category:macOS]] | ||
[[Category:Code Snippets]] | [[Category:Code Snippets]] |
Revision as of 06:35, 8 December 2021
This article applies to macOS only.
See also: Multiplatform Programming Guide
Overview
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 file system file.
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.
The alternative example code below demonstrates how to do this for various URL schemes (eg mailto:, http:, https:, sms:, tel:, etc).
Example code
unit Unit1;
{$mode objfpc}{$H+}
{$modeswitch objectivec2}
interface
uses
Classes,
Forms,
Dialogs, // needed for ShowMessage()
StdCtrls, // needed for buttons
CocoaAll, // needed for Cocoa framework (origin the NeXTSTEP libraries)
CocoaUtils; // needed for NSStringToString()
type
{ TForm1 }
TForm1 = class(TForm)
Button1: TButton;
Button2: TButton;
procedure Button1Click(Sender: TObject);
procedure Button2Click(Sender: TObject);
private
public
end;
var
Form1: TForm1;
implementation
{$R *.lfm}
{ TForm1 }
procedure TForm1.Button1Click(Sender: TObject);
var
contentUrl: NSUrl;
defAppUrl: NSUrl;
defAppName: String;
begin
contentUrl := NSUrl.URLWithString(NSSTR('https://sentinel.sentry.org/'));
defAppUrl := NSWorkspace.sharedWorkspace.URLForApplicationToOpenURL(contentUrl);
// Bundle ID (required)
ShowMessage(NSStringToString(NSBundle.bundleWithURL(defAppUrl).bundleIdentifier));
// Bundle Display Name (optional)
defAppName := NSStringToString(NSBundle.bundleWithURL(defAppUrl).objectForInfoDictionaryKey(NSStr('CFBundleDisplayName').description));
// Bundle Name (conventionally required)
if (defAppName = '') then
defAppName := NSStringToString(NSBundle.bundleWithURL(defAppUrl).objectForInfoDictionaryKey(NSStr('CFBundleName').description));
// Cannot fail :-)
if (defAppName = '') then
defAppName := NSStringToString(defAppUrl.URLByDeletingPathExtension.lastPathComponent);
// Show result
ShowMessage(defAppName);
end;
procedure TForm1.Button2Click(Sender: TObject);
var
contentUrl: NSUrl;
defAppUrl: NSUrl;
defAppName: String;
begin
contentUrl := NSUrl.URLWithString(NSSTR('file:///Users/trev/my_defaults.txt'));
defAppUrl := NSWorkspace.sharedWorkspace.URLForApplicationToOpenURL(contentUrl);
// Bundle ID (required)
ShowMessage(NSStringToString(NSBundle.bundleWithURL(defAppUrl).bundleIdentifier));
// Bundle Display Name (optional)
defAppName := NSStringToString(NSBundle.bundleWithURL(defAppUrl).objectForInfoDictionaryKey(NSStr('CFBundleDisplayName').description));
// Bundle Name (conventionally required)
if (defAppName = '') then
defAppName := NSStringToString(NSBundle.bundleWithURL(defAppUrl).objectForInfoDictionaryKey(NSStr('CFBundleName').description));
// Cannot fail :-)
if (defAppName = '') then
defAppName := NSStringToString(defAppUrl.URLByDeletingPathExtension.lastPathComponent);
// Show result
ShowMessage(defAppName);
end;
end.
Alternative example code for URL schemes
unit Unit1;
{$mode objfpc}{$H+}
{$modeswitch objectivec1}
interface
uses
SysUtils, Forms, StdCtrls,
MacOSAll, CocoaAll, CocoaUtils;
type
{ TForm1 }
TForm1 = class(TForm)
Button1: TButton;
Memo1: TMemo;
procedure Button1Click(Sender: TObject);
private
public
end;
var
Form1: TForm1;
implementation
{$R *.lfm}
{ TForm1 }
procedure TForm1.Button1Click(Sender: TObject);
var
myURL: NSURL;
URLRef: CFURLRef;
OSStatus: Integer;
myStr: String;
begin
// Create URL scheme from one of:
// file:///
// file://localhost/
// mailto:
// http:
// https:
// ftp:
// sms:
// tel:
// facetime:
// ... There are probably more.
myURL := NSURL.alloc.initWithString(NSStr('mailto:'));
// Check for default pplication
OSStatus := LSGetApplicationForURL(CFURLRef(myURL), kLSRolesAll, Nil, @URLRef);
// Check for error (eg application not found for URL = -10814)
if(OSStatus <> 0) then
begin
Memo1.Append('LSGetApplicationForURL error status: ' + IntToStr(OSStatus));
Exit;
end;
// Get CFString from CFURLRef, Cast to NSString, Convert to AnsiString
myStr := NSStringToString(NSString(CFURLGetString(URLRef)));
// Output to memo
memo1.Append('LSGetApplicationForURL status: ' + IntToStr(OSStatus)
+ LineEnding + LineEnding + 'Default app: ' + myStr);
// Housekeeping
myURL.release;
end;
end.