Friday, 29 December 2017

Detect user activity in a windows system using Java.

When I was working on a project to shut down the systems that were left turn on after use by students in a computer lab, then I searched a lot of Java code to detect mouse and keyboard activity by users. Since you all know that you can detect mouse and keyboard by Java Code but it is limited to only frame that is focused.
Robot class lets you know the somehow the pointer position, but it is hard to ignore the keyboard.
After a long search on Internet I found  zOlive code (post) very useful to detect user inactivity on windows system.
I applied whole java source code of zOlive in my project.

See how I applied the zOlive code to detect user inactivity and shutdown the system.
As said by zOlive  in his post:-
To run this code you require jna.jar file from JNA website.
Go to the directory where jna.jar was saved and create the file Win32IdleTime.java in it.
Open cmd.exe and go to the directory. Compile with
javac -classpath jna.jar Win32IdleTime.java
Run with
  • java -cp jna.jar;. Win32IdleTime
    (replace “;” by “:” on Unix systems).

import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Date;
import com.sun.jna.*;
import com.sun.jna.win32.*;
/**
 * Utility method to retrieve the idle time on Windows and sample code to test it.
 * JNA shall be present in your classpath for this to work (and compile).
 * @author ochafik
 */
public class Win32IdleTime {
        public interface Kernel32 extends StdCallLibrary {
                Kernel32 INSTANCE = (Kernel32)Native.loadLibrary("kernel32", Kernel32.class);
                /**
                 * Retrieves the number of milliseconds that have elapsed since the system was started.
                 * @see http://msdn2.microsoft.com/en-us/library/ms724408.aspx
                 * @return number of milliseconds that have elapsed since the system was started.
                 */
                public int GetTickCount();
        };
        public interface User32 extends StdCallLibrary {
                User32 INSTANCE = (User32)Native.loadLibrary("user32", User32.class);
                /**
                 * Contains the time of the last input.
                 * @see http://msdn.microsoft.com/library/default.asp?url=/library/en-us/winui/winui/windowsuserinterface/userinput/keyboardinput/keyboardinputreference/keyboardinputstructures/lastinputinfo.asp
                 */
                public static class LASTINPUTINFO extends Structure {
                        public int cbSize = 8;
                        /// Tick count of when the last input event was received.
                        public int dwTime;
                }
                /**
                 * Retrieves the time of the last input event.
                 * @see http://msdn.microsoft.com/library/default.asp?url=/library/en-us/winui/winui/windowsuserinterface/userinput/keyboardinput/keyboardinputreference/keyboardinputfunctions/getlastinputinfo.asp
                 * @return time of the last input event, in milliseconds
                 */
                public boolean GetLastInputInfo(LASTINPUTINFO result);
        };
        /**
         * Get the amount of milliseconds that have elapsed since the last input event
         * (mouse or keyboard)
         * @return idle time in milliseconds
         */
        public static int getIdleTimeMillisWin32() {
                User32.LASTINPUTINFO lastInputInfo = new User32.LASTINPUTINFO();
                User32.INSTANCE.GetLastInputInfo(lastInputInfo);
                return Kernel32.INSTANCE.GetTickCount() - lastInputInfo.dwTime;
        }
        enum State {
                UNKNOWN, ONLINE, IDLE, AWAY
        };
        public static void main(String[] args) {
                if (!System.getProperty("os.name").contains("Windows")) {
                        System.err.println("ERROR: Only implemented on Windows");
                        System.exit(1);
                }
                State state = State.UNKNOWN;
                DateFormat dateFormat = new SimpleDateFormat("EEE, d MMM yyyy HH:mm:ss");
                for (;;) {
                        int idleSec = getIdleTimeMillisWin32() / 1000;
                        State newState =
                                idleSec < 30 ? State.ONLINE :
                                idleSec > 5 * 60 ? State.AWAY : State.IDLE;
                        if (newState != state) {
                                                                          // You can put your code here according to newstate
                                state = newState;
                                System.out.println(dateFormat.format(new Date()) + " # " + state);
                        }
                        try { Thread.sleep(1000); } catch (Exception ex) {}
                }
        }
}

Say thanks to zOlive to post such a nice post.
You may also find the MAC OSx version and Linux version of this code in his post.

No comments:

Post a Comment

Change image source dynamically on hyperlink

 Changing image source dynamically using JQuery. Here in this example I have created there hyperlink and stored all images in the same folde...