Java: way to completely disable any Swing unwanted beeps? - java

I am working on a fairly complex Java application using Swing.
On some occasions there are unwanted beeps without any user intervention. No crash, application keeps working fine, I'm respecting the EDT rules etc.
Yet in some cases a beep can be heard: I may be doing something silly triggering that beep but in any case it s not a user action for it can happen upon importing data, when the user is away.
Is it possible, for a Java application that should never ever emit any sound to configure it, say by setting a property for the whole application that says: "dont' ever emit a beep"?
I ve been Googling for that issue and I ve found message by people having the same issue but no answer: all I found was some hack saying that there was a known issue with JEditorPane and that using a putProperty("IgnoreCharsetDirective", Boolean.TRUE) was helpful to make unwanted beeps happen less often. Yet information is very scarce on the subject.
It s a real issue because the application is used in an environment where the sound is needed on the computer, but this Java application emitting noise is unacceptable.

Your problem is discussed on the Java Forum:
// Write a custom toolkit
public class MyToolkit extends sun.awt.windows.WToolkit
{
public void beep() {
}
}
// Set this property
System.setProperty("awt.toolkit", "MyPackage.MyToolkit");
NOTE: The use of this workaround is discouraged. You should still try to find the root of the problem.
Edit: Removed a link, since the thread on Java Forum is now offline.

In Swing you need to override the LookAndFeel as follows:
UIManager.setLookAndFeel(new NimbusLookAndFeel() {
#Override
public void provideErrorFeedback(Component component) {
// Your beep decision goes here
// You want error feedback
super.provideErrorFeedback(component);
}
});
Typically your beep decision would reference some kind of external configuration/preferences flag for your application.

Related

How to unregister app with DJISDKManager and SDKManagerCallback correctly with Mobile-SDK-Android?

Environment
gradle
implementation 'com.dji:dji-sdk:4.6'
compileOnly 'com.dji:dji-sdk-provided:4.6'
Application class (new Helper setup)
public class DJISampleApplication extends Application {
#Override protected void attachBaseContext(Context paramContext) {
super.attachBaseContext(paramContext);
Helper.install(this);
}
...
}
MainActivity (start SDK registration)
AsyncTask.execute(() -> DJISDKManager.getInstance()
.registerApp(getActivity(), new DJISDKManager.SDKManagerCallback() {
#Override public void onRegister(DJIError djiError) {
if (djiError == DJISDKError.REGISTRATION_SUCCESS) {
DJISDKManager.getInstance().startConnectionToProduct();
}
}
#Override public void onProductDisconnect() {}
#Override public void onProductConnect(BaseProduct baseProduct) {}
#Override public void onComponentChange(BaseProduct.ComponentKey componentKey, BaseComponent oldComponent, BaseComponent newComponent) {}
})
);
Problem
After calling 'registerApp' from the DJISDKManager instance, everything works as expected. If you back out of the application, the DJISDKManager or other DJI related classes, do not respect the Activity/Fragment lifecycles.
The first (and more obvious) issues that I noticed is that DJISDKManager keeps polling for a location. The system bar location icon never goes away, which is telling me that something is still running from the DJI SDK setup. I am not even sure why it is polling for a location but I assume it has something to do with registering the app.
Taking a deeper look using the Android Profiler tool in Android Studio, I can confirm that DJI related threads are continuously running. This happens until the Android OS (which I am mainly testing on v8.1.0 using a Pixel XL). Below is a screenshot that shows SwUdpService (located in dji.midware.sockets.P3) that is always running. You will also notice DjiExecutor, which happens every min or so. Keep in mind, this is all happening while the app is in the background. If you would force close the app, all of this goes away including the location icon.
Extra Info
I have tried a bunch of different tests but mainly have been testing DJI-SDK 4.5.1 and 4.6. Going back to an earlier SDK is not an option due to the new drone support. Please note, I kept my code very minimal in my tests and in this post so I could exactly pinpoint what code triggers the background threads that never stop.
DJISDKManager provides a few methods of interest but does not work as expected.
DJISDKManager.getInstance().destroy();
A destroy method, which in every scenario that I tested just crashes the app. It seems that it kills all of the SDK references but then some code still trying to run cannot find classes initially setup from the Helper.class throws exceptions and crashes the app.
DJISDKManager.getInstance().stopConnectionToProduct();
The stopConnectionToProduct does not do what I need. I am pretty sure this is more to stop receiving callbacks for product changes but in my testing did not really change any behavior. In fact, startConnectionToProduct does not seem to be needed anymore. Maybe these are both old methods that should be deprecated?
As we all know, the DJI SDK is very limited for obvious reasons. It seems to me that there is not 'unregisterApp' for the SDK and no public way to correctly control these DJI threads and respect the Android lifecycle. I did notice that the Android SDK sample that DJI provides behaves the same way. I tested both 4.5.1 and 4.6 branches on their repo located here: https://github.com/dji-sdk/Mobile-SDK-Android
If you test the DJI GO app, they correctly handle the Android lifecycle and from what I tell there are no threads continuously running in the background.
What I Need
I am quite new to DJI SDK development but have been developing Android applications for a long time. I know the DJI SDK has changed a lot on how you set things up, control different managers, etc. I mainly want to confirm I am not overlooking something. If I am indeed not overlooking the obvious, does anyone have a solution?
It would be awesome if we had more control over how our apps initialize the DJISDKManager, register or app, and handle callbacks/listeners. Right now its setup for a "hail mary" register function that has one callback that does too much. The fact that DJISDKManager is already a static instance and has no public control methods, it seems impossible to efficiently use the SDK.
I would love to be able to properly setup DJISDKManager as a lifecycle-aware component. I have even done some testing with manager helper class that implements LifecycleObserver, but lacking any way to stop DJI's services/threads/etc, it's pointless to use. In this LifecycleObserver class, I have even tried setting the callback to null onPause and recreate a new callback/register app onResume. This changes no behavior.
Thanks for reading :)

