web-dev-qa-db-fra.com

Comment ouvrir une URL avec le navigateur par défaut avec les applications multiplates-formes FireMonkey?

D'habitude, j'utilise: ShellExecute(0, 'OPEN', PChar(edtURL.Text), '', '', SW_SHOWNORMAL);

Comment puis-je avoir le même comportement (ouvrir un lien dans le navigateur par défaut) sur toutes les plateformes (Windows et OSX)?

27
Whiler

Dans le forum de discussion FireMonkey, j'ai trouvé ce code pour une question à propos de NSWorkspace.URLForApplicationToOpenURL:

uses
  Posix.Stdlib;
....
  _system(PAnsiChar('open ' + ACommand));

(pas testé par moi)


Mise à jour : Posix n'étant pas disponible sous Windows, il n'est pas possible d'écrire une solution utilisant les mêmes appels de système d'exploitation sur toutes les plateformes. Je suggère de déplacer ce code dans une unité centrale 'XPlatform' qui contient des fichiers IFDEF POSIX, etc.

12
mjn

En ce qui concerne la réponse de mjn , j’ai écrit l’unité suivante. Je l'ai testé avec succès sur Windows, mais je n'ai pas d'OSX pour le tester sur cette plate-forme. Si quelqu'un peut confirmer que cela fonctionne, j'apprécierais.

unit fOpen;

interface

uses
{$IFDEF MSWINDOWS}
  Winapi.ShellAPI, Winapi.Windows;
{$ENDIF MSWINDOWS}
{$IFDEF POSIX}
  Posix.Stdlib;
{$ENDIF POSIX}

type
  TMisc = class
    class procedure Open(sCommand: string);
  end;

implementation

class procedure TMisc.Open(sCommand: string);
begin
{$IFDEF MSWINDOWS}
  ShellExecute(0, 'OPEN', PChar(sCommand), '', '', SW_SHOWNORMAL);
{$ENDIF MSWINDOWS}
{$IFDEF POSIX}
  _system(PAnsiChar('open ' + AnsiString(sCommand)));
{$ENDIF POSIX}
end;

end.

et je l'appelle comme ça: 

TMisc.Open('https://stackoverflow.com/questions/7443264/how-to-open-an-url-with-the-default-browser-with-firemonkey-cross-platform-applic');
17
Whiler

Pour toutes les plateformes (Windows, MacOs, iOS et Android), vous pouvez utiliser l'unité que j'ai écrite pour mon blog

unit u_urlOpen;

interface

uses
  System.SysUtils, System.Types, System.UITypes, System.Classes,
  System.Variants,
{$IF Defined(IOS)}
  macapi.helpers, iOSapi.Foundation, FMX.helpers.iOS;
{$ELSEIF Defined(Android)}
Androidapi.JNI.GraphicsContentViewText,
  Androidapi.JNI.Net,
   Androidapi.JNI.App,
  Androidapi.helpers;
{$ELSEIF Defined(MACOS)}
Posix.Stdlib;
{$ELSEIF Defined(MSWINDOWS)}
Winapi.ShellAPI, Winapi.Windows;
{$ENDIF}

type
  tUrlOpen = class
    class procedure Open(URL: string);
  end;

implementation

class procedure tUrlOpen.Open(URL: string);
{$IF Defined(Android)}
var
  Intent: JIntent;
{$ENDIF}
begin
{$IF Defined(Android)}
  Intent := TJIntent.Create;
  Intent.setAction(TJIntent.JavaClass.ACTION_VIEW);
  Intent.setData(StrToJURI(URL));
  tandroidhelper.Activity.startActivity(Intent);
  // SharedActivity.startActivity(Intent);
{$ELSEIF Defined(MSWINDOWS)}
  ShellExecute(0, 'OPEN', PWideChar(URL), nil, nil, SW_SHOWNORMAL);
{$ELSEIF Defined(IOS)}
  SharedApplication.OpenURL(StrToNSUrl(URL));
{$ELSEIF Defined(MACOS)}
  _system(PAnsiChar('open ' + AnsiString(URL)));
{$ENDIF}
end;

end.
3
Patrick PREMARTIN

Code XE2 C++ testé avec succès (Windows 7 64 et OSX Lion), améliorations mineures. Merci Whiler, la douleur est finie :)

#include <fmx.h>
// ---------------------------------------------------------------------------
#ifdef _WIN32
#include <shellapi.h>
#endif// Windows
#ifdef TARGET_OS_MAC
#include <Posix.Stdlib.hpp>
#endif // Mac

void OpenCommand(String _sCommand) {
    #ifdef _Windows
    String open = "open";
    ShellExecute(0, open.w_str(), _sCommand.c_str(), NULL, NULL, SW_SHOWNORMAL);
    #endif // Windows

    #ifdef TARGET_OS_MAC
    system(AnsiString("open " + AnsiString(_sCommand)).c_str());
    #endif // Mac
}
3
Tuomas Kayhko

Et maintenant une version C++ (code OSx non testé, pas aussi sûr du _POSIX #def):

#ifdef _Windows
#include <Winapi.Windows.hpp>
#endif // _Windows
#ifdef _POSIX
#include <Posix.Stdlib.h>
#endif // _POSIX

void OpenCommand(String _sCommand)
{
    #ifdef _Windows
    ShellExecute(0, _T("open"), _sCommand.c_str(), _T(""), _T(""), SW_SHOWNORMAL);
    #endif // _Windows
    #ifdef _POSIX
    _system(AnsiString("open " + AnsiString(_sCommand)).c_str());
    #endif // _POSIX
}
1
Rhys Drummond

Comme @NicoBlu l'a mentionné, la solution acceptée semble tronquer l'URL après la première occurrence de '&'. Voici ce qui fonctionne pour moi sans troncature:

uses Macapi.AppKit, Macapi.Foundation, Macapi.Helpers;

// ...

procedure OpenLinkInDefaultBrowser(const Link: string);
  var URL : NSURL;
      Workspace : NSWorkspace;
begin
  URL := TNSURL.Wrap(TNSURL.OCClass.URLWithString(StrToNSStr(Link)));
  Workspace := TNSWorkspace.Wrap(TNSWorkspace.OCClass.sharedWorkspace);
  Workspace.openURL(URL);
end;
1
DNR
_system(PAnsiChar('open ' + AnsiString(sCommand)));

not works si la chaîne d'URL (sCommand) inclut le caractère esperluette (&), nécessaire pour spécifier plusieurs arguments dans la chaîne de requête. 

URL envoyé à def. Le navigateur dans OSX (Safari) est tronqué à la première occurrence de &.

0
NicoBlu
LEncodedString : String;

begin
    LEncodedString := TIdURI.URLEncode('http://www.malcolmgroves.com');
    sharedApplication.openURL(StringToNSURL(LEncodedString));
end;
0
Maxime Bonin