25

I have encountered this error:

java.lang.UnsupportedOperationException: Desktop API is not supported on the current platform

I would open a file from my java application. I use this method:

Desktop.getDesktop().open(new File(report.html"));

How can i solve this problem?

Ahmed Ashour
  • 5,179
  • 10
  • 35
  • 56
user2520969
  • 1,389
  • 6
  • 20
  • 30

4 Answers4

57

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;
        }
    }
}
sbk
  • 9,212
  • 4
  • 32
  • 40
MightyPork
  • 18,270
  • 10
  • 79
  • 133
  • 1
    Altough installing libgnome2-0 fix it, we, as developers, have to workaround those things. Thank you! :-) – Jorge Fuentes González May 15 '14 at 13:56
  • @MightyPork Good efforts. Keep it up. +1 for *The goal is achieved by using system-specific commands*. – OO7 Nov 19 '14 at 10:52
  • 1
    An improved version of MightyPork's class is available at https://github.com/jjYBdx4IL/github-utils/blob/master/src/main/java/com/github/jjYBdx4IL/utils/awt/Desktop.java. Feel free to contribute improvements. – user1050755 Feb 19 '16 at 13:28
  • It was moved to https://github.com/jjYBdx4IL/misc/blob/master/swing-utils/src/main/java/com/github/jjYBdx4IL/utils/awt/Desktop.java – xeruf Jan 09 '19 at 17:24
  • @MightyPork have you considered wrapping this up as a library and distributing via bintray or similar? It'd be really useful for multiple projects to just be able to pull this in via a dependency. I'm happy to do so if you like, but since it's not my code I wouldn't want to without permission. – Michael Berry Apr 03 '19 at 16:30
  • @MichaelBerry do you realize this post is six years old? I no longer even work with Java! Feel free to do whatever you want with it – MightyPork Apr 05 '19 at 13:30
  • @MightyPork I did, but some of us poor sods still work with Java desktop apps ;) Thanks for that, I may package it up in due course. – Michael Berry Apr 05 '19 at 13:45
16

I am using Ubuntu 12.04 LTS 64-bit with Oracle jdk1.6.0_45 and was having the same problem. I’m running gnome-classic as the desktop instead of Unity. This is what worked for me:

sudo apt-get install libgnome2-0

After installing this package I restarted my Java Swing app and Desktop.getDesktop().open(new File("myfile")); worked just fine.

mpromonet
  • 11,326
  • 43
  • 62
  • 91
John
  • 349
  • 3
  • 5
7

The Desktop class is not supported on all systems.

From the Java Swing tutorial How to Integrate with the Desktop Class:

Use the isDesktopSupported() method to determine whether the Desktop API is available. On the Solaris Operating System and the Linux platform, this API is dependent on Gnome libraries. If those libraries are unavailable, this method will return false. After determining that the Desktop API is supported, that is, the isDesktopSupported() returns true, the application can retrieve a Desktop instance using the static method getDesktop().

In any case, it would be best to provide an alternative way to open a file if there is no support for Desktop.

Modus Tollens
  • 5,083
  • 3
  • 38
  • 46
1

Support varies between implementations on the various JDKs. I encountered the "UnsupportedOperationException" using OpenJDK 1.7.0. Switching to the Oracle JDK 1.7 worked.

Where practical, you may be able to switch JDKs or suggest that your users switch JDKs to enable a certain feature.

Mark McDonald
  • 7,571
  • 6
  • 46
  • 53