Naturalmente o Java já provê listeners adequados para que você consiga monitorar eventos do teclado ou mouse na sua aplicação, por exemplo: Você consegue saber quando o botão esquerdo do mouse é clicado, quando a tecla ESCAPE do teclado é pressionada e assim por diante. Esses eventos são comuns a qualquer aplicação em Java, pois são com eles que conseguimos interagir com o usuário sabendo o que exatamente ele deseja fazer ou acionar.

Mas o escopo desse monitoramento começa e termina na fronteira da sua aplicação, ou seja, você só consegue monitorar eventos dentro da sua própria aplicação, mesmo que o usuário esteja com a sua aplicação aberta mas ele clicar ou digitar algo em outra aplicação, você não conseguirá “capturar” esse evento. Pensando nisso, foi desenvolvida uma biblioteca chamada JnativeHook (disponível na seção do downloads deste artigo) que provê um “plus” ao Java, ela permite que você monitore eventos externos a sua aplicação, ou seja, eventos de clique do mouse ou digitação de teclas que foram realizadas em aplicações de terceiros são capturadas pela sua aplicação que está em funcionamento.

Usando o JnativeHook

Para exemplificar o uso de tal biblioteca vamos propor a seguinte situação hipotética: Você é Analista de Sistemas de uma fábrica que produz materiais balísticos, nessa fábrica há um computador central que possui um sistema crítico que controla as linhas de produção. Esse sistema que controla as linhas de produção da fábrica não possui nenhum tipo de log para que depois possa ser feita uma auditoria de quem digitou qual comando, na hora X, e no minuto Y.

Então você ficou encarregado de desenvolver um sistema que irá controlar os comandos digitados nesse outro sistema, o seu sistema deve monitorar o usuário logado e o que ele digitou desde de seu primeiro clique até o último clique, assim caso algum problema ocorra podemos recorrer ao seu sistema e realizar uma auditoria afim de descobrir quem é o culpado. Tal situação é crítica, pois um erro da produção de um equipamento balístico pode ocasionar um desastre enorme.

O primeiro passo para o desenvolvimento de tal sistema é a criação de um projeto Java e a importação, que suponhamos que já esteja feito. É óbvio que um sistema deste “calibre” deve ser muito robusto e aprova de erros, afinal, estamos lhe dando com vidas. Mas não vamos nos prender totalmente ao exemplo especificado acima, o importante é perceber a importação que tal recurso pode ter em momentos adequados.

Iremos criar uma classe com o nome Capture que implementa a interface NativeKeyListener. Assim que você implementar tal interface será obrigado a implementar seus métodos que são: nativeKeyPressed, nativeKeyReleased e nativeKeyTyped. Vamos também partir do principio que nosso computador central não possui mouse, apenas entrada via teclado por se tratar de um terminal de comandos. Então na nossa listagem 1 veja como ficou nossa classe sem nenhum código extra além do que citamos acima.


import org.jnativehook.GlobalScreen;
import org.jnativehook.NativeHookException;
import org.jnativehook.keyboard.NativeKeyEvent;
import org.jnativehook.keyboard.NativeKeyListener;

public class Capture implements NativeKeyListener {

	public void nativeKeyPressed(NativeKeyEvent e) {	
		
	}

	public void nativeKeyReleased(NativeKeyEvent e) {
	}

	public void nativeKeyTyped(NativeKeyEvent e) {
	}

}
Listagem 1. Capture implementando NativeKeyListener

Vamos implementar alguns procedimentos para mostrar o que esta sendo digitado pelo usuário. Atente para o seguinte ponto: Não importa onde você digite, pode ser no notepad, no browser (google chrome, firefox) ou qualquer outro local, a sua aplicação irá capturar esse evento.


import org.jnativehook.GlobalScreen;
import org.jnativehook.NativeHookException;
import org.jnativehook.keyboard.NativeKeyEvent;
import org.jnativehook.keyboard.NativeKeyListener;

public class Capture implements NativeKeyListener {

	public void nativeKeyPressed(NativeKeyEvent e) {	
		
		if (e.getKeyCode() == NativeKeyEvent.VK_ENTER){
			System.out.println("");			
		}else if (e.getKeyCode() == NativeKeyEvent.VK_SPACE){
			System.out.print(" ");
		}else{
			System.out.print(NativeKeyEvent.getKeyText(e.getKeyCode()));
		}
	}

	public void nativeKeyReleased(NativeKeyEvent e) {
	}

	public void nativeKeyTyped(NativeKeyEvent e) {
	}

