Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Pass Parameters to JavaFx Application by double-click on file

Tags:

macos

javafx

I created a JavaFX application, deployed the .app file and it works fine. I then set the operative system to open all the files with a specific extension with my application. My problem is that when I double-click on a file I get my application to open, but I don't know which is the file that opened it.

I tried to check the application parameters with the function getParameters().getRaw() but it always returns an empty List.

Does anybody know how to retrieve the path to the file that opened the application?

like image 902
u09 Avatar asked Mar 17 '15 14:03

u09


Video Answer


2 Answers

I've been having the same problem on OS X for quite a while now, and the accepted answer didn't work for me. After much Googling, I finally found a solution at http://permalink.gmane.org/gmane.comp.java.openjdk.openjfx.devel/10370.

In summary, I needed to use a com.sun API in order to get it to work. I've included some sample code below:

public class MyApp extends Application {
    public MyApp() {
        com.sun.glass.ui.Application glassApp = com.sun.glass.ui.Application.GetApplication();
        glassApp.setEventHandler(new com.sun.glass.ui.Application.EventHandler() {
            @Override
            public void handleOpenFilesAction(com.sun.glass.ui.Application app, long time, String[] filenames) {
                super.handleOpenFilesAction(app, time, filenames);
                // Do what ever you need to open your files here
            }
        });
    }

    // Standard JavaFX initialisation follows
}

This should be considered a temporary solution until a proper APIs are implemented to handle file opening. Hopefully this answer helps someone who can't get the accepted answer to work.

Note: Java is not a language I use often (I use Scala and ScalaFX for my application), so I apologise for any syntax errors in the code.

like image 90
Benedict Lee Avatar answered Oct 23 '22 18:10

Benedict Lee


I finally found a way to solve this.

To answer this I created a Sample Application that is composed by three classes:

Launcher
MyApp
Handler_OpenFile

MyApp is the class extending the javafx.application.Application class, the Handler_OpenFile is used to handle the double-click event and finally the Launcher is the one containing the main.

Launcher.java: this class MUST exist because if the main was defined inside the class that extends the javafx.application.Application the OpenFilesEvent won't work properly (more precisely the OpenFilesEvent will be fired only if the application was already opened).

public class Launcher {
    public static void main(String[] args) {
        if (System.getProperty("os.name").contains("OS X")){
            com.apple.eawt.Application a = com.apple.eawt.Application.getApplication();
            Handler_OpenFile h_open = new Handler_OpenFile();
            a.setOpenFileHandler(h_open);
            Application.launch(Main.class, args);
        }
    }
}

Handler_OpenFile.java: this class defines a static variable that stores the value of the File that opened the application. This isn't probably the best solution but it's the only way I could make it work for now.

public class Handler_OpenFile implements OpenFilesHandler {
    public static File file = null;

    @Override
    public void openFiles(OpenFilesEvent e) {
        for (File file : e.getFiles()){
            this.file = file;      
        }
    }
}

MyApp.java: this class will be able to access the static value assigned in the Handler_OpenFile class and retrieve the opening file's absolute path.

public class MyApp extends Application {
    @Override
    public void start(Stage primaryStage) {

        Logger logger = Logger.getLogger("log");  
        FileHandler fh;  

        try {  
            // This block configure the logger with handler and formatter  
            fh = new FileHandler("../Logfile.log");  
            logger.addHandler(fh);
            SimpleFormatter formatter = new SimpleFormatter();  
            fh.setFormatter(formatter);  

            // the following statement is used to log any messages  
            logger.info("Application launched from: " + Handler_OpenFile.file.getAbsolutePath());  

        } catch (SecurityException | IOException exception) {  
            exception.printStackTrace();  
        } 


        try {
            BorderPane root = new BorderPane();
            Scene scene = new Scene(root,400,400);
            primaryStage.setScene(scene);
            primaryStage.show();
        } catch(Exception e) {
            e.printStackTrace();
        }
    }
}

finally in the build.xml file that creates your bundle you will have to add the file association (in this example with files with a .zzz extension):

<fx:info title="Sample" vendor="me">
    <fx:association extension="zzz" description="Sample Source"/>
</fx:info>

this will work only with the last update of Java(8u40): documentation at this link. For previous versions you will have to change the info.plist manually inside your bundle like it is said in the Apple Java Extensions documentation.

like image 20
u09 Avatar answered Oct 23 '22 17:10

u09