sábado, 14 de fevereiro de 2009

J2ME e Bluetooth

Olá povo,

Uma das coisas mais legais de se desenvolver aplicações e jogos para celulares é a mobilidade que eles nos proporcionam. Uma tecnologia que está cada vez mais presente nos celulares mais populares no Brasil é o Bluetooth. Por isso, hoje vou falar um pouquinho sobre como desenvolver aplicações com essa tecnologia em Java ME.

Bluetooth é uma tecnologia utilizada para criar pequenas redes sem fio, também chamadas de WPANs (Wireless Personal Area Network). O alcance das redes Bluetooth normalmente é de 10 metros. Não vou filosofar muito sobre a pilha de protocolos, potências, etc. Informações mais detalhadas acesse o site oficial da tecnologia Bluetooth.

Antes de qualquer coisa precisaremos saber se o dispositivo para qual iremos desenvolver suporta a JSR-082. É ela que define o uso da tecnologia Bluetooth com Java ME. Consulte o site do fabricante para obter essa informação. Caso seu telefone não implemente essa JSR, você poderá testar esse exemplo no WTK.

O esquema abaixo demonstra como é estabelecida uma conexão entre dispositivos Bluetooth.



Note que primeiramente devemos estabelecer quem é o servidor. Ele ficará visível para que outros dispositivos o encontrem, aguardará por clientes e os proverá um serviço. O cliente por sua vez terá mais trabalho. Ele primeiro procurará por dispositivos (inquiry) disponíveis em sua área de alcance. Esses podem ser mouses, teclados, antenas ou qualquer outro dispositivo Bluetooth. Após obter essa lista de dispositivos, escolheremos um e verificaremos se ele está disponibilizando o serviço que nos interessa. Se estiver, a conexão entre os dois será estabelecida.

Agora, mãos à obra! Vamos listar agora as classes mais importantes do pacote javax.microedition.bluetooth.*:



LocalDevice - Representa o dispositivo Bluetooth local. É um singleton que pode ser obtido pelo método getLocalDevice(). Com ele podemos, entre outras coisas, dizer se o nosso aparelho será visível para os outros dispositivos, obter o endereço ou o nome do seu dispositivo Bluetooth entre outras.

LocalDevice myPhone = LocalDevice.getLocalDevice();
System.out.println(myPhone.getFriendlyName());

DiscoveryListener - Interface que é notificada quando os eventos de busca de dispositivos e serviços acontecem. Ela tem quatro métodos:

/*
Método chamado quando um dispositivo é econtrado.
Devemos armazenar (em um Vector por exemplo) o
remoteDevice para podermos buscar pelo serviço.
*/
void deviceDiscovered(RemoteDevice remoteDevice,
DeviceClass deviceClass);

/*
Método que é chamado quando a busca de dispositivos
termina.
discType - indica o resultado da busca:
INQUIRY_COMPLETED - Busca terminada com sucesso.
INQUIRY_TERMINATED - Busca cancelada.
INQUIRY_ERROR - Erro na busca.
*/
void inquiryCompleted(int discType);

/*
Método chamado quando a busca do serviço termina.
transID - Id da transação de busca pelo serviço
respCode - indica o resultado da busca:
SERVICE_SEARCH_TERMINATED - Busca cancelada.
SERVICE_SEARCH_ERROR - Erro na busca.
SERVICE_SEARCH_NO_RECORD - Dispositivo não tem o
serviço solicitado.
SERVICE_SEARCH_DEVICE_NOT_REACHABLE - Dispositivo
remoto está fora do alcance.
SERVICE_SEARCH_COMPLETED - Serviço encontrado com
sucesso.
*/
void serviceSearchCompleted(int transID, int respCode);

/*
Método chamando quando o serviço procurado é encontrado.
transID - Id da transação de busca pelo serviço
serviceRecord - informações do serviço encontrado.
*/
void servicesDiscovered(int transID, ServiceRecord[] serviceRecord);

DiscoveryAgent - Obtido através da instância do LocalDevice é o responsável por realizar a busca de dispositivos remotos na área de alcance do dispositivo local e de localizar o serviço no dispositivo remoto.

DiscoveryAgent agent = myPhone.getDiscoveryAgent();
agent.startInquiry(DiscoveryAgent.GIAC,
classeQueImplementeDiscoveryListener);

Com a chamada do startInquiry, cada vez que um dispositivo for encontrado a classe que implementa DiscoveryListener será notificada através do método deviceDiscovered. E quando o inquiry terminar o método inquiryCompleted será chamado.

RemoteDevices - representa um dispositivo Bluetooth remoto. Objetos dessa classe são retornados quando se realiza um inquiry (busca por dispositivos). Então devemos armazena-los em memória para que possamos fazer a busca de serviços com esse objeto através do objeto discoveryAgent.

