I'm a Java developer and I have a new question. I want to open a file with another program. I can do it easily with the java.awt.Desktop class with this code:
public static void open(File document) throws IOException {
Desktop dt = Desktop.getDesktop();
dt.open(document);
}
But is there a way to choose which program it uses to open the file? My program is only for Ubuntu. I want a list with all regular programs that can open that file (all options you see with a right click on the file). And if it is an executable file it should just execute. Is this possible with Java? And if it isn't, Is it possible with C++?
It's possible, but probably not as easy as using the Desktop API, as that probably just calls xdg-open under the hood.
As the Desktop API almost certainly calls xdg-open under the hood (as most well-designed programs would do), you may be able to achieve the effect you desire by setting your desktop up such that xdg-open does the right thing for you.
If that's not sufficient, xdg-open uses platform tools to do its work, falling back to xdg-mime. This reads .desktop files. You can probably do the same...
Related
I have created an ImageViewer using javafx for browsing and editing images. This appn provides an open menu to select image files to be browsed. I converted the .jar file into .exe file. In properties of one image file I changed the option "open with" so that the image now by default opens using this ImageViewer. But when I double click the image, appn ImageViewer launches and doea nothing as theres no coding for such things. The only way to view image is to use the "open menu". But I want the functionality that on clicking of the image, the appn ImageViewer launches and displays the image. Is there any way of doing this?
To answer your question: Yes, there is a way to do this since we know other applications can do it - we just have to identify what it is.
I have done something similar before, so allow me to walk you through my thinking regarding how to find the answer and then I think it will be clear.
Consider the problem - you have an operating system trying to talk to an application such that it will tell the app which file to open. Logically we must conclude that the system must send the app a path to that file.
Now, how would the communication take place? Let's think about setting default programs - are there any limitations there or can you ask any program to open any kind of file? If you experiment a bit you'll find that there are no restrictions - you can ask any program to open any file (not saying it will work correctly, but it can be done). So what does that tell us? It means the system has no idea which programs are the "correct" ones to open files and this suggests there is no registration mechanism where you would have to say to the system "Hey, I can open this kind of file".
So, if any program can open any file and the system does not maintain a registry of programs that can open files how would you think it would talk to a program to communicate the file path it should open? Well, the simplest most generic way would seem to be with command line arguments. This way all the system does is invoke the application and pass an argument containing the file path.
When you define your main method: public static void main(String[] args){...} the "args" parameter is where the command line arguments are being passed to your program. If you write some log statements and/or System.out statements to dump the contents of the args I bet you'll find that the file path is being passed this way.
Once you confirm that you can obtain the file path through the args then you just have to write your file reading logic such that is uses the argument passed in by the system to find and read the file contents.
I have a Java application that is designed to run on removable drives. I would like to add a button to allow the user to safely remove the drive the program runs on as USB Disk Ejector allows. However, I'm not sure how to achieve this (code wise) as the drive cannot be ejected if the program is running from it. I know that this program is open source, but I don't know where to find the code I am looking for and it isn't written in a language I have learnt.
I would therefore very much appreciate it if somebody could help me work out how to achieve this functionality in my Java application. Obviously I don't want to just copy, but the only thing I know at the minute is I have to pass control over to some sort of temporary script that is not on the drive I wish to eject.
Thanks in advance
As far as I know, it is not possible to implement this in pure Java as operations such as ejecting/unmounting drives are operating system-specific and not included in the default Java library which usually only supports the lowest common denominator. You need to execute some platform-specific code either by executing a script/batch file or by running native code written e.g. in C using Java's JNI mechanism.
You're right that you will need to run the application from another drive. I would follow the Java Web Start CD Install guide, which should work just as well for a USB drive or any other media as it does for CDs.
You would need to make your application a Java Web Start application. It's actually much easier than it sounds; your .jar does not need to change, you just create a small XML file with a .jnlp extension and place it next to the .jar file. Information on Java Web Start and JNLP files can be found in the tutorial and in the links at the bottom of that page.
Your external executable which performs the safe removal can be included in your application .jar file. You can copy it from your .jar to a temporary file in order to run it:
Path safeRemovalProgram = Files.createTempFile(null, ".exe");
try (InputStream stream =
MyApp.class.getResourceAsStream("saferemoval.exe")) {
Files.copy(stream, safeRemovalProgram,
StandardCopyOption.REPLACE_EXISTING);
}
safeRemovalProgram.toFile().setExecutable(true);
ProcessBuilder builder =
new ProcessBuilder(safeRemovalProgram.toString());
builder.redirectOutput(ProcessBuilder.Redirect.INHERIT);
Process safeRemovalProcess = builder.start();
For whatever reason, I sometimes need to find the current user's My Documents folder on Windows in a Java program to read some files. But as far as I can tell, there is no way to do it that isn't severely flawed.
The first wrong way: System.getProperty("user.home");
Why it won't work:
It only returns the \username\ folder; I'd need to add "\Documents\" on to the end to get the Documents folder... and that only works in English.
Sun bugs 6519127 and 4787931. Java finds the user home folder on Windows by reading a deprecated registry key* to find the Desktop then taking the parent; this method has multiple known problems that will easily cause a completely wrong folder to be returned. The bugs are 3.75 years and 8 years old with no fix.
The second wrong way: Using a registry-reading program to get the Personal folder of the user, which is My Documents (but i18n'd).
Why it won't work:
While it fixes the English-only problem, it's still using the same deprecated registry area, so the bugs still apply to it.
The deprecated registry key says to use a native call (SHGetKnownFolderPath) which I obviously can't do from Java.
The third wrong way:
JFileChooser fr = new JFileChooser();
FileSystemView fw = fr.getFileSystemView();
File documents = fw.getDefaultDirectory();
Why it won't work: It works great!
Except when it doesn't. While I had a program that used this open and running in the background, I opened a DirectX game (Fallout: New Vegas). The Java program immediately terminated with no stack trace. Always reproducible (for me on that game, and who knows what else). Couldn't find a Sun bug#.
So is there any method to find a user's Documents folder, on Windows, from Java, that doesn't have known problems?
(This is a nice big question.)
*(The key is "HKCU\Software\Microsoft\Windows\CurrentVersion\Explorer\Shell Folders")
There's no pure java way to do it, but you could use the JNA wrapper over JNI to do it without having to write any native code yourself. There's a good example of how to get the Documents folder on Windows halfway down the responses at:
What is the best way to find the users home directory in Java?
A time consuming, but reliable way of finding the 'Documents' folder of a windows user: Make your java app execute a bat script that uses Reg.exe (a windows system file) to find the value of the reg key which has the path in it. Then use a pipeline in the same bat file to send that data to the 'findstr' function which windows command prompt has. Use another pipeline to output the returned value to a text file. Then, simply make your java app read that text file, and delete it once its done :) Worked well enough for me.
Code for the bat file:
# echo off
Title Find Documents Folder
Reg Query "HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Explorer\Shell Folders" |findstr "Personal">>DocPath.dat
exit
There is a custom Java API that someone built (their website no longer works), but there code remains on Google Code:
http://winfoldersjava.googlecode.com/files/WinFoldersJava_1.1.zip
There are two DLL's that need to be referenced, one for each architecture(x86 and x64).
user.home is not "my documents", but users home folder, like on Unix ~/.
To get to "My documents" you can use System.getProperty("user.home")+"\Documents"; irrespective of the language system. Try it.
I know the following things, and was wondering if they can be combined to make Java use jump-lists in Windows:
Windows displays Jump-Lists for supporting programs when a taskbar icon is right-clicked
C++, C#, F#, and VB support this natively (as shown here)
Java can import native capabilities using the JNA (as shown here)
Anybody have experience they can lend to help me create a jump-list for a Java app?
The J7Goodies library won't work, as it no longer exists.
The word "natively" is overstating the case a bit. WPF provides jump list support. That's not the same as C# providing it. (For Windows Forms people there's the Code Pack which is a set of managed wrappers.) And MFC provides jump list support which is also not the same as C++ providing it. Anyway, there are two things going on here. One is adding files you opened recently to that jumplist, which under some circumstances you can get for free. The other is adding arbitrary files (typically starting point templates etc) to the jumplist.
To add a file to the recent/frequent list, you call SHAddToRecentDocs, though you may not have to if, for example, you use the Common File Dialog control to open files, and/or the user double-clicks files to launch your app and open them (you have the file type registered.) Lots of folks suggest calling it anyway to be on the safe side. To add any old thing to the jumplist see http://msdn.microsoft.com/en-us/library/dd378402(v=VS.85).aspx.
How to call those from Java, I forget, but I hope they get you started.
There is a Java library providing the new Windows 7 features for Java. It's called J7Goodies by Strix Code. You can create your own jump lists with it.
I am displaying a list of files; i.e. xls, doc, pdf, odt etc., in my Java application (Eclipse RCP). When the user clicks on the file, I want to launch the appropriate (according to what the OS thinks) native application, just like it happens in Windows Explorer or the Finder.
And while I am here: It would be nice to also display the same icons that Finder or Explorer use for the different file types.
Is there a library or Eclipse plugin for this?
What you want is java.awt.Desktop:
Desktop.getDesktop().open( file );
I have found an API in Eclipse's SWT now that seems to do the trick:
org.eclipse.swt.program.Program "provides access to facilities for discovering operating system specific aspects of external program launching."
It has methods to find the program for a given file extension, get the program's icon, and even launch the program.
Sounds like you're after the Java Activation Framework ("JAF"). This API lets you determine what files are and what actions you can do on them. Or alternatively the Java Desktop Integration Component ("JDIC"). JDIC allows you to create and no doubt query file associations.
Both projects seem to be in a semi-abandoned state howeer (sigh). But that's par for the course for Sun these days. Only other thing I know of is some Windows specific third party library that's based on JNI called Winpack. It does a bunch of other things too.
You can get the associated icon using the FileSystemView class (Java 1.4+).