如何使用Java在默认的Web浏览器中打开URL

141
有人可以告诉我如何打开默认的网络浏览器并将页面设置为 "www.example.com" 吗?谢谢。

2
重复问题:https://dev59.com/imgu5IYBdhLWcg3w8Lav - koppor
1
可能是在Java GUI中打开网页浏览器的重复问题。 - Nathan
12个回答

205

java.awt.Desktop 是您要寻找的类。

import java.awt.Desktop;
import java.net.URI;

// ...

if (Desktop.isDesktopSupported() && Desktop.getDesktop().isSupported(Desktop.Action.BROWSE)) {
    Desktop.getDesktop().browse(new URI("http://www.example.com"));
}

3
这是一个跨平台的解决方案还是仅限于 Windows?本线程中的其他答案建议在 Linux 上使用 Runtime 类。 - isapir
2
这对我不起作用。在我的Windows机器上,IsDesktopSupported方法总是返回false。怎么回事? - krzysiek.ste
2
如果用户已经为文件扩展名(例如“html”)分配了自定义的“打开方式”操作,则不会打开浏览器,而是打开用户链接的程序... 这根本不是解决方案! - thesaint
4
请使用Desktop.getDesktop().isSupported(Desktop.Action.BROWSE)检查。 - Thibstars
5
如果用户已更改HTML文件的处理程序,那么这就是用户希望HTML文件的默认浏览器,因此这正是问题所要问的。 - toolforger
显示剩余3条评论

51

对于我来说,使用Desktop.isDesktopSupported()的解决方案并没有起作用(在Windows 7和Ubuntu上)。请尝试以下方法从Java代码中打开浏览器:

Windows:

Runtime rt = Runtime.getRuntime();
String url = "http://stackoverflow.com";
rt.exec("rundll32 url.dll,FileProtocolHandler " + url);

Mac

Runtime rt = Runtime.getRuntime();
String url = "http://stackoverflow.com";
rt.exec("open " + url);

Linux:

Runtime rt = Runtime.getRuntime();
String url = "http://stackoverflow.com";
String[] browsers = { "google-chrome", "firefox", "mozilla", "epiphany", "konqueror",
                                 "netscape", "opera", "links", "lynx" };
 
StringBuffer cmd = new StringBuffer();
for (int i = 0; i < browsers.length; i++)
    if(i == 0)
        cmd.append(String.format(    "%s \"%s\"", browsers[i], url));
    else
        cmd.append(String.format(" || %s \"%s\"", browsers[i], url)); 
    // If the first didn't work, try the next browser and so on

rt.exec(new String[] { "sh", "-c", cmd.toString() });

如果您想要拥有跨平台应用程序,需要添加操作系统检查(例如):

String os = System.getProperty("os.name").toLowerCase();

Windows:

os.indexOf("win") >= 0

Mac:

os.indexOf("mac") >= 0

Linux:

os.indexOf("nix") >=0 || os.indexOf("nux") >=0