agent.searchServices(null, uuidSet, remoteDevice,
classeQueImplementeDiscoveryListene);

Com a chamada desse método, quando o serviço procurado for encontrado a classe que implementa DiscoveryListener será notificada através do método servicesDiscovered, e quando a busca por serviços terminar o método serviceSearchCompleted será chamado.

Abrindo uma conexão (Servidor)
Lembrando que toda conexão utilizando GCF (Generic Connection Framework) deve ser feita em uma Thread separada, segue abaixo um trecho de código que abre uma conexão servidora e fica aguardando por conexões de clientes.

localDevice = LocalDevice.getLocalDevice();
int initialDiscoveredMode =
localDevice.getDiscoverable();
localDevice.setDiscoverable(DiscoveryAgent.GIAC);

StreamConnectionNotifier notifier =
(StreamConnectionNotifier) Connector.open(
"btspp://localhost:0000000000000000000BE3125CDAE");
connection = notifier.acceptAndOpen();
execute(connection);

Antes de abrir a conexão, o dispositivo é colocado em modo de descoberta para que outros possam encontra-lo. Depois é aberta a conexão servidora (localhost) utilizando "btspp" que é o protocolo de comunicação (BlueTooth Serial Port Profile). O número gigante :) após os ":" é o identificador do serviço UUID. O método execute trata os dados vindos do outro dispositivo. Segue abaixo o seu código:

protected void execute(StreamConnection conn){
try {
os = connection.openDataOutputStream();
is = connection.openDataInputStream();
String message;
while (true){
message = is.readUTF();
}
} catch (IOException e) {
e.printStackTrace();
} finally {
//closeStreams();
}
}

"os" e "is" são atributos da classe e devem ser um DataOutputStream e um DataInputStream.
Por último, o método que envia as mensagens:

public void send(String message){
try {
os.writeUTF(message);
os.flush();
} catch (IOException e) {
e.printStackTrace();
}
}

Bem pessoal, esse é só um aperitivo. Quem quiser saber mais, postem suas dúvidas.

[Editado]
Atendendo aos comentários, um exemplo bem simples pode ser baixado aqui.

[Editado 2]
E neste link vocês podem baixar um exemplo mais simplificado e comentado (mas precisando de algumas melhorias) do exemplo anterior.

4br4ç05,
nglauber

domingo, 1 de fevereiro de 2009

Vírus do Pen-Drive (BV:Autorun)


Olá povo,

Mais uma vez, depois de um longo tempo sem postar, venho deixar uma dica preciosa aqui - pelo menos foi pra mim.
Como já citei várias vezes aqui, ministro aulas de Java, e em uma dessas aulas veio a pergunta: "Professor, o senhor pode copiar esse material que o senhor tá usando pro meu pen-drive?". Ao que respondí que sim. Que mal poderia ter um inocente pen-drive? Tá, tá bom, pode ter vírus, mas pensava que o meu bom e velho Avast detectaria... Você já sabem o que aconteceu né?

Meu computador foi infectado pelo vírus BV:Autorun-G. Na verdade não é um vírus, é um malware. Ele se instala através do autorun do pen-drive e assim, qualquer pen-drive que se conecte ao computador infectado, será infectado também, da mesma forma que qualquer computador que receba o pen-drive também ficará infectado. Sua ação é de "reciclador". Ele pega os arquivos da lixeira e envia pro pen-drive infectado.

Depois de procurar em diversos sites em vão, achei a solução simples e fácil, diferentemente do que eu achei nos sites. Segue o passo-a-passo para a remoção dessa praga:
1) Usei o CCleaner (http://www.ccleaner.com/) para fazer uma limpeza geral em arquivos e entradas de registro desnecessárias.
2) Usei o FlashDesinfector (http://www.techsupportforum.com/sectools/sUBs/Flash_Disinfector.exe) para fazer com que o pen-drive não executasse mais o malware. Esse programinha exclui o arquivo autorun.inf do pen-drive infectado por um diretório do mesmo nome impedindo que o virus execute quando você "espete" o pen-drive na máquina.
3) Nesse passo é que o milagre se fez :) usei o RegRun Security Suite (http://www.greatis.com/security/). Enquanto nem o Avast e nem o Avira o detectaram, esse software encontrou de "prima". Esse malware normalmente se instala em C:\RECYCLER\[um número de registro]\exe32.exe. Quando ele encontrar esse arquivo, remova-o. Cuidado pra não fazer feito eu, que apaguei algumas DLLs do Windows e tive que restaurar o sistema e fazer o passo 3 de novo :)
4) Seja feliz novamente :)


Apesar de nessas minhas pesquisas o pessoal falar que é um vírus inofensivo, ninguém gosta de ficar com nenhuma vírus/spyware/malware no PC.

