Monitoring battery or power supply of laptop from java - java

I am developing an application which monitors the presence of the power supply of the laptop. If there is a power cut or restoration it will intimate me over email. It will also application monitoring and controlling over email (Basically to control my laptop from my office over email). I am done with email interfacing but I have no idea on how to monitor the power supply / battery supply from java.
If any can give some pointer on this it will be of great help.
Thanks in advance ....

You have probably already solved this problem but for the others - you can do it the way Adam Crume suggests, using an already written script battstat.bat for Windows XP and higher.
Here is an example of the resulting function:
private Boolean runsOnBattery() {
try {
Process proc = Runtime.getRuntime().exec("cmd.exe /c battstat.bat");
BufferedReader stdInput = new BufferedReader(
new InputStreamReader(proc.getInputStream()));
String s;
while ((s = stdInput.readLine()) != null) {
if (s.contains("mains power")) {
return false;
} else if (s.contains("Discharging")) {
return true;
}
}
} catch (IOException ex) {
Logger.getLogger(Main.class.getName()).log(Level.SEVERE, null, ex);
}
return false;
}
Or you can simplify the script to return directly True/False or whatever fits.

On linux, you can use /proc/acpi/battery/

A quick google search turns up a java acpi library on sourceforge. Hasn't been updated since 2004 though.

Here's code that works on Windows by using the SYSTEM_POWER_STATUS structure.
Note that you need to add jna to your (Maven) dependencies for this to work.
import java.util.ArrayList;
import java.util.List;
import com.sun.jna.Native;
import com.sun.jna.Structure;
import com.sun.jna.win32.StdCallLibrary;
public interface Kernel32 extends StdCallLibrary
{
public Kernel32 INSTANCE = (Kernel32) Native.loadLibrary("Kernel32",
Kernel32.class);
public class SYSTEM_POWER_STATUS extends Structure
{
public byte ACLineStatus;
#Override
protected List<String> getFieldOrder()
{
ArrayList<String> fields = new ArrayList<String>();
fields.add("ACLineStatus");
return fields;
}
public boolean isPlugged()
{
return ACLineStatus == 1;
}
}
public int GetSystemPowerStatus(SYSTEM_POWER_STATUS result);
}
In your code call it like this:
Kernel32.SYSTEM_POWER_STATUS batteryStatus = new Kernel32.SYSTEM_POWER_STATUS();
Kernel32.INSTANCE.GetSystemPowerStatus(batteryStatus);
System.out.println(batteryStatus.isPlugged());
Result:
true if charger is plugged in false otherwise
This has been derived off BalsusC's answer.

A quick and dirty way to handle this is call a native program (via Runtime.exec(...)) and parse the output. On Windows, the native program might be VBScript that uses WMI.

Related

Any way to programmatically determine which Java language features are available on current platform?