1
为什么要在这里使用StringBuffer? - Stephan
7
在 Linux 解决方案中列出所有的浏览器是很糟糕的。如果有人使用列表中未包含的其他浏览器呢?(例如列表中没有 Chrome 或 Chromium)或者有人同时拥有 Epiphany 和 Firefox,但更喜欢使用后者呢?在这种情况下,使用“xdg-open”要好得多。因此,解决方案可以像 macOS 一样简单。 - m4tx
1
Windows 的另一个选项是 rt.exec("start "" + url +"");。 - Ivan Nikitin

44

这是我的代码。它将在默认浏览器中打开给定的URL(跨平台解决方案)。

import java.awt.Desktop;
import java.io.IOException;
import java.net.URI;
import java.net.URISyntaxException;

public class Browser {
    public static void main(String[] args) {
        String url = "http://www.google.com";

        if(Desktop.isDesktopSupported()){
            Desktop desktop = Desktop.getDesktop();
            try {
                desktop.browse(new URI(url));
            } catch (IOException | URISyntaxException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }else{
            Runtime runtime = Runtime.getRuntime();
            try {
                runtime.exec("xdg-open " + url);
            } catch (IOException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }
    }
}

2
"'xdg-open' 不被识别为内部或外部命令,可执行程序或批处理文件。" - xehpuk
11
那是一个Unix命令。你为什么在Windows上运行它? - Zuko
8
除了检查 'Desktop.isDesktopSupported()',还要检查 'Desktop.getDesktop().isSupported(Action.BROWSE)'。 - Kanchu

7
正如Tim Cooper提供的答案中所述,自Java 6(1.6)版本以来,java.awt.Desktop已经提供了这个功能,但需要注意以下细节: 使用isDesktopSupported()方法来确定桌面API是否可用。在Solaris操作系统和Linux平台上,此API依赖于Gnome库。如果这些库不可用,则该方法将返回false。 对于不支持或提供java.awt.Desktop的平台,请查看BrowserLauncher2项目。它源于Eric Albert最初编写和发布的BrowserLauncher类,并进行了一些更新。我在20世纪初成功地在一个多平台Java应用程序中使用了原始的BrowserLauncher类,该应用程序在本地运行并具有Web浏览器界面。
请注意,BrowserLauncher2的许可证是GNU Lesser General Public License。如果该许可证不可接受,请寻找一份原始的BrowserLauncher副本,其许可证非常自由:

此代码的版权所有者为Eric Albert(ejalbert@cs.stanford.edu),版权所有(1999-2001),只要本段落到评论结束的部分未被删除,即可以任何形式重新分发或修改。作者请求被通知使用此代码的任何应用程序、小程序或其他二进制文件,但这更多是出于好奇心而非必需。此软件不包括任何保修。作者对使用此软件造成的任何数据或功能损失或任何不良或意外影响不承担责任。

致谢: Steven Spencer,JavaWorld杂志(Java Tip 66) 还要感谢Ron B. Yeh、Eric Shapiro、Ben Engber、Paul Teitlebaum、Andrea Cantatore、Larry Barowski、Trevor Bedzek、Frank Miedrich和Ron Rabakukk

除BrowserLauncher2之外的项目也可能更新了原始的BrowserLauncher,以适应自2001年以来浏览器和默认系统安全设置的更改。

BrowserLauncher2的维护分支可在https://github.com/rajing/browserlauncher2上获得。 - koppor
1
对于那些想在 Mac 上使用 BrowserLauncher2 的人来说,无论是原始的 BrowserLauncher2 还是 @koppor 提到的分支,在 Mac OS X Sierra 上均无法正常工作。两者都假定存在一个“mrj.version”系统属性,而该属性显然已不再存在。因此,当启动程序构建时,代码将抛出 NullPointerException。有关更多信息,请参见 https://sourceforge.net/p/browserlaunch2/bugs/14/。 - Coren

7

希望你不介意,我从上面整理了所有有用的东西,并编写出一个完整的类供测试使用...

import java.awt.Desktop;
import java.io.IOException;
import java.net.URI;
import java.net.URISyntaxException;

public class MultiBrowPop {

    public static void main(String[] args) {
        OUT("\nWelcome to Multi Brow Pop.\nThis aims to popup a browsers in multiple operating systems.\nGood luck!\n");

        String url = "http://www.birdfolk.co.uk/cricmob";
        OUT("We're going to this page: "+ url);

        String myOS = System.getProperty("os.name").toLowerCase();
        OUT("(Your operating system is: "+ myOS +")\n");

        try {
            if(Desktop.isDesktopSupported()) { // Probably Windows
                OUT(" -- Going with Desktop.browse ...");
                Desktop desktop = Desktop.getDesktop();
                desktop.browse(new URI(url));
            } else { // Definitely Non-windows
                Runtime runtime = Runtime.getRuntime();
                if(myOS.contains("mac")) { // Apples
                    OUT(" -- Going on Apple with 'open'...");
                    runtime.exec("open " + url);
                } 
                else if(myOS.contains("nix") || myOS.contains("nux")) { // Linux flavours 
                    OUT(" -- Going on Linux with 'xdg-open'...");
                    runtime.exec("xdg-open " + url);
                }
                else 
                    OUT("I was unable/unwilling to launch a browser in your OS :( #SadFace");
            }
            OUT("\nThings have finished.\nI hope you're OK.");
        }
        catch(IOException | URISyntaxException eek) {
            OUT("**Stuff wrongly: "+ eek.getMessage());
        }
    }

    private static void OUT(String str) {
        System.out.println(str);
    }
}

6
您可以使用Runtime创建跨平台解决方案:
import java.awt.Desktop;
import java.net.URI;

public class App {

    public static void main(String[] args) throws Exception {
        String url = "http://stackoverflow.com";

        if (Desktop.isDesktopSupported()) {
            // Windows
            Desktop.getDesktop().browse(new URI(url));
        } else {
            // Ubuntu
            Runtime runtime = Runtime.getRuntime();
            runtime.exec("/usr/bin/firefox -new-window " + url);
        }
    }
}

6
/usr/bin/firefox 不是非 Windows 平台上的标准浏览器名称!可能是 Chrome,或 Epiphany,或其他许多浏览器。 - toolforger

5
很简单,只需编写以下代码:

非常简单,只需编写下面的代码:

String s = "http://www.google.com";
Desktop desktop = Desktop.getDesktop();
desktop.browse(URI.create(s));

如果你不想加载URL,那么可以将你的浏览器名称写入字符串值中,例如:

String s = "chrome";
Desktop desktop = Desktop.getDesktop();
desktop.browse(URI.create(s));

在执行程序后,它会自动打开一个空的URL网页


2
我将上面Brajesh Kumar的答案重写为Clojure,如下所示:
(defn open-browser 
  "Open a new browser (window or tab) viewing the document at this `uri`."
  [uri]
  (if (java.awt.Desktop/isDesktopSupported)
    (let [desktop (java.awt.Desktop/getDesktop)]
      (.browse desktop (java.net.URI. uri)))
    (let [rt (java.lang.Runtime/getRuntime)]
      (.exec rt (str "xdg-open " uri)))))

如果对任何人有用的话。

1
在Windows上调用“cmd /k start http://www.example.com”。 实际上,您可以始终使用start命令调用“默认”程序。 例如,start abc.mp3将调用默认的mp3播放器并加载请求的mp3文件。

你已经发布了便携版本。我只是提出了另一个解决方案,如果你需要在默认程序中打开的不仅仅是URL,则可以记住此解决方案。 - d-live

1
JavaFX在其StandaloneHostService中打包了一种跨平台解决方案,它独立于AWT,与krzysiek.ste的答案有些相似。
我重新编写了它,包括一些xdg-open的替代方案(顺便说一下,这些替代方案实际上是由xdg-open使用的)。
private static final String[][] commands = new String[][]{
        {"xdg-open", "$1"},
        {"gio", "open", "$1"},
        {"gvfs-open", "$1"},
        {"gnome-open", "$1"},  // Gnome
        {"mate-open", "$1"},  // Mate
        {"exo-open", "$1"},  // Xfce
        {"enlightenment_open", "$1"},  // Enlightenment
        {"gdbus", "call", "--session", "--dest", "org.freedesktop.portal.Desktop",
            "--object-path", "/org/freedesktop/portal/desktop",
            "--method", "org.freedesktop.portal.OpenURI.OpenURI",
            "", "$1", "{}"},  // Flatpak
        {"open", "$1"},  // Mac OS fallback
        {"rundll32", "url.dll,FileProtocolHandler", "$1"},  // Windows fallback
};

这是最终的Java代码片段,避免了字符串拼接和转义字符问题。
public static void showDocument(final String uri) {
    String osName = System.getProperty("os.name");
    try {
        if (osName.startsWith("Mac OS")) {
            Runtime.getRuntime().exec(new String[]{"open", uri});
        } else if (osName.startsWith("Windows")) {
            Runtime.getRuntime().exec(new String[]{"rundll32", "url.dll,FileProtocolHandler", uri});
        } else { //assume Unix or Linux
            new Thread(() -> {
                try {
                    for (String[] browser : commands) {
                        try {
                            String[] command = new String[browser.length];
                            for (int i = 0; i < browser.length; i++)
                                if (browser[i].equals("$1"))
                                    command[i] = uri;
                                else
                                    command[i] = browser[i];
                            if (Runtime.getRuntime().exec(command).waitFor() == 0)
                                return;
                        } catch (IOException ignored) {
                        }
                    }
                    String browsers = System.getenv("BROWSER") == null ? "x-www-browser:firefox:iceweasel:seamonkey:mozilla:" +
                            "epiphany:konqueror:chromium:chromium-browser:google-chrome:" +
                            "www-browser:links2:elinks:links:lynx:w3m" : System.getenv("BROWSER");
                    for (String browser : browsers.split(":")) {
                        try {
                            Runtime.getRuntime().exec(new String[]{browser, uri});
                            return;
                        } catch (IOException ignored) {
                        }
                    }
                } catch (Exception ignored) {
                }
            }).start();
        }
    } catch (Exception e) {
        // should not happen
        // dump stack for debug purpose
        e.printStackTrace();
    }
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接