HiveBrain v1.2.0
Get Started
← Back to all entries
patternjavaMinor

Detecting if the system is idling

Submitted by: @import:stackexchange-codereview··
0
Viewed 0 times
systemthedetectingidling

Problem

The following code detects if the system is idling. It approaches the problem by using the 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

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.