Is Desktop#browse supported on Linux platform just for Gnome desktop?
There are already several questions on SO about that issue:
- Desktop.getDesktop().browse Hangs
- Desktop and desktop.browse are supported, but browse still hangs
- Desktop browse does not work in java for Ubuntu
There is also this discussion:
https://bugs.launchpad.net/ubuntu/+source/openjdk-8/+bug/1574879
where someone says:
gnome_url_show is actually in libgnome-2-0 package
So, if the package is missing, Desktop.browse()
will fail. There are 2 solutions to fix that.
Solution 1
Install the libgnome package.
Solution 2
Execute xdg-open to open the URL, e.g.:
Runtime.getRuntime().exec(new String[]{"xdg-open", someurl});
Desktop API is not supported on the current platform
Basically, the problem is that Java Desktop integration doesn't work well on Linux.
It was designed to work good with Windows; something works on other systems, but nobody really cared to add proper support for those. Even if you install the required 'gnome libraries', the results will be poor.
I've faced the very same problem a while ago, and came up with the class below.
The goal is achieved by using system-specific commands:
KDE: kde-open
GNOME: gnome-open
Any X-server system: xdg-open
MAC: open
Windows: explorer
If none of those works, it tries the implementation provided by Java Desktop.
Because this one usually fails, it's tried as the last resort.
DesktopApi class
This class provides static methods open
, browse
and edit
.
It is tested to work on Linux (Kde and Gnome), Windows and Mac.
If you use it, please give me credit.
package net.mightypork.rpack.utils;
import java.awt.Desktop;
import java.io.File;
import java.io.IOException;
import java.net.URI;
import java.util.ArrayList;
import java.util.List;
public class DesktopApi {
public static boolean browse(URI uri) {
if (openSystemSpecific(uri.toString())) return true;
if (browseDESKTOP(uri)) return true;
return false;
}
public static boolean open(File file) {
if (openSystemSpecific(file.getPath())) return true;
if (openDESKTOP(file)) return true;
return false;
}
public static boolean edit(File file) {
// you can try something like
// runCommand("gimp", "%s", file.getPath())
// based on user preferences.
if (openSystemSpecific(file.getPath())) return true;
if (editDESKTOP(file)) return true;
return false;
}
private static boolean openSystemSpecific(String what) {
EnumOS os = getOs();
if (os.isLinux()) {
if (runCommand("kde-open", "%s", what)) return true;
if (runCommand("gnome-open", "%s", what)) return true;
if (runCommand("xdg-open", "%s", what)) return true;
}
if (os.isMac()) {
if (runCommand("open", "%s", what)) return true;
}
if (os.isWindows()) {
if (runCommand("explorer", "%s", what)) return true;
}
return false;
}
private static boolean browseDESKTOP(URI uri) {
logOut("Trying to use Desktop.getDesktop().browse() with " + uri.toString());
try {
if (!Desktop.isDesktopSupported()) {
logErr("Platform is not supported.");
return false;
}
if (!Desktop.getDesktop().isSupported(Desktop.Action.BROWSE)) {
logErr("BROWSE is not supported.");
return false;
}
Desktop.getDesktop().browse(uri);
return true;
} catch (Throwable t) {
logErr("Error using desktop browse.", t);
return false;
}
}
private static boolean openDESKTOP(File file) {
logOut("Trying to use Desktop.getDesktop().open() with " + file.toString());
try {
if (!Desktop.isDesktopSupported()) {
logErr("Platform is not supported.");
return false;
}
if (!Desktop.getDesktop().isSupported(Desktop.Action.OPEN)) {
logErr("OPEN is not supported.");
return false;
}
Desktop.getDesktop().open(file);
return true;
} catch (Throwable t) {
logErr("Error using desktop open.", t);
return false;
}
}
private static boolean editDESKTOP(File file) {
logOut("Trying to use Desktop.getDesktop().edit() with " + file);
try {
if (!Desktop.isDesktopSupported()) {
logErr("Platform is not supported.");
return false;
}
if (!Desktop.getDesktop().isSupported(Desktop.Action.EDIT)) {
logErr("EDIT is not supported.");
return false;
}
Desktop.getDesktop().edit(file);
return true;
} catch (Throwable t) {
logErr("Error using desktop edit.", t);
return false;
}
}
private static boolean runCommand(String command, String args, String file) {
logOut("Trying to exec:\n cmd = " + command + "\n args = " + args + "\n %s = " + file);
String[] parts = prepareCommand(command, args, file);
try {
Process p = Runtime.getRuntime().exec(parts);
if (p == null) return false;
try {
int retval = p.exitValue();
if (retval == 0) {
logErr("Process ended immediately.");
return false;
} else {
logErr("Process crashed.");
return false;
}
} catch (IllegalThreadStateException itse) {
logErr("Process is running.");
return true;
}
} catch (IOException e) {
logErr("Error running command.", e);
return false;
}
}
private static String[] prepareCommand(String command, String args, String file) {
List<String> parts = new ArrayList<String>();
parts.add(command);
if (args != null) {
for (String s : args.split(" ")) {
s = String.format(s, file); // put in the filename thing
parts.add(s.trim());
}
}
return parts.toArray(new String[parts.size()]);
}
private static void logErr(String msg, Throwable t) {
System.err.println(msg);
t.printStackTrace();
}
private static void logErr(String msg) {
System.err.println(msg);
}
private static void logOut(String msg) {
System.out.println(msg);
}
public static enum EnumOS {
linux, macos, solaris, unknown, windows;
public boolean isLinux() {
return this == linux || this == solaris;
}
public boolean isMac() {
return this == macos;
}
public boolean isWindows() {
return this == windows;
}
}
public static EnumOS getOs() {
String s = System.getProperty("os.name").toLowerCase();
if (s.contains("win")) {
return EnumOS.windows;
}
if (s.contains("mac")) {
return EnumOS.macos;
}
if (s.contains("solaris")) {
return EnumOS.solaris;
}
if (s.contains("sunos")) {
return EnumOS.solaris;
}
if (s.contains("linux")) {
return EnumOS.linux;
}
if (s.contains("unix")) {
return EnumOS.linux;
} else {
return EnumOS.unknown;
}
}
}
Desktop.getDesktop().browse Hangs
You are not alone. This is a bug that appears to happen in some versions of JDK 1.6 and 1.7. I haven't seen it occuring in JDK 1.8.
It can occur on Windows too and all you can do is either update the JVM or not use the Desktop class (which sucks).
Desktop.getDesktop().open(file) on Ubuntu not working
From here:
In order to use the API, you have to call java.awt.EventQueue.invokeLater() and call methods of the Desktop class from a runnable passed to the invokeLater():
void fxEventHandler() {
EQ.invokeLater(() -> {
Desktop.open(...);
});
}
Related Topics
How to Avoid Java.Net.Bindexception: Address Already in Use
How to Get Chromedriver Process Pid Using Java
How to Run Sudo Command Without Password from Java Program
Change Unix Password with Java
How to Start Using and Developing on Ubuntu Linux
Cannot Run Program "Mvn" Error=2, No Such File or Directory
Java App Behind Proxy to Use Http_Proxy Variable in Linux
A Simple Way of Embedding a Video in My Swing Gui
How Does a Jvm Process Allocate Its Memory
Equivalent of Data Protection API on Linux
Hadoop Mapper Is Failing Because of "Container Killed by the Applicationmaster"
Kafka - Broker: Group Coordinator Not Available
Java 8 with Jetty on Linux Memory Issue
Installer/Packager for a Java Application for Ubuntu and Suse
Why Parallel Execution on Java Compile Take Linear Growth in Time
Conversion to Dalvik Format Failed: Unable to Execute Dex: Java Heap Space