Para finalizar, segue algumas dicas para vocês não sofrerem o mesmo que eu:
- Usem todas as ferramentas de detecção que puderem (anti-vírus, anti-spyware, etc.) e as mantenham atualizadas.
- Desativem o auto-run das mídias externas (CD, DVD, pen-drive, etc) no seu PC.
- Não espetem pen-drive de estranhos na sua máquina.

Bem, acho que é só...
Espero postar mais em breve e não demorar tanto.

4br4ç05,
nglauber

quarta-feira, 22 de outubro de 2008

Site que adivinha pensamento?

Oi povo,

Depois de muito tempo sem postar, vai aqui um site bem legal que adivinha pensamentos. É isso mesmo. Você pensa em alguma coisa e o site vai te fazendo perguntas até ele te dizer em que você pensou.
http://pt.akinator.com/
Escolha seu idioma e faça um teste. É bem bacana.

Espero postar mais coisas legais daqui a alguns dias.

4br4ç05,
nglauber

terça-feira, 9 de setembro de 2008

Imagens SVG com J2ME

Olá povo,

Vê só, antes de mais nada, quero dizer que esse post é sobre um assunto que eu começei a dar uma 'fuçada' agora. Então, qaulquer besteira que eu fale, me perdoem.

No projeto em que estou trabalhando, os designers elaboraram uma tela principal da aplicação onde os ícones para acesso às funcionalidades da aplicação tinham um comportamento 'meio 3D'. Porque eu digo 'meio'? Por que ele só usava uma profundidade pra mostrar qual ícone estava selecionado.
Infelizmente o aparelho não tinha suporte pra JSR-184 (Java Mobile 3D), então tivemos que fazer as coisas usando 2D mesmo.
Conversando com um colega, ele nos sugeriu dar uma olhada em SVG (Scalable Vectorial Graphics) pra JavaME. Resolví dar uma olhada em um artigo da WebMobile que falava sobre o assunto (infelizmente agora não lembro do nome do autor do artigo) e ver o que realmente ela poderia ajudar.
O SVG é uma linguagem pra descrever imagens bi-dimensionais em XML. SVG Tiny é um subconjunto do SVG utilizado para utilizar essas imagens em dispositivos móveis. A JSR-226 define uma API para carregar, manipular e pintar esse tipo de imagem. Ela não está contida por padrão em nenhum perfil ou configuração, sendo assim, sua implementação fica à cargo de cada fabricante. Como os cálculos vetoriais são realizados com ponto flutuante, a configuração CLDC1.1 é requerida.
Essa API faz algumas 'mágicas' as quais não conseguimos com imagens bitmap, mas a maior delas é o poder de redimensionar a imagem via código. Como a imagem não passa de um arquivo texto com coordenadas relativas, basta refazer os cálculos e renderizar a imagem novamente. Isso traz um enorme benefício quando falamos em portabilidade de aplicações que usam Canvas, visto que, se usarmos esse tipo de imagem, basta fazermos o código para que essas imagens seja expandidas para que aplicação rode sem problemas em qualquer telefone, independente do tamanho da tela.
Bem, vamos a um pouquinho de prática. Segue abaixo um arquivo *.svg que pinta 3 quadrados e um texto.

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1 Tiny//EN"
"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11-tiny.dtd" [
<!ENTITY ns_svg "http://www.w3.org/2000/svg">
<!ENTITY ns_xlink "http://www.w3.org/1999/xlink">]>
<svg version="1.1" baseProfile="tiny" id="root" xmlns="&ns_svg;"
xmlns:xlink="&ns_xlink;" width="176" height="208"
preserveAspectRatio="none" viewBox="0 0 176 208" xml:space="preserve">

<rect id="r1" x="0" y="0" fill="#FFFFFF" stroke="#000000" width="176" height="208"/>
<rect id="r2" x="20" y="20" fill="#FFFF00" stroke="#000000" stroke-width="2" width="136" height="168"/>
<rect id="r3" x="60" y="60" fill="#FF0000" stroke="#000000" stroke-width="2" width="56" height="88"/>
<text id="xy" x="88" y="104" text-anchor="middle" font-family="Arial" font-size="10">88,104</text>
</svg>


E agora o código do canvas que carrega e pinta essa imagem na tela.

class SvgCanvas extends Canvas {

private ScalableGraphics sg;

private SVGImage svgImage;

public SvgCanvas() {
sg = ScalableGraphics.createInstance();
try {
InputStream is = getClass().getResourceAsStream
("/res/svg/retangulo.svg");
svgImage = (SVGImage)SVGImage.createImage(is, null);
} catch (Exception e) {
e.printStackTrace();
}
}

protected void paint(Graphics g) {
g.setColor(0xFFFFFF);
g.fillRect(0, 0, getWidth(), getHeight());

sg.bindTarget(g);
sg.render(0, 0, svgImage);
sg.releaseTarget();
}
}


