J2ME

Utilizando JNI em J2ME

Olá pessoal,

Hoje falarei sobre a utilização de JNI em aplicações J2ME. Eventualmente nos deparamos com a necessidade de acessar recursos nativos de celulares e PDA`s, como a câmera e o GPS, e não encontramos API`s java que nos auxiliem nessa tarefa.
Em muitos casos sequer existem essas API`s uma vez que a máquina virtual não as suporta, o que torna o trabalho ainda pior. Para isso existe uma alternativa: a utilização da Java Native Interface ou simplesmente JNI.

A JNI permite que um código escrito em Java interaja com uma biblioteca, por exemplo, escrita em C/C++ ou em outras tantas linguagens de programação. Ainda sobre a JNI, é possível capturar e lançar exceções de uma biblioteca qualquer e tratá-las dentro da aplicação Java. Imaginemos então um caso real onde precisamos desenvolver uma aplicação para Windows Mobile que acesse o GPS do dispositivo. Utilizando a máquina virtual J9 da IBM bastaria realizar os seguintes passos:

1a – Escrever a classe java que carrega a dll e que possui os métodos nativos que servirão como um proxy para chamar os recursos da DLL. Caso a aplicação esteja sendo desenvolvida com a configuração CDC:

System.loadLibrary("GpsDll");
public native double getLongitude();
public native double getLatitude();

1b – Caso a aplicação esteja sendo desenvolvida com a configuração CLDC, basta importar a classe com.ibm.oti.vm.VM, presente na J9, e utilizar o método VM.loadLibrary() ao invés do System.loadLibrary(). Para isso, a classe onde esse método esta declarado precisa estar dentro da pasta ext da J9 (Ex.: \Program Files\J9\MIDP20\lib\jclMidp20\ext) ou o jar contendo essa classe precisa estar especificado no argumento –Xbootclasspath do arquivo que contem o link para executar a aplicação:

VM.loadLibrary("GpsDll");
public native double getLongitude();
public native double getLatitude();

2 – Compilar a classe;

3 – Utilizar a ferramenta javah, disponivel junto com a SDK do java, para gerar o arquivo header do C/C++. (javah –jni br.com.involves.gps.GpsDevice);

/* DO NOT EDIT THIS FILE - it is machine generated */
 
#include 
 
/* Header for class br_com_involves_gps_GpsDevice */
 
#ifndef _Included_br_com_involves_gps_GpsDevice
 
#define _Included_br_com_involves_gps_GpsDevice
 
#ifdef __cplusplus
 
extern "C" {
 
#endif
 
/*
 
* Class:     br_com_involves_gps_GpsDevice
 
* Method:    getLongitude
 
* Signature: ()D
 
*/
 
JNIEXPORT jdouble JNICALL Java_br_com_involves_gps_GpsDevice_getLongitude
 
(JNIEnv *, jclass);
 
/*
 
* Class:     br_com_involves_gps_GpsDevice
 
* Method:    getLatitude
 
* Signature: ()D
 
*/
 
JNIEXPORT jdouble JNICALL Java_br_com_involves_gps_GpsDevice_getLatitude
 
(JNIEnv *, jclass);
 
#ifdef __cplusplus
 
}
 
#endif
 
#endif

4 – Em uma IDE C/C++, como por exemplo o visual studio, criar um arquivo .cpp que irá implementar o header;

#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include "br_com_involves_gps_GpsDevice.h"
 
JNIEXPORT jdouble JNICALL Java_br_com_involves_gps_GpsDevice_getLatitude
  (JNIEnv *env, jclass jObject)
{
     HANDLE g_hGPSDevice;
     g_hGPSDevice = GPSOpenDevice(NULL,NULL,NULL,0);
     GPS_POSITION gpsPosition;
     ZeroMemory(&gpsPosition,sizeof(GPS_POSITION));
     gpsPosition.dwVersion=GPS_VERSION_1;
     gpsPosition.dwSize=sizeof(GPS_POSITION);
     DWORD result=GPSGetPosition(g_hGPSDevice,&gpsPosition,500000,0);
     double latitude = 0.0;
     latitude = gpsPosition.dblLatitude;
     return (jdouble)latitude;
}
 
JNIEXPORT jdouble JNICALL Java_br_com_involves_gps_GpsDevice_getLongitude
  (JNIEnv *env, jclass jObject)
{
      .....
}

5 – Gerar a DLL para a versão do windows mobile em uso;

6 – Adicionar a dll na pasta bin da J9;

Com esses passos é possível acessar recursos nativos sem depender de API`s java para isso. É possível utilizar a JNI tanto com a configuração CDC como CLDC.

Aproveitem os benefícios da JNI e espero que tenha ajudado vocês a compreendê-la um pouco melhor.

Agradecimentos a Rodrigo Veleda.
Um abraço e até a próxima.

1 Comentário