Switching to fullscreen crashes application

Introduction
I’m attempting to switch my application from windowed to fullscreen. Earlier this would have been as easy as making use of LibGDX’s setDisplayMode(Display), as well as the same library’s getDesktopDisplayMode(). Unfortunately, some things have changed.
Research
As of LibGDX 1.8.0—inside the Graphics—what was previously known as setDisplayMode(DisplayMode) has been renamed to setFullScreenMode(DisplayMode), as well as what was previously known as getDesktopDisplayMode() has been renamed to getDisplayMode().
By then, one might think, that using the renamed methods in the same way as one previously would to switch from windowed to fullscreen would work just as fine:
// Tabulator key triggers change from windowed to fullscreen
// The application works fine until that of pressing the tabulator key
if(Gdx.input.isKeyJustPressed(Keys.TAB))
Gdx.graphics.setFullscreenMode(Gdx.graphics.getDisplayMode());
This doesn’t work fine by any means. As a matter of fact, the application hangs followed by crashing upon pressing the tabulator key.
It’s worth to notice that the setFullscreenMode(Display)—according to the documentation—returns a boolean depending on whether or not the operation was successful. In this case, if you were to put it inside a print statement, you can clearly tell it never returns: even should you let the application be for a while.
Moreover
I took a good look around the web—in vain—searching for possible causes of as to why this might be happening. Looking at the release notes of 1.8.0, it truly seems as though all that needs be done is switch from using the previous methods contained by the library to the new ones.
Question
Does anyone have any insight on as to why the application crashes upon pressing the tabulator key—granted the code following it as shown above is present? Perhas someone could at the very least point me in the right direction?
There’s a fair chance what I’ve concluded is missing out on some important facts.
Solution
It turns out I’ve managed to be slightly silly!
Background
Whenever I create applications—especially games—even though I use libraries such as LibGDX, I like to go ahead and create myself a separate thread for handling the game logic. This yields me more control over the application as a whole—whether it be tick extremely frequently whilst rendering more seldom, or the other way around.
By the way of my logic, the provided code from the question...
if(Gdx.input.isKeyJustPressed(Keys.TAB))
Gdx.graphics.setFullscreenMode(Gdx.graphics.getDisplayMode());
... I decided to put inside the tick method. Since that’s inside a separate thread, LibGDX probably felt a little left out.
Moreover
From my understanding, LibGDX handles all its logic inside the ApplicationAdapter’s render method. That’s where it evaluates all of the user’s actions and makes sure they don’t collide with other things taking place to its own various different components.
For the aforementioned reasons—when I decided to put the “fullscreen logic” inside a separate thread, LibGDX crashed. Oh well, at least it works now—That is, by putting the aforementioned code inside the LibGDX’s ApplicationHandler’s render method!

Why Is .headless Defaulted To True?

