I know it is possible to get system information in Java and have searched SO for this particular question but have come up empty.
Question:
Can I gather complete system information about all attached monitors? Particularly I am hoping to get a unique ID, model number, or manufacturer of each monitor.
Wayan Saryada for example demonstrated a simple example here that gets basic information about all connected monitors. Code follows to protect from link rot:
//
// Get local graphics environment
//
GraphicsEnvironment env = GraphicsEnvironment.getLocalGraphicsEnvironment();
GraphicsDevice[] devices = env.getScreenDevices();
int sequence = 1;
for (GraphicsDevice device : devices) {
System.out.println("Screen Number [" + (sequence++) + "]");
System.out.println("Width : " + device.getDisplayMode().getWidth());
System.out.println("Height : " + device.getDisplayMode().getHeight());
System.out.println("Refresh Rate: " + device.getDisplayMode().getRefreshRate());
System.out.println("Bit Depth : " + device.getDisplayMode().getBitDepth());
System.out.println("");
}
This code however produces nothing unique. Its just generic information that is helpful but does not meet my end goal.
Use Case / End Goal:
My intentions is to make a portable application that tracks (detects) what computer/ computer setup you are using and displays the appropriate desktop. One example is on my work computer with a large monitor it lays out my desktop one way and then on my laptop it hides some things; long story short it would show an alternate desktop display (less icons, only the ones I need for work/ home).
I have all that extra stuff worked out but I need a way to track not just what computer I am on but which monitors I have attached at the time. Essentially a "MAC address" for attached monitors; I know that is not a thing. This way on a triple monitor setup for example my application knows what goes where. Then if I remove one monitor it knows what to change to.
So long story short there just is no way to accurately detect in Java which monitor is which in the GraphicsDevice API. There are several other ways to detect this information but again Java runs into the same problem. Java just auto increments the monitors it finds like so:
Display0,
Display1,
Display2
...And so on.
Each time the computer turns on different monitor assignments can happen and each time a monitor turns off the order can change. The same is true if the graphics driver crashes or reboots while in use.
One Solution
This does not solve my original issue: The OP's questions. However I know it is extremely hard to get full human readable system information with Java, especially all attached monitors. I put in a request to dbwiddis on GitHub and he was able to add this feature to Oshi. His Java library pulls everything you need to know about every attached monitor to a computer. A perfect all in one solution for Network Admins.
The Issue Still / Hack
There still is no way (including using other API's accessible through other programming languages) to detect which monitor is which. The "MAC Address" of all your attached monitors if you will. The only way to do this reliably (really a hack) is to pop up a terminal that outputs information that you then can grab with Java. This way Java can manually make the matches. It can go out to Display2 and read the terminal window that is open on it and now we know which monitor is Display2.
I have no code for this right now because it is extremely unreliable and not guaranteed to be cross OS compatible. It should work fine in windows but your will need to execute a batch file or powershell script to get the terminals on the monitors you want.
Just look at the GraphicsDevice API:
https://docs.oracle.com/javase/7/docs/api/java/awt/GraphicsDevice.html#getIDstring%28%29
Related
My girlfriend recently bought a product for her skin, its basically a mask with lights on the inside that runs a power cord similar to an auxiliary cord into an auxiliary port on a mini controller. It is only good for 30 uses, every time you turn it on, an lcd screen counts down til it hits 0, then you have to buy a new controller.
I find it extremely wasteful to buy a new plastic controller after 30 uses. My question is it possible to somehow connect this device to my laptop through the aux port or aux port extension and modify the code written on it.
I work as a web developer by trade, so I am no stranger to code. I just need to know how to connect it, read the code and compile the code, etc, to modify the counter or remove it.
It is ЯU 94v-0 mini controller (Yes, the R is backwards)
Interestingly enough if I plug the mask into my iPhone or Mac, it will power one set of lights (there are two types/sets), but not the other.
Thanks in advance for the hackery advice.
I Have Better IDEA! Just buy new device (This device has an memory ATMLH436, which is basically same as AT24C02 eeprom chip), disconnect the WP pin and connect it only with the VCC pin, it then can't write the counter down (since it will be write protected), every time you pull the batteries out and in again, it will be as fresh as new. Should work like a charm :D
Here is the historical answer, maybe usefull to someone in the future:
How to hack instruction.
This device has an memory ATMLH436, which is basically same as AT24C02 eeprom chip, which is an EPROM with I2C interface, it is 2 KBytes memory. And the counter is most likely stored on this element.
You need to buy a new device, connect the not used eeprom to a i2c programator (you need to buy one, or ask a friend, I remeber this as a simple device connected to a rs232 port, but you can find one for usb), read the memory content and store it in a file and then you can use this file to reprogram the eprom to the original "new" state every time you want.
How to connect the i2c eeprom to mac:
hmmm, you need to have an i2c programator, that's first step.
Check the one you're about to buy if it has a Macintosh compatible software for reading/ writing.
If not, maybe use other computer.
remeber that in order to be able to program the device you need to connect the pin 7 (Write protect pin) to the ground. Here's the chip spec: http://www.atmel.com/Images/doc0180.pdf
Basically in oreder to communicate with the device you need:
know the address of the device - it is set by the A0,A1,and A2 pins connected either to ground or VCC - the programator soft will require that address.
connect the SDA, SCL and GND pins to the programator.
the chip need power supply of 5V connected beetween GND (-) and VCC (+) to operate.
In order to program the WP pin needs to be connected to GND.
There are big chances that: A0,A1,A2 and WP are grounded, but I can't be sure.
In case of this scenario the address of the device is 1010000 and there's nothing left that needs to be done in oreder to program it. I assume if the WP pin is not grounded you can disconnect it from whatever it is connected to and hardwire it to ground - should not affect normal operation of the device. probably you don't need to unsolder the chip in order to be able to read/write it, you need to connect GND, SDA, SCL and VCC. I would make a connector for these 4 pins to have it accessible from ouside of the device.
In order to make my life easier for many reprogram cycles, I would solder some connector to not have to disssassemble the device each time I need to reprogram it.
There are small chances that the counter is in the fat black round dot on the PCB, in which case there's nothing you can do to reset it since it is some custom chip without spec - if you have a great lab with X-RAY machine (like https://www.hawkerrichardson.com.au/electronic-production-systems/inspection-test-a-repair/unicomp-ax-8200) and other such stuff + lot of experience you could :) but rather not many people have such toys since they are very expensive :)
There are some pins to connect to the rounded chip, but I don't have any idea how to use them, what's the protocol or anything...
but if they could produce eprom inside of it, they wouldn't probably use any additional external eeprom because of the costs. But since eeprom production is not so easy as the regular chip, they use rather external memory from other supplier rather that producing one by themself - it's one logical argument that the counter is there in the AT24C02.
The correct way to hack this thing would be to listen to the I2C communication line with a scope. Note the exact binary sequence.
Then remove the external eeprom entirely and replace it with another MCU, which only has one task and that is to reply as the main MCU expects it to do. Though of course it never saves the down-counter.
Essentially you'd get this sequence each time you power up:
Main MCU: "Hello my eeprom, can I get the counter?"
Hack MCU: "Err yes I am totally an eeprom, the counter is 5."
Main MCU: "Store the counter value 6".
Hack MCU: "Roger that" (does nothing).
You'll get the same sequence over and over.
To succeed you need to know: microcontroller programming, I2C, basic electronics, soldering.
I am going to research on which key typed most in which hour in a 24-hour-day?
Later, I would research on which word used most in which hour in a 24-hour-day?
Say in the evening you would find most used word good or bye as people usually ends up their meeting in the evening.
So, I need to record keystrokes on the background using a java application with a time-stamp.
My questions are:
How to run a java program on the background?(Obviously informing the user).
How to record keystrokes which are used in other applications and counted in the java application without affecting its original application?
Note that:
This question does not serve my problem. Though it has an accepted answer, but the answer is not helpful for me because it could not distinguish between uppercase and lowercase letter, it returns same ASCII character. It just gave some sources and some other files. I expect more readable answer and a clear view how the java program launch on the start up and run on the background.
Just a little information to get you moving in the right direction. What you are looking to implement to listen for the keystrokes is KeyListener. I believe the actual function is keyTyped(ActionEvent e) but am not sure.
Other then that to run a program silently in the background will probably require some manipulation of the window + windows properties. You could just have the program run without a UI, or create a very lightweight UI that posts data. If you are looking for an actual "out of sight out of mind" background process, I am not sure how to do this with Java. However I imagine just an un-intrusive GUI would be sufficient for your purposes.
I am creating a Java application that will run on both Linux and Windows. The application will execute native code for multiple-monitor configurations. Because of this, I want to pass the monitor's ID from Java to the native code. This has lead me to Java's ScreenDevice.getIDstring().
Javadocs claim that this method is useful for debugging, but that it also uniquely identifies a monitor. For Linux devices, it returns a usable ID string that allows the native code to quickly retrieve the desired monitor object.
On Windows, however, the method simply returns /display0 for the first display, and then counts upwards for every following display (regardless if a graphics card contains both monitors, or if the monitors are on separate graphics cards).
When it comes to Windows C++ code, I have tried using EnumDisplayDevices and looking at the respective DeviceIDs and DeviceStrings. These do not match the values of Java:
First Monitor - Java = /display0, Windows = \\.\DISPLAY1
Second Monitor - Java = /display1, Windows = \\.\DISPLAY7
I am really confused as to where this /display# ID value is coming from... Where can I acquire the same /display# value when running native Windows C++ code?
Note: It would technically be possible to cycle through all existing displays to try and match the X/Y/width/height between the OS native code and Java, but this would be a lot of work and not very efficient. I would see this as a possible solution, but it is not very ideal.
I'm looking for a way to specify an output device with JavaFx
I have a similar issue as this question: JavaFX specific Audio Output, but with different needs.
I need a way to get a list of all possible Audio Output devices (like the one you see in your user preferences) and allow the user to select which one they want the audio to come out of in JavaFx. This seems like a really basic feature that should be in any music/media API, and is essential for most audio software.
I'm using the MediaPlayer in JavaFx, though if there is another class I'm happy to use it. Note though that I need the same functionality for video (specifying audio output), so I need a class/solution that works for both.
If there's something in JavaFx 8 that will help, I can always wait until it is released.
What I really expected there to be was the same thing as the Screens class:
Screen.getScreens() // Gets an observable list of all screens.
I'm fine with hackish solutions. Really, anything that works.
For years it has been a very unfortunate limitation of the Java implementation for OS X, being BTW particular for that platform, that "Java Sound Audio Engine" is the only programmatically available output audio line. In consequence, whatever you send to this line, i.e. out from any java application that you make, will always be routed to what has been set as the default output in the OS X, typically internal speakers. So the JSAE is just Java terminology for "default audio out". To our understanding - sadly - this is still the case with latest release.
Why unfortunate ? Because it effectively disables even humble audio routing. We are working with these matters on a daily basis, and it calls for all sorts of added complexity. There are work arounds, but via third party apps as SoundFlower and HiJack Pro. www.soundPimp.com for example.
As assylias has pointed out getmixerinfo method can help you
Info[] mixerInfo = AudioSystem.getMixerInfo();
for(int i = 0; i < mixerInfo.length; i++)
{
System.out.println(mixerInfo[i].getName());
}
You can explore further details here
Perhaps making use of jniwrap.jar and winpack.jar so I don't have to roll my own JNI code, how can I read the "Virtual Bytes" performance counter for a Java service? The service will read its own performance counter so that it can periodically log how much virtual address space is in use. Currently, it logs the JMX value "CommittedVirtualMemorySize" returned by the OS JMX MBean, but this only shows the amount of memory that is committed, so doesn't really help you understand if you are about to exhaust your virtual address space.
This is for a Java-based server process where sometimes the Java compiler thread exhausts the C Heap, crashing the whole JVM in the process. My own code is not the culprit -- it's the JVM itself. But this diagnostic data will help me understand the full virtual address space needs of the service.
Edit: Since asking this question, I have tried several different things, so far to no avail. It turns out that winpack.jar allows registry access and there is a registry key RegistryKey.PERFORMANCE_DATA that supposedly provides access to performance data via registry-like access, but I always got no keys back. I found some sample code in VB that used this method to get performance data, and even with that code, I got back no data. This is on a Win7Pro desktop. Is this data not available by default?
If I cannot get that method to work, then I think the only other choice is trying to use jniwrap or winpack to somehow execute code in Java equivalent to this C# code:
PerformanceCounter PC = new PerformanceCounter();
PC.CategoryName = "Process";
PC.CounterName = "Virtual Bytes";
PC.InstanceName = "Java#1";
PC.ReadOnly = true;
float VirtualBytes = PC.NextValue();
but I can't think of a good way to do this. Is there anyone familiar either with Jniwrapper/winpack or with getting performance data via the registry who can suggest a way of doing this?
I recognize there's always the possibility of writing an external C# program or WMI script to get this information, but I expect that to be orders of magnitude slower (and more work to implement) than getting direct programmatic access to this information.
It turns out that the WinPack.jar library direclty provides this information! I didn't find any documentation that helped me find this. Just looking through its API documentation and experimenting, I was able to come up with this code. Replace MemoryStatus with MemoryInfo if you're using the latest version of the library:
import com.jniwrapper.win32.system.MemoryStatus;
...
private void test() {
MemoryStatus mStatus = new MemoryStatus();
System.out.println("TotalVirtual: " + getBytesInMB(mStatus.getTotalVirtual()) + " MB");
System.out.println("AvailVirtual: " + getBytesInMB(mStatus.getAvailVirtual()) + " MB");
System.out.println("UsedVirtual: " + getBytesInMB(mStatus.getTotalVirtual() - mStatus.getAvailVirtual()) + " MB");
}
private long getBytesInMB(final long input) {
return input / 1024 / 1024;
}
this gives me what I am looking for -- the virtual address space usage of the Java process that is running this code. It is not a general purpose solution, but it may help other people who want to log the same kind of information.