patternjavaMinor
Detecting if the system is idling
Viewed 0 times
systemthedetectingidling
Problem
The following code detects if the system is idling. It approaches the problem by using the
Please suggest code changes or even a different solution!
```
package base;
import java.awt.AWTException;
import java.awt.DisplayMode;
import java.awt.GraphicsDevice;
import java.awt.GraphicsEnvironment;
import java.awt.Rectangle;
import java.awt.Robot;
import java.awt.Toolkit;
import java.awt.image.BufferedImage;
public class CheckIdle extends Thread {
private Robot robot;
private double threshHold = 0.05;
private int activeTime;
private int idleTime;
private boolean idle;
private Rectangle screenDimenstions;
public CheckIdle(int activeTime, int idleTime) {
this.activeTime = activeTime;
this.idleTime = idleTime;
// Get the screen dimensions
// MultiMonitor support.
int screenWidth = 0;
int screenHeight = 0;
GraphicsEnvironment graphicsEnv = GraphicsEnvironment
.getLocalGraphicsEnvironment();
GraphicsDevice[] graphicsDevices = graphicsEnv.getScreenDevices();
for (GraphicsDevice screens : graphicsDevices) {
DisplayMode mode = screens.getDisplayMode();
screenWidth += mode.getWidth();
if (mode.getHeight() > screenHeight) {
screenHeight = mode.getHeight();
}
}
screenDimenstions = new Rectangle(0, 0, screenWidth, screenHeight);
// setup the robot.
robot = null;
try {
robot = new Robot();
} catch (AWTException e1) {
e1.printStackTrace();
}
idle = false;
}
public void run() {
while (true) {
BufferedImage screenShot = robot
Robot class to take a screenshot, waits for a while, and then takes another screenshot. It then compares screenshot 1 with screenshot 2. If a certain amount of change is detected, it presumes the system is idling, else the system is active.Please suggest code changes or even a different solution!
```
package base;
import java.awt.AWTException;
import java.awt.DisplayMode;
import java.awt.GraphicsDevice;
import java.awt.GraphicsEnvironment;
import java.awt.Rectangle;
import java.awt.Robot;
import java.awt.Toolkit;
import java.awt.image.BufferedImage;
public class CheckIdle extends Thread {
private Robot robot;
private double threshHold = 0.05;
private int activeTime;
private int idleTime;
private boolean idle;
private Rectangle screenDimenstions;
public CheckIdle(int activeTime, int idleTime) {
this.activeTime = activeTime;
this.idleTime = idleTime;
// Get the screen dimensions
// MultiMonitor support.
int screenWidth = 0;
int screenHeight = 0;
GraphicsEnvironment graphicsEnv = GraphicsEnvironment
.getLocalGraphicsEnvironment();
GraphicsDevice[] graphicsDevices = graphicsEnv.getScreenDevices();
for (GraphicsDevice screens : graphicsDevices) {
DisplayMode mode = screens.getDisplayMode();
screenWidth += mode.getWidth();
if (mode.getHeight() > screenHeight) {
screenHeight = mode.getHeight();
}
}
screenDimenstions = new Rectangle(0, 0, screenWidth, screenHeight);
// setup the robot.
robot = null;
try {
robot = new Robot();
} catch (AWTException e1) {
e1.printStackTrace();
}
idle = false;
}
public void run() {
while (true) {
BufferedImage screenShot = robot
Solution
In
Isn't this better as
Here, why initialize robot to null first? Isn't this given in the constructor? And why do you continue if there is an AWT exception? Doesn't it mean no GUI? perhaps your constructor should throw that exception. Otherwise, perhaps it is better to have a larger block for try catch. The reason is that the exception handling code is better away from the main sequence. You use robot in the run code. So in order for that to run, robot has to be non null. So catching the exception here is not correct.
You also set idle to false, which is not really needed because it is initialized to false by java.
Why do you take an extra screen shot? Isn't this what you mean?
Here, where do you use the changed? (as noted in comment to the question.)
The for loop may be better as
Since it avoids multiple calls to getRGB.
And is there any chance of getHeight or getWidth returning 0?
Also, I assume that you are calling .run instead of .start only because you are testing?
if (compareScreens(screenShot, screenShot2) < threshHold) {
idle = true;
} else {
idle = false;
}Isn't this better as
idle = compareScreens(screenShot, screenShot2) < threshHold;Here, why initialize robot to null first? Isn't this given in the constructor? And why do you continue if there is an AWT exception? Doesn't it mean no GUI? perhaps your constructor should throw that exception. Otherwise, perhaps it is better to have a larger block for try catch. The reason is that the exception handling code is better away from the main sequence. You use robot in the run code. So in order for that to run, robot has to be non null. So catching the exception here is not correct.
// setup the robot.
robot = null;
try {
robot = new Robot();
} catch (AWTException e1) {
e1.printStackTrace();
}You also set idle to false, which is not really needed because it is initialized to false by java.
Why do you take an extra screen shot? Isn't this what you mean?
public void run() {
try {
BufferedImage screenShot = null;
BufferedImage screenShotPrev
= robot.createScreenCapture(screenDimenstions);
while (true) {
Thread.sleep(idle ? idleTime : activeTime);
screenShot = robot.createScreenCapture(screenDimenstions);
idle = compareScreens(screenShotPrev, screenShot) < threshHold;
screenShotPrev = screenShot;
}
} catch (InterruptedException e) {
...
}Here, where do you use the changed? (as noted in comment to the question.)
private double compareScreens(BufferedImage screen1, BufferedImage screen2) {
int counter = 0;
boolean changed = false;
// Count the amount of change.
for (int i = 0; i < screen1.getWidth() && !changed; i++) {
for (int j = 0; j < screen1.getHeight(); j++) {
if (screen1.getRGB(i, j) != screen2.getRGB(i, j)) {
counter++;
}
}
}
return (double) counter
/ (double) (screen1.getHeight() * screen1.getWidth()) * 100;
}The for loop may be better as
int[] s1 = ((DataBufferInt) screen1.getRaster().getDataBuffer()).getData();
int[] s2 = ((DataBufferInt) screen2.getRaster().getDataBuffer()).getData();
for(int i = 0; i < s1.length; i++)
if (s1[i] != s2[i]) counter++;Since it avoids multiple calls to getRGB.
And is there any chance of getHeight or getWidth returning 0?
Also, I assume that you are calling .run instead of .start only because you are testing?
Code Snippets
if (compareScreens(screenShot, screenShot2) < threshHold) {
idle = true;
} else {
idle = false;
}idle = compareScreens(screenShot, screenShot2) < threshHold;// setup the robot.
robot = null;
try {
robot = new Robot();
} catch (AWTException e1) {
e1.printStackTrace();
}public void run() {
try {
BufferedImage screenShot = null;
BufferedImage screenShotPrev
= robot.createScreenCapture(screenDimenstions);
while (true) {
Thread.sleep(idle ? idleTime : activeTime);
screenShot = robot.createScreenCapture(screenDimenstions);
idle = compareScreens(screenShotPrev, screenShot) < threshHold;
screenShotPrev = screenShot;
}
} catch (InterruptedException e) {
...
}private double compareScreens(BufferedImage screen1, BufferedImage screen2) {
int counter = 0;
boolean changed = false;
// Count the amount of change.
for (int i = 0; i < screen1.getWidth() && !changed; i++) {
for (int j = 0; j < screen1.getHeight(); j++) {
if (screen1.getRGB(i, j) != screen2.getRGB(i, j)) {
counter++;
}
}
}
return (double) counter
/ (double) (screen1.getHeight() * screen1.getWidth()) * 100;
}Context
StackExchange Code Review Q#10952, answer score: 4
Revisions (0)
No revisions yet.