	public static void main(String[] args) {
		try {
			GlobalScreen.registerNativeHook();
		} catch (NativeHookException ex) {
			System.err
					.println("There was a problem registering the native hook.");
			System.err.println(ex.getMessage());

			System.exit(1);
		}

		// Construct the example object and initialze native hook.
		GlobalScreen.getInstance().addNativeKeyListener(
				new Capture());
	}

}
Listagem 2. Mostrando no console o que está sendo digitado

Colocamos o método main para inicializar nossa Classe e carregar o Hook, agora é só deixar a mesma em execução e utilizar o sistema operacional como se nada tivesse logando suas ações.

Se você preferir também pode monitorar o uso do mouse com a listagem 3.


import org.jnativehook.GlobalScreen;
import org.jnativehook.NativeHookException;
import org.jnativehook.mouse.NativeMouseEvent;
import org.jnativehook.mouse.NativeMouseInputListener;

public class CaptureMouse implements NativeMouseInputListener {
        public void nativeMouseClicked(NativeMouseEvent e) {
                System.out.println("Mosue Clicked: " + e.getClickCount());
        }

        public void nativeMousePressed(NativeMouseEvent e) {
                System.out.println("Mosue Pressed: " + e.getButton());
        }

        public void nativeMouseReleased(NativeMouseEvent e) {
                System.out.println("Mosue Released: " + e.getButton());
        }

        public void nativeMouseMoved(NativeMouseEvent e) {
                System.out.println("Mosue Moved: " + e.getX() + ", " + 
                e.getY());
        }

        public void nativeMouseDragged(NativeMouseEvent e) {
                System.out.println("Mosue Dragged: " + e.getX() + ", " + 
                e.getY());
        }

        public static void main(String[] args) {
                try {
                        GlobalScreen.registerNativeHook();
                }
                catch (NativeHookException ex) {
                        System.err.println("There was a problem registering 
                        the native hook.");
                        System.err.println(ex.getMessage());

                        System.exit(1);
                }

                //Construct the example object.
                CaptureMouse captureMouse = new CaptureMouse();

                //Add the appropriate listeners for the example object.
                GlobalScreen.getInstance().addNativeMouseListener(captureMouse);
                GlobalScreen.getInstance().addNativeMouseMotionListener(captureMouse);
        }
}
Listagem 3. Usando monitorador de eventos do mouse com JnativeHook

Enfim, já monitoramos o nosso teclado e o movimento do mouse, mas ainda podemos fazer um pouco mais. Monitorar o scroll do mouse, ou mouse wheel. Na listagem 4 demonstramos como fazer isso.


import org.jnativehook.GlobalScreen;
import org.jnativehook.NativeHookException;
import org.jnativehook.mouse.NativeMouseWheelEvent;
import org.jnativehook.mouse.NativeMouseWheelListener;

public class CaptureMouseWheel implements NativeMouseWheelListener {
        public void nativeMouseWheelMoved(NativeMouseWheelEvent e) {
                System.out.println("Mosue Wheel Moved: " + e.getWheelRotation());
        }

        public static void main(String[] args) {
                try {
                        GlobalScreen.registerNativeHook();
                }
                catch (NativeHookException ex) {
                        System.err.println("There was a problem registering the native hook.");
                        System.err.println(ex.getMessage());
                        ex.printStackTrace();

                        System.exit(1);
                }

                //Construct the example object and initialze native hook.
                GlobalScreen.getInstance().addNativeMouseWheelListener(new CaptureMouseWheel());
        }
}
Listagem 4. Monitorando scroll do mouse

O que você irá perceber na listagem 4 é que só existem dois estados para o Scroll do mouse: o 1 e o -1, onde o 1 significa que você está realizando um “scroll down” e o -1 é o “scroll up”, em outras palavras o 1 é scroll para baixo e o -1 é o scroll para cima.

Por fim, você pode usar a sua criatividade para unir as listagens 2,3 e 4 afim de montar uma aplicação capaz de monitorar o scroll do mouse, os eventos do teclado e o movimento do mouse assim como seu click. As possibilidades são inúmeras e podem servir para as mais diversas aplicações.

O principal objetivo deste artigo foi demonstrar o uso da biblioteca JnativeHook na prática, como alternativa para aqueles que desejam monitorar eventos externos a sua aplicação, algo não muito comum mas necessário em alguns casos mais específicos, como o citado em nossa situação hipotética. Na seção de downloads deste artigo você encontrará o “.jar” da respectiva biblioteca que deve ser importada em seu projeto, assim você poderá importá-la como mostrado nas listagens de 1 a 4.