Bem pessoal, apesar de todos esses benefícios trazidos pelas imagens vetoriais, poucos aparelhos trazem a implementação da JSR-226. E a renderização dessas imagens parece ser bem lenta, tendo em vista toda a leitura do XML e dos cálculos efetuados.
Pra finalizar, vou dar meu aval: Por enquanto, não gostei. No entanto, quem sabe com celulares mais poderosos poderemos ter esse tipo utilização de imagens mais viável.

Dêem sua opinião, porque, como eu falei, tô começando a estudar isso agora.
Maiores informações:
http://www.w3.org/Graphics/SVG/
http://www.jcp.org/en/jsr/detail?id=226
http://pt.wikipedia.org/wiki/SVG

4br4ç05,
nglauber

quarta-feira, 3 de setembro de 2008

Chegou Google Chrome!

Olá povo,

A Google, a empresa que quer dominar o mundo (se é que já não domina) lançou dia 01/09/2008 o Google Chrome, o browser da empresa.
Quem se interessar, pode baixar livremente clicando aqui.

Confesso que vou esperar um pouquinho, tendo em vista que essa é uma versão BETA, o pessoal em 2 dias já achou um furo de segurança no mesmo. Além do mais, teremos que esperar até que outras empresas tenham a boa-vontade de escrever os plugins pra ele, como os sites de bancos por exemplo.

Então, a Google lançou um browser novo. Isso é bom? Depende do ponto de vista. Por um lado é uma boa, parece que o Chrome tem um monte de 'pra que isso' e tudo mais, além de termos mais uma opção além do IE e do Firefox. Mas vocês já pensaram no problema que teremos como desenvolvedores web? Pobres de nós, vamos ter que testar em mais um browser todas as nossas funções javascript, métodos Ajax, CSS, etc. Ou você acha que tudo vai funcionar de primeira? :)

Mais um browser, e o que nós ganhamos como desenvolvedores? Mais trabalho!

P.S.: Espero me retratar em breve sobre o Chrome.

4br4ç05,
nglauber

quarta-feira, 27 de agosto de 2008

Programas úteis JavaME

Olá povo,

Bem, esse é um postzinho bem rápido. É só pra listar alguns programinhas úteis no desenvolvimento de aplicações/jogos para celular. Lá vão eles:
  • SnagIt: captura a tela do computador. É similar ao PrintScreen, porém permite gravar vídeos da tela. Isso me foi útil quando precisei contar frames de uma animação de um personagem de um jogo que estava desenvolvendo.
  • HxD: leitor de arquivos hexadecimais. Utilizei o mesmo para criar um midi (arquivo de áudio) em tempo de execução. Eu olhei como era um arquivo midi em hexa, e só foi escrever no mesmo formato.
  • mapwin: ferramenta para criação de mapas para jogos 2D. Você adiciona a imagem com os tiles (imagem com vários quadradinhos que juntas vão formar o cenário) e só é montar o mapa.
  • PNGGauntlet: otimizador de imagens PNG. Diminui bastante o tamanho do JAR de jogos ou aplicações que tenham muitas imagens.
  • JADMaker: esse aplicativozinho cria o arquivo JAD a partir de um JAR que tenha um MIDlet. Ele é util quando você quer testar um MIDlet que você baixou no emulador antes de colocar no celular.

É isso pessoal. Qualquer dúvida sobre alguma das ferramentas, comentem aí.

4br4ç05,
nglauber

segunda-feira, 28 de julho de 2008

Os frameworks são para que mesmo?

oi povo,

Como já venho postando aqui, estou dando aula de Java Web. E nesse desafio tive que estudar alguns frameworks (JSF, Hibernate, DWR, etc.), mesmo sem ser muito fã de frameworks. Como programo para celulares e fico chorando alguns míseros bytes de memória, camadas e mais camadas de software uma em cima da outra me dá muito medo! :)
Sem sombra de dúvida que ao menos um pouco eles agilizam o desenvolvimento pra web, mas a que custo também viu.
A minha última experiência foi colocar o Ajax4JSF pra funcionar. Depois que a JBoss incorporou essa biblioteca no seu richfaces, não ficou nada facinho colocar ele pra funcionar (pelo menos eu não achei).
Então achei em algum blog aí da vida (como esse), como configurar o Ajax4JSF, e aí resolví compartilhar com vocês. Além dos jars do JSF, são necessários:

richfaces-3.0.1.jar
ajax4jsf-1.1.0.jar
oscache-2.3.2.jar

E nessas versões específicas! É isso mesmo, se colocar com a versão 1.1.1 não funciona! Mas a 1.1.0 funciona...

Tudo pela "agilidade" e "facilidade" no desenvolvimento.

4br4ç05,
nglauber