I was wondering if there is a Java API that could tell you whether a particular language feature (e.g. "diamond" operator) is available on the current platform.
(In other words, what I'm trying to do is analogous to "browser sniffing" in JavaScript.)
This would be really handy in meta-programming (writing a Java program that generates Java source code.
The best solution I've found so far is to parse System.getProperty("java.specification.version") and check whether it's ≥ the version that introduced this feature, but I'm not 100% sure that this property is available in all JVMs (or even whether it conforms to the same syntax in all JVMs). Another minor annoyance with this approach is that you have to take the extra step of looking up which version of Java introduced the language feature you're interested in. Not a big deal, since that info is pretty easy to google, but ideally it would be nice if there was an API that could readily provide the info, for example:
code.append("Map<Integer, String> map = ");
if (javax.meta.JavaVersion.getCurrentVersion().supportsDiamond()) {
code.append("new Map<>();");
} else {
code.append("new Map<Integer, String>();");
}
Obviously there's no package named javax.meta, but I was wondering if there might already be an existing solution for this problem that's cleaner than parsing the "java.specification.version" property.
Update: I just realized that Package#getSpecificationVersion() also provides the same value as System.getProperty("java.specification.version") but is probably more reliable, because System properties are mutable. In other words, the best way to get the Java spec version is probably to call Package#getSpecificationVersion() on any "built-in" package. For example: String.class.getPackage().getSpecificationVersion()
This will give you the version of java that the system is running.
System.getProperty("java.version")
If you're running Java 9 and greater you can use:
Runtime.Version version = Runtime.version();
Java Docs
Just a note the Java versioning naming standard changed at Java 9 as well.
Java Version: 1.7, 1.8, 9, 10, 11
I don't have a solution for you to check for specific features.
A feature could be: JDK 10
Method : Optional.orElseThrow()
API : API for Creating Unmodifiable Collections
System Property : Fore example, to Disable JRE Last Usage Tracking
GC enhancement (Full parallel)
Javadoc Support : (For Multiple Stylesheets)
It Could also be a REMOVAL of feature : also in Java 10
Removal of Support for Using Old LookAndFeel
Removal of Runtime.getLocalizedInputStream and getLocalizedOutputStream Methods
And so on..
So it is hard to check or discover programmatcally if a new feature exist or of it has been removed UNLESS you know what you are looking for, it needs to to be provided by Oracle itself as a documentation, feature name and description.
If we are going to create and API for that, we must get the list first from Oracle docs, and then do required checks for each feature to discover the current version or if it is supported.
Following is an example to programmaticaly check the compiler for a specific functionality.
import java.io.IOException;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.lang.reflect.InvocationTargetException;
import java.net.URI;
import java.util.Arrays;
import javax.tools.Diagnostic;
import javax.tools.DiagnosticCollector;
import javax.tools.JavaCompiler;
import javax.tools.JavaFileObject;
import javax.tools.SimpleJavaFileObject;
import javax.tools.ToolProvider;
import javax.tools.JavaCompiler.CompilationTask;
import javax.tools.JavaFileObject.Kind;
public class CompileSourceInMemory {
public static void main(String args[]) throws IOException {
JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
DiagnosticCollector<JavaFileObject> diagnostics = new DiagnosticCollector<JavaFileObject>();
StringWriter writer = new StringWriter();
PrintWriter out = new PrintWriter(writer);
out.println("public class HelloWorld {");
out.println(" public static void main(String args[]) {");
out.println(" System.out.println(\"This is in another java file\");");
out.println(" }");
out.println("}");
out.close();
JavaFileObject file = new JavaSourceFromString("HelloWorld", writer.toString());
Iterable<? extends JavaFileObject> compilationUnits = Arrays.asList(file);
CompilationTask task = compiler.getTask(null, null, diagnostics, null, null, compilationUnits);
boolean success = task.call();
for (Diagnostic diagnostic : diagnostics.getDiagnostics()) {
System.out.println(diagnostic.getCode());
System.out.println(diagnostic.getKind());
System.out.println(diagnostic.getPosition());
System.out.println(diagnostic.getStartPosition());
System.out.println(diagnostic.getEndPosition());
System.out.println(diagnostic.getSource());
System.out.println(diagnostic.getMessage(null));
}
System.out.println("Success: " + success);
if (success) {
try {
Class.forName("HelloWorld").getDeclaredMethod("main", new Class[] { String[].class })
.invoke(null, new Object[] { null });
} catch (ClassNotFoundException e) {
System.err.println("Class not found: " + e);
} catch (NoSuchMethodException e) {
System.err.println("No such method: " + e);
} catch (IllegalAccessException e) {
System.err.println("Illegal access: " + e);
} catch (InvocationTargetException e) {
System.err.println("Invocation target: " + e);
}
}
}
}
class JavaSourceFromString extends SimpleJavaFileObject {
final String code;
JavaSourceFromString(String name, String code) {
super(URI.create("string:///" + name.replace('.','/') + Kind.SOURCE.extension),Kind.SOURCE);
this.code = code;
}
#Override
public CharSequence getCharContent(boolean ignoreEncodingErrors) {
return code;
}
}
See JDK 10 features
I just discovered another partial solution: javax.lang.model.SourceVersion. It still doesn't solve the problem entirely, but seems like a step in the right direction.
So instead of my old approach,
if (System.getProperty("java.specification.version").compareTo("1.7") >= 0)
// do something that requires Java 7
you could write:
if (SourceVersion.latestSupported().ordinal() >= SourceVersion.RELEASE_7.ordinal())
// do something that requires Java 7
(because SourceVersion has its enum constants declared in ascending order)
This class also provides the static methods isKeyword, isName, isIdentifier, which might be useful, but it was already reasonably easy to derive some of this info (e.g. Character.isJavaIdentifierPart(cp)).
Under the hood, SourceVersion also relies on reading the "java.specification.version" system property:
private static SourceVersion getLatestSupported() {
try {
String specVersion = System.getProperty("java.specification.version");
if ("1.8".equals(specVersion))
return RELEASE_8;
else if("1.7".equals(specVersion))
return RELEASE_7;
else if("1.6".equals(specVersion))
return RELEASE_6;
} catch (SecurityException se) {}
return RELEASE_5;
}
That's some smelly code right there! e.g. if someone calls System.setProperty("java.specification.version", "6.9"); then SourceVersion.latestSupported() will return RELEASE_5 ;)
I'm surprised that even Sun didn't provide a "magic" way to get the Java version directly from the VM (like the various internal "magic" operations exposed by the sun.misc package)

Both ways, java <=> python, communication using py4j

I am using py4j for communication between python and java.I am able to call python method from java side. But from python I am not able to send any object or call java method. Here is the code i have tried.
My java code:
public interface IHello {
public String sayHello();
public String sayHello(int i, String s);
// public String frompython();
}
//ExampleClientApplication.java
package py4j.examples;
import py4j.GatewayServer;
import java.io.BufferedReader;
import java.io.InputStreamReader;
public class ExampleClientApplication extends Thread {
public void run(){
System.out.println("thread is running...");
}
public static void main(String[] args) {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
GatewayServer.turnLoggingOff();
GatewayServer server = new GatewayServer();
server.start();
IHello hello = (IHello) server.getPythonServerEntryPoint(new Class[] { IHello.class });
try {
System.out.println("Please enter a string");
String str = br.readLine();
System.out.println(hello.sayHello(1, str));
} catch (Exception e) {
e.printStackTrace();
}
ExampleClientApplication t1 = new ExampleClientApplication();
t1.start();
//server.shutdown();
}
}
My python code :
class SimpleHello(object):
def sayHello(self, int_value=None, string_value=None):
print(int_value, string_value)
return "From python to {0}".format(string_value)
class Java:
implements = ["py4j.examples.IHello"]
# Make sure that the python code is started first.
# Then execute: java -cp py4j.jar
py4j.examples.SingleThreadClientApplication
from py4j.java_gateway import JavaGateway, CallbackServerParameters
simple_hello = SimpleHello()
gateway = JavaGateway(
callback_server_parameters=CallbackServerParameters(),
python_server_entry_point=simple_hello)
The send objects problem is easily solved by implementing a getter/eval method in the java interface that is implemented by python, which can then be called from java to get the variable that is requested. For an example have a look at the py4j implementation here: https://github.com/subes/invesdwin-context-python
Specifically see the get/eval method implementation here: https://github.com/subes/invesdwin-context-python/blob/master/invesdwin-context-python-parent/invesdwin-context-python-runtime-py4j/src/main/java/de/invesdwin/context/python/runtime/py4j/pool/internal/Py4jInterpreter.py
For the other way around, you would have to do same on the java gateway class and provide a get/eval method that can be called from python. The actual java code could be executed in a ScriptEngine for groovy and the result could be returned to python. (see http://docs.groovy-lang.org/1.8.9/html/groovy-jdk/javax/script/ScriptEngine.html)
Though it might be a better idea to decide about a master/slave role and only once input the parameters, then execute the code in python and retrieve the results once. Or the other way around if python should be leading. Thus you would reduce the communication overhead a lot. For a tighter integration without as much of a performance penalty as py4j incurs, you should have a look at https://github.com/mrj0/jep to directly load the python lib into the java process. Then each call is not as expensive anymore.

Java NTFS compression attribute

I need to read and modify the 'Compressed' attribute of a file on an NTFS partition from Java. I imagined something in the java.nio.file.attribute package would do it -- hell it's a complex enough package, but I can't find this attribute.
The DosFileAttributes class has getters for the classic hidden/system/readonly/archive attributes only.
I tried Files.readAttributes which allows dynamically retrieving all attributes from a particular "attribute view". Under "dos:*" there was only the same attributes that are already available from the public methods of the DosFileAttributes class. I tried "ntfs:*" and "windows:*" but they weren't accepted as valid view names.
I also tried the UserDefinedFileAttributeView, but it gave me an empty list on any file I tried.
I wondered about shelling out to the attrib command (accepting the limitation that it wouldn't work for NTFS partitions mounted under Linux or other OSes) but that doesn't seem to support the attribute either. Help?
Since this does seem to be missing from the standard Java API, I took a look at doing it myself with JNA. It's my first experience with JNA. It's not as pretty as I'd like and JNA's code seems to be sorely lacking in generics, but it's a hundred times better than mucking about with JNI and trying to set up awful cross-compilers for the different platforms needed (minimum x86 & x64 even if you target only one OS). It's the annoying compilation process that drove me from C++ to Java in the first place, and I hope never to have to return to it.
Anyway, this seems to work. Hopefully it will be useful to someone else too. It provides four public methods:
isAvailable() -- whether or not calling the other methods should work (i.e., we are on Windows and the JNA native lib loaded okay)
isCompressed(File)
setCompressed(File, boolean)
volumeSupportsFileCompression(File) -- asks Windows if the partition where a file is located supports [individual] file compression. E.g., it's true on NTFS, and false on FAT (USB sticks and so on).
Compression in the Windows API is done through a dedicated I/O control operation, and is not merely a "SetAttributes" call. If it were simpler (isomorphic with other file attributes) I'd have put the encryption attribute in there as well for completeness' sake, but anyway.
import java.io.File;
import java.io.IOException;
import com.sun.jna.Native;
import com.sun.jna.Pointer;
import com.sun.jna.ptr.IntByReference;
import com.sun.jna.ptr.ShortByReference;
import com.sun.jna.win32.StdCallLibrary;
import com.sun.jna.win32.W32APIOptions;
import com.sun.jna.platform.win32.Kernel32;
import com.sun.jna.platform.win32.WinNT.HANDLE;
public class WindowsFileOps {
private WindowsFileOps() {}
private static interface Kernel32Extra extends StdCallLibrary {
int COMPRESSION_FORMAT_NONE = 0x00000000;
int COMPRESSION_FORMAT_DEFAULT = 0x00000001;
int FSCTL_SET_COMPRESSION = 0x0009C040;
Kernel32Extra INSTANCE = (Kernel32Extra)Native.loadLibrary("kernel32",
Kernel32Extra.class, W32APIOptions.UNICODE_OPTIONS);
boolean GetVolumeInformation(
String lpRootPathName,
Pointer lpVolumeNameBuffer,
int nVolumeNameSize,
IntByReference lpVolumeSerialNumber,
IntByReference lpMaximumComponentLength,
IntByReference lpFileSystemFlags,
Pointer lpFileSystemNameBuffer,
int nFileSystemNameSize
);
}
private static Boolean isAvailable;
public static boolean isAvailable() {
if (isAvailable == null) {
try {
isAvailable = Kernel32.INSTANCE != null && Kernel32Extra.INSTANCE != null;
} catch (Throwable t) {
isAvailable = false;
}
}
return isAvailable;
}
private static String pathString(File file) {
// "\\?\" is a Windows API thing that enables paths longer than 260 chars
return "\\\\?\\" + file.getAbsolutePath();
}
private static int getAttributes(File file) throws IOException {
int attrib = Kernel32.INSTANCE.GetFileAttributes(pathString(file));
if (attrib == Kernel32.INVALID_FILE_ATTRIBUTES) {
throw new IOException("Unable to read file attributes of " + file);
}
return attrib;
}
public static boolean isCompressed(File file) throws IOException {
return (getAttributes(file) & Kernel32.FILE_ATTRIBUTE_COMPRESSED) != 0;
}
public static void setCompressed(File file, boolean compressed) throws IOException {
HANDLE hFile = Kernel32.INSTANCE.CreateFile(
pathString(file),
Kernel32.GENERIC_READ | Kernel32.GENERIC_WRITE,
Kernel32.FILE_SHARE_READ,
null,
Kernel32.OPEN_EXISTING,
0,
null);
try {
if (!Kernel32.INSTANCE.DeviceIoControl(
hFile,
Kernel32Extra.FSCTL_SET_COMPRESSION,
new ShortByReference((short)(
compressed
? Kernel32Extra.COMPRESSION_FORMAT_DEFAULT
: Kernel32Extra.COMPRESSION_FORMAT_NONE
)).getPointer(),
2,
null, 0,
new IntByReference(),
null
)) throw new IOException("Unable to alter compression attribute of " + file);
} finally {
Kernel32.INSTANCE.CloseHandle(hFile);
}
}
public static boolean volumeSupportsFileCompression(File file) throws IOException {
IntByReference flags = new IntByReference();
if (!Kernel32Extra.INSTANCE.GetVolumeInformation(
pathString(file.getAbsoluteFile().toPath().getRoot().toFile()),
null, 0,
null,
null,
flags,
null, 0
)) throw new IOException("GetVolumeInformation failure");
return (flags.getValue() & Kernel32.FILE_FILE_COMPRESSION) != 0;
}
}
Instead of DosFileAttributes try use BasicFileAttributes and check isOther() and isRegularFile() flags. That may tell you if file is compressed. If not you would have to create your own FileSystemProvider impl for NTFS or write small JNI code that will use WinAPI to read that flag for you.

How can I get the window handle (hWnd) for a Stage in JavaFX?

We're building a JavaFX application in Windows, and we want to be able to do some things to manipulate how our application appears in the Windows 7/8 taskbar. This requires modifying a Windows variable called the "Application User Model ID".
We've already managed to do exactly what we want in Swing by using JNA, and we'd like to repeat our solution in JavaFX. Unfortunately, to do this, we need to be able to retrieve the hWnd (window handle) for each window in our application. This can be done in Swing/AWT via the JNA Native.getWindowPointer() method, which works with java.awt.Window, but I can't figure out a good way to do this with a javafx.stage.Window.
Does anyone know of any way to do get hWnd for a Stage?
Here's a JavaFX2 version (uses Stage rather than Window):
private static Pointer getWindowPointer(Stage stage) {
try {
TKStage tkStage = stage.impl_getPeer();
Method getPlatformWindow = tkStage.getClass().getDeclaredMethod("getPlatformWindow" );
getPlatformWindow.setAccessible(true);
Object platformWindow = getPlatformWindow.invoke(tkStage);
Method getNativeHandle = platformWindow.getClass().getMethod( "getNativeHandle" );
getNativeHandle.setAccessible(true);
Object nativeHandle = getNativeHandle.invoke(platformWindow);
return new Pointer((Long) nativeHandle);
} catch (Throwable e) {
System.err.println("Error getting Window Pointer");
return null;
}
}
Add a dependency on JNA:
<dependency>
<groupId>net.java.dev.jna</groupId>
<artifactId>jna-platform</artifactId>
<version>5.3.1</version>
</dependency>
Then give your Stage a distinct title ("MyStage" in this example), and then get the Window ID like this:
WinDef.HWND hwnd = User32.INSTANCE.FindWindow(null, "MyStage");
long wid = Pointer.nativeValue(hwnd.getPointer());
This will work on Windows regardless of JavaFX version.
The following method shows how you can get a native window handle (hWnd) for a JavaFX Stage (or Window) and then store it in a JNA Pointer object:
private static Pointer getWindowPointer(javafx.stage.Window window) {
Pointer retval = null;
try {
Method getPeer = window.getClass().getMethod("impl_getPeer");
final Object tkStage = getPeer.invoke(window);
Method getPlatformWindow = tkStage.getClass().getDeclaredMethod("getPlatformWindow");
getPlatformWindow.setAccessible(true);
final Object platformWindow = getPlatformWindow.invoke(tkStage);
Method getNativeHandle = platformWindow.getClass().getMethod("getNativeHandle");
retval = new Pointer((Long) getNativeHandle.invoke(platformWindow));
} catch (Throwable t) {
System.err.println("Error getting Window Pointer");
t.printStackTrace();
}
return retval;
}
This solution is fragile and generally undesirable, since it uses reflection to access a bunch of private methods. But it gets the job done. Hopefully Oracle will eventually give us direct access to native window handles so we don't have to do this.
Of course, this code only works when you're running on MS Windows. Also, I've only tried it out with early release builds of JavaFX 8 (but I suspect it will work fine on JavaFX 2 as well. EDIT: looks like it doesn't work in JavaFX 2.)
The following code works for me in JavaFX 11 on Windows (I only need it there). I haven't tested it in any other version.
It's quite brittle, but manageable in my case, as I bundle the Java Runtime with the application so I always know what's underneath.
If you use Java 9 modules, you also need to open up the packages to your calling module:
--add-opens javafx.graphics/javafx.stage=com.example and --add-opens javafx.graphics/com.sun.javafx.tk.quantum=com.example
package com.example;
import com.sun.jna.Pointer;
import com.sun.jna.platform.win32.WinDef;
import javafx.stage.Stage;
import javafx.stage.Window;
import java.lang.reflect.Method;
public class FXWinUtil {
public static WinDef.HWND getNativeHandleForStage(Stage stage) {
try {
final Method getPeer = Window.class.getDeclaredMethod("getPeer", null);
getPeer.setAccessible(true);
final Object tkStage = getPeer.invoke(stage);
final Method getRawHandle = tkStage.getClass().getMethod("getRawHandle");
getRawHandle.setAccessible(true);
final Pointer pointer = new Pointer((Long) getRawHandle.invoke(tkStage));
return new WinDef.HWND(pointer);
} catch (Exception ex) {
System.err.println("Unable to determine native handle for window");
return null;
}
}
}
If you're using JNA (which is likely if you're doing hackish stuff like this), you can also profit from WinDef.HWND.
com.sun.glass.ui.Window.getWindows.get(0).getNativeWindow
//
com.sun.glass.ui.Window.getFocusedWindow.getNativeWindow
Solution for JavaFX 16, written on Kotlin (only Reflection)
fun getPointer(scene: Scene): Long {
val tkStage = SceneHelper.getPeer(scene)
val windowStage = tkStage.javaClass.getDeclaredMethod("getWindowStage")
.apply { isAccessible = true }
.invoke(tkStage)
val platformWindow = windowStage.javaClass.getDeclaredMethod("getPlatformWindow")
.apply { isAccessible = true }
.invoke(windowStage)
// Use fields 'ptr' and 'delegatePtr' instead of getNativeHandle() to avoid Platform.runLater
val ptr = Window::class.java.getDeclaredField("ptr")
.apply { isAccessible = true }[platformWindow] as Long
val delegatePtr = Window::class.java.getDeclaredField("delegatePtr")
.apply { isAccessible = true }[platformWindow] as Long
return if (delegatePtr != 0L) delegatePtr else ptr
}

Java Swing - How to double click a project file on Mac to open my application and load the file?

I have created a Mac Java Swing application, and i have set a file extension(*.pkkt) for it in the "Info.plist" file, so when double clicking that file it opens my application.
When i do that the program runs fine. Now i need to load the (*.pkkt) project in the program, but the file path is not passed as an argument to the main(...) method in Mac as happens in Windows Operating System.
After some search i found an Apple handling jar "MRJToolkitStubs" that has the MRJOpenDocumentHandler interface to handle such clicked files. I have tried using it to load that file by implementing that Interface in the main program class, but it is not working. The implemented method is never called at the program start-up.
How does this Interface run ?
------------------------------------------------- Edit: Add a Code Sample
Here is the code i am using :
public static void main( final String[] args ) {
.
.
.
MacOpenHandler macOpenHandler = new MacOpenHandler();
String projectFilePath = macOpenHandler.getProjectFilePath(); // Always Empty !!
}
class MacOpenHandler implements MRJOpenDocumentHandler {
private String projectFilePath = "";
public MacOpenHandler () {
com.apple.mrj.MRJApplicationUtils.registerOpenDocumentHandler(this) ;
}
#Override
public void handleOpenFile( File projectFile ) {
try {
if( projectFile != null ) {
projectFilePath = projectFile.getCanonicalPath();
System.out.println( projectFilePath ); // Prints the path fine.
}
} catch (IOException e) {}
}
public String getProjectFilePath() {
return projectFilePath;
}
}
As mentioned in the comment above "getProjectFilePath()" is always Empty !
On Java 9, use Desktop.setOpenFileHandler()
The proprietary com.apple.eawt packages have been removed from recent versions of Java and has been incorporated into various methods in the Desktop class. For your specific example:
import java.awt.desktop.OpenFilesHandler;
import java.awt.desktop.OpenFilesEvent;
import java.io.File;
import java.util.List;
public class MyOpenFileHandler implements OpenFilesHandler {
#Override
public void openFiles​(OpenFilesEvent e) {
for (File file: e.getFiles​()) {
// Do whatever
}
}
}
Then elsewhere, add this:
Desktop.getDesktop().setOpenFileHandler(new MyOpenFileHandler());
The OpenFilesEvent class also has a getSearchTerm() method. Say that a person used Spotlight on macOS to search for the word "StackOverflow", then decided to open up a document. With this method, can you determine that "StackOverflow" was the word they searched for, and choose to do something with that (perhaps highlight the first occurrence of the word).
You're going to want to use the Apple Java Extensions.
They should be included in any JDK that runs on Mac OS X, but the documentation is kind of hard to get. See this answer for more details.
Specifically, you'll want to make an OpenFilesHandeler.
This code snippet should work:
import com.apple.eawt.event.OpenFilesHandeler;
import com.apple.eawt.event.AppEvent;
import java.io.File;
import java.util.List;
class MacOpenHandler implements OpenFilesHandeler {
#Override
public void openFiles(AppEvent.OpenFilesEvent e) {
List<File> files = e.getFiles();
// do something
}
}
And somewhere:
import com.apple.eawt.Application;
...
MacOpenHandeler myOpenHandeler = new MacOpenHandeler();
Application.getApplication().setOpenFileHandler(myOpenHandeler);

Categories