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