Question Setup
There are a few moving parts to this question, so I will try to do my best to replicate the issue in its simplest form.
I am attempting to add a TrayIcon to a SystemTray. This is typically a very simple objective on operating systems ("platforms") that support the call (this will play an integral part in a few moments).
I am programming for and on a Windows machine, presently (this is not a question about interoperability).
Here's the logic behind the code I've got that works:
public class SomeClass {
public static void main(String[] args) {
if(SystemTray.isSupported()) {
// DO SOMETHING TO ADD AN ICON
}
}
}
With all of its inclusions, this works. However, what I am really after, is the ability to inject the SystemTray instance with it's icon already "ready to go".
That code looks something a little more like this:
public class SomeClass extends NecessarySpringExtension {
private #Setter(onMethod=#_#Resource(name="SystemTrayControl"))) SystemTrayControl systemTrayControl;
// The above uses Lombok, as well.
public static void main(String[] args) {
// DO SOME RELATED STUFF like setting the configurations for
// for the application
}
}
The resource returns an instance (#Bean) of the SystemTrayControl class which, itself, makes a call to SystemTray; however, now, SystemTray is no longer supported (see some explanation in the The Question section, below).
Some Change Detail
Here's a snippet of some of that code (obviously, I've got my head submerged in the issue. Let me know if the context needs expanding. My belief is the following should be enough code to give you a sense of the structure):
SystemTrayControl Class:
#PostConstruct
public void showIcon() {
if (SystemTray.isSupported()) {
val tray = SystemTray.getSystemTray(); ....
Resource Class:
#Configuration
public class BeansForNeeds {
#Bean
public SystemTrayControl systemTrayControl() {
return new SystemTrayControl():
} ....
For the sake of more context: if I remove the condition seen in the SystemTrayControl class , I get a HeadlessException (which I've done a bit of reading on).
The Question
The issue stems from that fact that when utilizing a SpringApplicationBuilder in your program, the .headless property defaults to true. The javadoc states:
Sets if the application is headless and should not instantiate AWT.
Defaults to true to prevent java icons appearing
If I manually set the property to false, then the application runs well; however, I am always a bit "shaky" overwriting default behavior, particular if the language of "prevents" x, y, or z makes into the mix.
So, the question is:
Why is the property defaulted to true? What are the side effects of allowing the behavior prohibited by .headless? What's it got against AWT?
Once upon a time, pulling in the AWT classes (and native stuff) on a true headless box like Unix without X would cause runtime exceptions and other nasty OS level failures. And the errors would only happen once the classes were loaded, so it could be slightly non-deterministic.
This was with Java 6 or so, I recall.Things may have changed since then. And I suppose it is important that it was a problem only for the AIX Java, which is a clean-room Java that is not based on the Sun reference implementation. It wasn't strictly a bug, though, because the reference implementations just escaped the same problem by mistake when I looked at the code for each.
In my case, we had to be careful in some startup code to not accidentally use a handy utility class if it touched AWT, because then all of it would be pulled in, and fall over as it ran into missing native UI. This would never happen on Windows, where a lot of development took place. But once deployed on a true headless AIX box the app would fail hard with a runtime exception that bubbled right up to the user.
This is because we had "client" code (that was, ostensibly, headless and did not rely on the any UI code) and "UI" code (that knew how to interact with a command line or a full Swing GUI.) The client code was changed such that it pulled in some handy utility class (I forget which one) but this caused the VM to pull in some other classes, which pulled in AWT, which hit some native code expecting there to be a native UI of some sort.
Since the AIX box had no X, these native components were not there, and the whole thing fell apart with a translated native/runtime exception.
So, not only did we have to run the VM headless, we had to make sure our code did not accidentally reference any AWT code, either directly or indirectly.
I'd want to do more research to see how this scenario interacts with the property discussed here, but the key takeaway for me is that cross-platform means cross-platform! And "headless" can mean something very specific on different platforms.

Debugging UI and pause when a key is pressed

I'm really no debugging expert and lately I came across a problem which hopefully has an easy solution. When I test and debug the Mathematica plugin for IDEA, I write some code, build it and run it in a sandbox IDEA.
For those who are not familiar with writing plugins for IDEA: The main problem is, that all the UI code is already there because it comes with IDEA. My plugin only implements specific interfaces which are required to make IDEA understand the Mathematica language. Therefore, setting a breakpoint or throwing something in an onClickListener like suggested by #Jeroen is not possible, because I virtually haven't written any single line of UI code*.
Now I had the situation that everything works fine, but when I cancel a specific action, something weird happens. I have no idea which specific method (it is none of mine!) is called at the moment when I press Esc to cancel this action. The current point is very likely deep inside the sources of IDEA which I have and which I can navigate with the debugger!.
Question: What is the easiest way in Java to make the debugger break, wherever it might be when I press Esc in the UI-program I currently debug?
*This is not entirely true, but for the sake of a general solution I would like to think of it that way.
As discussed in this question, you can create your own subclass of EventQueue which inspects events, and create a place in the code where you can set your break point and only catch certain kinds of events. It might look something like this:
EventQueue eventQueue = Toolkit.getDefaultToolkit().getSystemEventQueue();
eventQueue.push(new EventQueue(){
public void postEvent(AWTEvent theEvent) {
if(theEvent instanceof KeyEvent){
KeyEvent kEvent = (KeyEvent)theEvent;
if(kEvent.getKeyCode() == KeyEvent.VK_ESCAPE){
System.out.println("escape pressed, set breakpoint here");
}
}
super.postEvent(theEvent);
}
});
Then when you hit that breakpoint, you can step into the super.postEvent() call and see where it goes, which component(s) receive it, and when they begin to interact with some part of your code. Be forewarned that it may be a long slog, though -- AWT/Swing event dispatching can get pretty complex.
If you are working in (or can port to) Netbeans you can use their visual debugger which is specifically designed for these GUI-centric issues. It can direct you to specific source code when you interact with a GUI element, so it should be able to point you to the mystery code that is run when you click escape. I believe that other IDEs have similar features, but Netbeans is the only one I know of off the top of my head.

How can I use Java to read/draw/interact with another Java window/applet

I am interested in writing a Java program which does the following.
Attach to a currently running Swing window or applet, running in another JVM
Alternatively, load a Java application so as to be able to do the above
Read colors from the window
Send mouse and keyboard events to the window
I am hoping to make some sort of testing and automation tool that interacts with GUIs directly.
I am looking for some advice on how to accomplish any and all of the steps above. Thanks in advance.
It's not going to be so easy to capture the output of a another process - it will be simplest if your test app launches directly the swing app, in the same java VM.
You can then call paint(Graphics g) on the JFrame, passing the component an off screen graphics (BufferedImage - details here.) You can send input events to the AWT event queue via EventQueue.postEvent(AWTEvent) - this can be used to simulate AWT input.
However, have you surveyed the existing test frameworks out there? FEST has a test framework specifically for manipulating and verifying UI. There is also abbot, older by favored by some. There are also test frameworks that concentrate on function and state rather than screen grabs and input events. These are not better/worse, but complementary.
State UI testing includes SwingUnit, and UISpec4J.
There are a lot of good frameworks out there, so it might pay to do a little research before building yet another one!
EDIT:
To launch an application, instead of running
java -cp ... a.b.c.AppToTest
You run
java -cp ... TestWrapper AppToTest
and implement TestWrapper like this
public class TestWrapper {
/* args[0] - class to launch. Remainder of args passed to launched app.*/
public static void main(String[] args) throws Exception
{
Class app = Class.forName(args[0]);
Method main = app.getDeclaredMethod("main", new Class[] { (new String[1]).getClass()});
String[] appArgs = new String[args.length-1];
System.arraycopy(args, 1, appArgs, 0, appArgs.length);
main.invoke(null, appArgs);
// now you have just launched another application inside the same VM
}
}
Once you have launched the app, you can wait for the app to start, and poll
Window.getOwnerlessWindows to find any top-level windows the app creates.
A more direct approach is to install your own RepainManager - you canjust delegate to the existing one. This is invoked for all window drawing operations, an so you get right in the heart of the window hierarchy,
You can also register to listen to all events on the AWT EventQueue. That will also give you an inside view on what is happening in the app, and from that you can determine which windows are created, in focus etc..
If you have control over the 'tested' application, I think your best bet might be to create a server which allowed the tester program to proxy calls to an internal java.awt.Robot.
You'll need to write and support an specific protocol ( of your own invention ) in the target app.
You can do it with RMI, Sockets or some other form of RCP ( Protobuf, JSON, WebService etc. )
The point is, you have to open a port in the app and be able to understand instructions from an external source.
If what you're looking a a way to test it, I've heard Abbot is a good option. Take a look.
If you want to manipulate an application ( of which you don't have the source ) that may be more complicated.

Categories

Resources