Put a program icon depending on the platform - java

I've realized that my code has a problem with setting a program icon (instead of the java one) in different platforms. I had written this code for windows and mac:
private void putIcon() {
URL url = ClassLoader.getSystemResource("resources/icon.png");
String name = System.getProperty("os.name");
if (name.startsWith("Win")) {
Toolkit kit = Toolkit.getDefaultToolkit();
Image img = kit.createImage(url);
this.setIconImage(img);
} else {
Application.getApplication().setDockIconImage(new ImageIcon(url).getImage());
}
}
While I was testing it in mac there was not problem, but when I tried it windows I realized that won't work because that class isn't in windows:
import com.apple.eawt.Application;
What could I do to solve this issue? For what I've researched it's not possible to have some kind of "if" in the import section of the code, and if that class is there in windows it won't compile.

Check if the specified class Application can be found by using
Class.forName("com.apple.eawt.Application");
If this method does not throw a ClassNotFoundException, invoke the methods you want by using reflection only. Seems a bit hacky but it should work.
Also make sure that you are not importing the class.

Related

Why do I get "LoadLibrary failed with error 1114: a dynamic link library (DLL) initialization routine failed"?

When I run my java application program an error window appears saying that
"LoadLibrary failed with error 1114: a dynamic link library (DLL) >initialization routine failed".
I have tested my code on a different machine and it worked perfectly.The program shows a PApplet window with a map inside.However, Running the code on my laptop, the PApplet appears and all of the sudden the DLL error stops the rest from being shown.
What the problem could be and how can I fix it?
Here is the code I am trying to run. It is worth to mention that it runs successfully if I remove what's inside the setup() method.
import de.fhpotsdam.unfolding.UnfoldingMap;
import de.fhpotsdam.unfolding.providers.Google;
import de.fhpotsdam.unfolding.utils.MapUtils;
import processing.core.PApplet;
public class LifeExpectancy2 extends PApplet {
UnfoldingMap map;
public void setup()
{
size(800,600,OPENGL);
map = new UnfoldingMap (this, 50, 50, 700, 500, new Google.GoogleMapProvider());
MapUtils.createDefaultEventDispatcher (this, map);
}
public void draw()
{
}
}
I had the same issue after I installed my Netbeans to build some projects in PHP and it was fixed changing some graphics options in the control painel of my Windows 10.
Take a look on this video and see if it fixs your issue as well:
Windows 10 - Java Loadlibrary Error 1114
I hope it can be helpful!
Which Unfolding version did you download? You seem to use some Java IDE (and not Processing's one) so you need the Unfolding-for-Eclipse distribution which includes all needed native libraries (i.e. also the DLL in question).
For the records, the DLL is the native library for Windows OS to bind Java to the OpenGL API (JOGL).

Access parameters from custom URI scheme in Java application on OS X

I've successfully added a custom URI scheme in info.plist on OS X so my Java 1.7 based application (written in Netbeans) is launched whenever the user enters "myApp:SomeParameter" in their browser:
<key>CFBundleURLTypes</key>
<array>
<dict>
<key>CFBundleURLName</key>
<string>My App</string>
<key>CFBundleURLSchemes</key>
<array>
<string>myApp</string>
</array>
</dict>
</array>
I have also successfully added the corresponding registry entry for the application if installed on a Windows machine. The problem is that on the Windows platform I can easily pass on parameters (in the above case I want "SomeParameter" from the entered uri "myApp:SomeParameter"). It is simply passed on to the application main method as regular parameters, but this is not the case on OS X. I have done some research and tried this solution but it requires some Cocoa libraries and causes issues when compiled and run on Windows.
EDIT: I have tried to track down a version of AppleJavaExtensions that contains the com.apple.eawt.Application.setOpenURIHandler() but I've only found version 1.4 where it's missing. Any idea why?
Is there another way to pass parameters from a custom URI scheme to a cross platform Java application running on Mac / OS X?
EDIT 2: Please see accepted answer below, but as a side note: we successfully experimented with a possible workaround using AppleScript as a middle-tier. The script in this article can be simplified to receive the full URL with parameters, and then invoke your Java based application with the query string as normal command line parameters.
It looks like you're on the right track. Your Info.plist looks correct. You don't need to create any custom native Cocoa code, just use setOpenURIHandler(). For example:
public class AppleMenus implements com.apple.eawt.OpenURIHandler {
private MyApp myApp;
public AppleMenus(MyApp myApp) {
this.myApp = myApp;
final com.apple.eawt.Application app = com.apple.eawt.Application.getApplication();
app.setOpenURIHandler(this);
}
#Override
public void openURI(final com.apple.eawt.AppEvent.OpenURIEvent oue) {
myApp.openCustomURL(oue.getURI());
}
}
The only reason you would need AppleJavaExtensions is if you are trying to compile this code on a non-Apple environment, such as Windows. Windows won't know what OpenURIHandler is, so you will get a compile error there. AppleJavaExtensions just provides that necessary API without implementation, just for the purposes of being able to compile in these other environments.
Here, is the official latest (and probably last) version: https://developer.apple.com/legacy/library/samplecode/AppleJavaExtensions/Introduction/Intro.html
Note that your URI handler will be called in the currently running instance of you app or will first create a new instance of your app then get called. The OpenURIEvent will contain the entire URI message you send.
The following (for Java 9) will work cross platform (Windows and macOS has been tested):
import java.awt.*;
import java.awt.desktop.OpenURIEvent;
import java.awt.desktop.OpenURIHandler;
import java.net.URI;
import java.net.URISyntaxException;
public class UriLaunchedApp {
public static void main(String[] args) throws URISyntaxException {
try {
Desktop.getDesktop().setOpenURIHandler(new OpenURIHandler() {
#Override
public void openURI(OpenURIEvent e) {
System.out.println("We are maybe on macOS...");
processUri(e.getURI());
}
});
} catch (UnsupportedOperationException e) {
System.out.println("We are maybe on Windows...");
processUri(new URI(args[0]));
}
}
private static void processUri(URI uri) {
System.out.println("Do something with " + uri);
}
}
See too https://docs.oracle.com/javase/9/docs/api/java/awt/Desktop.html#setOpenURIHandler-java.awt.desktop.OpenURIHandler-.

How can I call Java applet methods with Javascript?

i've created a java applet last year for a socket connection from a web application to a local running java server. it worked fine.
since the last java updates (7 r21 i guess), i cannot access the methods within javascript anymore. Right now, i reduced the applet to a test applet (without the doPriviligedAction methods) but even this does not work anymore.
The current code is like
import java.applet.*;
public class socketApplet extends Applet {
public void init() {
System.out.println("Applet initialisiert.");
}
public void start() {
System.out.println("Applet gestartet.");
}
public void paint() {
System.out.println("Applet aktualisiert.");
}
public void stop() {
System.out.println("Applet angehalten.");
}
public void destroy() {
System.out.println("Applet beendet.");
}
public String testApplet() {
System.out.println("Applet getestet.");
return "Yep, I'm the Applet.";
}
}
Before the update i could access methods like testApplet() in javascript like this:
document.socketApplet.testApplet();
The applet is self-signed and embedded with an applet html-tag. It is starting (the java console is opening and prints the debug messages defined in the init, start and paint methods) but i cannot access the testApplet() method. The response in Javascript is "undefined" while the applet exists.
after reading a while (a few days now...) about the new security changes, i've added a manifest.txt with the following content:
Main-Class: socketApplet
Permissions: all-permissions
Codebase: *
Trusted-Library: true
No luck with or without the Trusted-Library attribute.
What do i have to do to enable the access with javascript again?
Edit:
The implementation:
<applet id="socketApplet" width="100" height="100" archive="../../socketApplet.jar" name="socketApplet" code="socketApplet" scriptable="true">
I am testing with the newest versions of Firefox and Safari on an up to date Mac OS X machine.
Edit2:
i am creating and signing the jar like this
Edit3:
Okay, now my jar worked a few times (not in a row), i got
and in the console
But most of the time it does not work. restarting the browser, clearing caches, nothing works. going to test this on another pc now (again).
Edit4:
Okay it is running on a virtual machine with windows xp and java 32bit 7u25 - on my 64bit mac just only 1 out of 30 tries.
Okay i found the source of all evil...
it had nothing to do with the applet. the confusing situation was that it worked in firefox on windows and not in firefox on the mac (same FF versions, same java versions). Safari on my mac didn't work because the plugin was disabled...
So it was a Firefox on mac problem only. I've tested different situations and the applet worked when writing the applet code above into a html page. Before, i've created the applet dynamically (what is necessary in the software):
var applet = document.createElement('applet');
applet.archive = 'socketApplet.jar';
applet.id = 'socketApplet';
applet.name = 'socketApplet';
applet.code = 'socketApplet';
applet.scriptable = 'true';
applet.width = '0';
applet.height = '0';
document.body.appendChild(applet);
It works everywhere but not in Firefox on Mac. So as a workaround i have to embed the applet in an iframe and i have to embed the iframe dynamically. that works...
var mFrame = document.createElement('iframe');
mFrame.id = 'testFrame';
mFrame.height = '200';
mFrame.width = '400';
document.body.appendChild(mFrame);
mFrame.src = 'frame.html'; // contains the applet code
Next i am going to change the html tag to the object and embed tag for IE support. Thanks for your help Andrew Thompson!
I dislike the iframe version because the access to the applet via javascript is more complex, but it seems like there is no other way around.
I am going to submit a Mozilla bug ticket for this.
https://bugzilla.mozilla.org/show_bug.cgi?id=912880
Maybe similar to this one but another situation:
https://bugzilla.mozilla.org/show_bug.cgi?id=872969

Java: CaptureDeviceManager#getDeviceList() is empty?

I am trying to print out all of the capture devices that are supported using the #getDeviceList() method in the CaptureDeviceManager class and the returned Vector has a size of 0.
Why is that? I have a webcam that works - so there should be at least one. I am running Mac OS X Lion - using JMF 2.1.1e.
Thanks!
CaptureDeviceManager.getDeviceList(Format format) does not detect devices. Instead it reads from the JMF registry which is the jmf.properties file. It searches for the jmf.properties file in the classpath.
If your JMF install has succeeded, then the classpath would have been configured to include all the relevant JMF jars and directories. The JMF install comes with a jmf.properties file included in the 'lib' folder under the JMF installation directory. This means the jmf.properties would be located by JMStudio and you would usually see the JMStudio application executing correctly. (If your JMF install is under 'C:\Program Files', then run as administrator to get around UAC)
When you create your own application to detect the devices, the problem you described above might occur. I have seen a few questions related to the same problem. This is because your application's classpath might be different and might not include the environment classpath. Check out your IDE's properties here. The problem is that CaptureDeviceManager cannot find the jmf.properties file because it is not there.
As you have found out correctly, you can copy the jmf.properties file from the JMF installation folder. It would contain the correct device list since JMF detects it during the install (Check it out just to make sure anyway).
If you want do device detection yourself, then create an empty jmf.properties file and put it somewhere in your classpath (it might throw a java.io.EOFException initially during execution but that's properly handled by the JMF classes). Then use the following code for detecting webcams...
import javax.media.*;
import java.util.*;
public static void main(String[] args) {
VFWAuto vfwObj = new VFWAuto();
Vector devices = CaptureDeviceManager.getDeviceList(null);
Enumeration deviceEnum = devices.elements();
System.out.println("Device count : " + devices.size());
while (deviceEnum.hasMoreElements()) {
CaptureDeviceInfo cdi = (CaptureDeviceInfo) deviceEnum.nextElement();
System.out.println("Device : " + cdi.getName());
}
}
The code for the VFWAuto class is given below. This is part of the JMStudio source code. You can get a good idea on how the devices are detected and recorded in the registry. Put both classes in the same package when you test. Disregard the main method in the VFWAuto class.
import com.sun.media.protocol.vfw.VFWCapture;
import java.util.*;
import javax.media.*;
public class VFWAuto {
public VFWAuto() {
Vector devices = (Vector) CaptureDeviceManager.getDeviceList(null).clone();
Enumeration enum = devices.elements();
while (enum.hasMoreElements()) {
CaptureDeviceInfo cdi = (CaptureDeviceInfo) enum.nextElement();
String name = cdi.getName();
if (name.startsWith("vfw:"))
CaptureDeviceManager.removeDevice(cdi);
}
int nDevices = 0;
for (int i = 0; i < 10; i++) {
String name = VFWCapture.capGetDriverDescriptionName(i);
if (name != null && name.length() > 1) {
System.err.println("Found device " + name);
System.err.println("Querying device. Please wait...");
com.sun.media.protocol.vfw.VFWSourceStream.autoDetect(i);
nDevices++;
}
}
}
public static void main(String [] args) {
VFWAuto a = new VFWAuto();
System.exit(0);
}
}
Assuming you are on a Windows platform and you have a working web-cam, then this code should detect the device and populate the jmf.properties file. On the next run you can also comment out the VFWAuto section and it's object references and you can see that CaptureDeviceManager reads from the jmf.properties file.
The VFWAuto class is part of jmf.jar. You can also see the DirectSoundAuto and JavaSoundAuto classes for detecting audio devices in the JMStudio sample source code. Try it out the same way as you did for VFWAuto.
My configuration was Windows 7 64 bit + JMF 2.1.1e windows performance pack + a web-cam.
I had the same issue and I solved by invoking flush() on my ObjectInputStream object.
According to the API documentation for ObjectInputStream's constructor:
The stream header containing the magic number and version number are read from the stream and verified. This method will block until the corresponding ObjectOutputStream has written and flushed the header.
This is a very important point to be aware of when trying to send objects in both directions over a socket because opening the streams in the wrong order will cause deadlock.
Consider for example what would happen if both client and server tried to construct an ObjectInputStream from a socket's input stream, prior to either constructing the corresponding ObjectOutputStream. The ObjectInputStream constructor on the client would block, waiting for the magic number and version number to arrive over the connection, while at the same time the ObjectInputStream constructor on the server side would also block for the same reason. Hence, deadlock.
Because of this, you should always make it a practice in your code to open the ObjectOutputStream and flush it first, before you open the ObjectInputStream. The ObjectOutputStream constructor will not block, and invoking flush() will force the magic number and version number to travel over the wire. If you follow this practice in both your client and server, you shouldn't have a problem with deadlock.
Credit goes to Tim Rohaly and his explanation here.
Before calling CaptureDeviceManager.getDeviceList(), the available devices must be loaded into the memory first.
You can do it manually by running JMFRegistry after installing JMF.
or do it programmatically with the help of the extension library FMJ (Free Media in Java). Here is the code:
import java.lang.reflect.Field;
import java.util.Vector;
import javax.media.*;
import javax.media.format.RGBFormat;
import net.sf.fmj.media.cdp.GlobalCaptureDevicePlugger;
public class FMJSandbox {
static {
System.setProperty("java.library.path", "D:/fmj-sf/native/win32-x86/");
try {
final Field sysPathsField = ClassLoader.class.getDeclaredField("sys_paths");
sysPathsField.setAccessible(true);
sysPathsField.set(null, null);
} catch (Exception e) {
e.printStackTrace();
}
}
public static void main(String args[]) {
GlobalCaptureDevicePlugger.addCaptureDevices();
Vector deviceInfo = CaptureDeviceManager.getDeviceList(new RGBFormat());
System.out.println(deviceInfo.size());
for (Object obj : deviceInfo ) {
System.out.println(obj);
}
}
}
Here is the output:
USB2.0 Camera : civil:\\?\usb#vid_5986&pid_02d3&mi_00#7&584a19f&0&0000#{65e8773d-8f56-11d0-a3b9-00a0c9223196}\global
RGB, -1-bit, Masks=-1:-1:-1, PixelStride=-1, LineStride=-1

Embedding a Java (.jar) file within a Mac Application

I need to have a .jar file run within my main NSWindow, how can I do this?
I have been looking at Apple's example for "JavaFrameEmbedding", and seem to be able to run it without any Java exceptions (previously I had exceptions), however I cannot see the applet. They use the JavaFrameView which is part of the JavaFrameEmbedding framework, although I can't find any documentation about this at all. This is using Lion (I have also tried on Snow Leopard without success).
Download this puppy and dig through it.
If you want to make the NSWindow in java and have the program run from there try something like this:
import com.apple.cocoa.application.*;
import com.apple.cocoa.foundation.*;
public class Test {
public static void main (String [] args) {
NSApplication nsapp = NSApplication.sharedApplication();
NSRect rect = new NSRect(500, 500, 500, 500);
NSWindow.MiniaturizableWindowMask;;
NSWindow window = new NSWindow(rect, style, NSWindow.Buffered,
false);
window.makeKeyAndOrderFront(window);
nsapp.run();
}
}

Categories