How to Get Desktop Class Supported Under Linux

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



Leave a reply



Submit