Mostrando postagens com marcador Java ME. Mostrar todas as postagens
Mostrando postagens com marcador Java ME. Mostrar todas as postagens

sábado, 11 de junho de 2011

Documentação do Java ME no Eclipse MTJ

Olá povo,

Esse post vai pro pessoal da segunda turma do TECDAM, que hoje durante a aula Java ME, me questionaram como anexar a documentação das APIs do Java ME no Eclipse. Como isso não é das coisas que se faz todo dia, não lembrei na hora. Então lá vai...

Ao instalar o SDK do Java ME, além das APIs e ferramentas de desenvolvimento, é criada uma pasta onde encontra-se a documentação do MIDP (Mobile Information Device Profile), do CLDC (Connected Limited Device Configuration) e de outras JSRs (Java Specification Request) importantes do Java ME. Entretanto o Eclipse não consegue "enxergar" essa documentação, sendo assim, vou mostrar como fazer esse ligação.

Estou partindo do presuposto que o Eclipse já está instalado e com o plugin MTJ já configurado. Se não estiver, acesse esse link.

Para que essa documentação fique disponível dentro do Code Assist do Eclipse, acesse o menu Window > Preferences (no Mac, Eclipse > Preferences). Na janela que será exibida, no lado esquerdo, selecione Java ME > Device Management. E no lado direito, selecione ClamshellCldcPhone1 e clique em Edit...
Na tela que será exibida, clique na aba Libraries. Na coluna javadoc, selecione as "..." da API cldc_1.0.jar.
Na tela que será exibida, selecione o local onde encontra-se a documentação do Java ME no seu computador. Aos usuário de Mac, o Java ME SDK é distribuído em um arquivo *.app, sendo assim, para selecionar a documentação você deve copiar o endereço da documentação a partir do Finder (ou do terminal) e colar no campo da tela. No meu caso, estava no seguinte local:/Applications/Java_ME_SDK_3.0.app/Contents/Resources/docs/api/midp-2.0.zip.
Feito isso, clique em Ok. Em seguida, repita os paços para as APIs cldc_1.1.jar, midp_2.0.jar e midp_2.1.jar.
Após isso, já podemos ver o javadoc da documentação da classe dentro do Eclipse.

4br4ç05,
nglauber

sexta-feira, 7 de janeiro de 2011

ANT + Antenna

Olá povo,

Esse post vai em homenagem a primeira turma de pós-graduação em Tecnologias para Desenvolvimento de Aplicações Movéis do CESAR.edu que aguentaram o mico que eu paguei quando o exemplo que eu vou mostrar nesse post não funcionou na sala. Então lá vai...

Vou demonstrar nesse post como utilizar o Ant e o Antenna. O Ant é uma ferramenta para automatização de scripts desenvolvida pela Apache Foundation. Baseia-se em tarefas a serem executadas e descritas em um arquivo XML (chamado de build file).

O Antenna é uma biblioteca que pode ser adicionada ao Ant para prover um conjunto de tarefas exclusivas para o desenvolvimento com Java ME. As tarefas realizadas pelo Antenna executam o trabalho que o WTK realiza, porém, com elas o processo de deploy (geração de um JAR/JAD) da aplicação fica mais flexível e independente de IDE.

Uma das grandes vantagens da utilização dessas ferramentas é auxiliar a prover portabilidade para a diversidade de fabricantes e modelos de aparelhos existentes no mercado, uma vez que tamanho de tela, quantidade e disponibilidade de teclas, formato de áudio e vídeo suportados são algumas das características que variam bastante de modelo para modelo.

Supondo que já temos o Eclipse configurado para Java ME, precisamos apenas baixar o JAR do Antenna que está disponível aqui. Depois, basta configurar no Eclipse o local onde você baixou o JAR. Para isso, acesso o menu Window > Preferences. No lado esquerdo, selecione Java ME, e preencha o campo Antenna JAR com o nome e local onde está o JAR do Antenna.

Vamos utilizar um projeto Java ME bem simples no Eclipse para demonstrar a utilização do Ant+Antenna. A estrutura final do projeto ficará como na imagem abaixo:


Vamos começar detalhando a classe PrincipalMIDlet.java:

public class PrincipalMIDlet extends MIDlet {

protected void startApp() {
Display.getDisplay(this).
setCurrent(new MeuCanvas());
}

protected void destroyApp(boolean uncond){
notifyDestroyed();
}

protected void pauseApp() {
}
}

class MeuCanvas extends Canvas {
//#ifdef operadora
//#expand private String OPERADORA = "%operadora%";
//#else
private String OPERADORA = "Indefinido";
//#endif

//#ifdef background
//#expand private int COR_BACKGROUND = %background%;
//#else
private int COR_BACKGROUND = 0;
//#endif

private static final int COR_TEXTO = 0xFFFFFF;

private Image icon;

public MeuCanvas() {
try {
icon = Image.createImage("/icon.png");
} catch (IOException e) {
}
}

protected void paint(Graphics g) {
int w = getWidth();
int h = getHeight();

g.setColor(COR_BACKGROUND);
g.fillRect(0, 0, w, h);

g.drawImage(icon, w/2, h/2,
Graphics.BOTTOM | Graphics.HCENTER);

g.setColor(COR_TEXTO);
g.drawString(OPERADORA, w/2, h/2,
Graphics.TOP | Graphics.HCENTER);
}
}

A parte bacana do código acima, está na definição das constantes OPERADORA e COR_BACKGROUND. Notem que elas estão envolvidas por trechos de código que aparentemente são comentários do Java, mas na verdade elas são diretivas de pré-processamento. Esse recurso é possível graças ao Antenna, que faz com que essas diretivas tenham funcionalidade similar as diretivas de compilação da linguagem C.

A instrução //#ifdef verifica se uma determinado símbolo foi definido, em caso positivo, o código-fonte que estiver dentro dessa diretiva é o que será compilado, caso contrário será compilado o código que está dentro da diretiva //#else. Toda diretiva //#ifdef deve ser fechada com a diretiva //#endif.

A diretiva //#expand substituirá qualquer símbolo que estiver entre "%" com seu respectivo valor. No nosso exemplo, definimos dois arquivos de símbolos que contêm os símbolos "operadora" e "background". Esses arquivos são mostrados abaixo:

#Claro.symbols
operadora='Claro'
background='0xFF0000'

#Vivo.symbols
operadora='Vivo'
background='0x0000FF'

Um outro detalhe a ser observado é que quando a imagem icon.png foi carregada, ela não foi carregada do diretório Vivo ou Claro. Isso porque, geraremos um JAR e um JAD da nossa aplicação para cada operadora, então os recursos de cada uma delas ficará na raiz do JAR.

Vamos agora ao script de deploy. A estrutura do build.xml, está conforme a imagem abaixo:


<?xml version="1.0" encoding="UTF-8"?>

<project name="ExemploAnt" basedir="." >

<!-- Carrega as tarefas do Antenna -->
<taskdef classpath="${antenna.lib}"
resource="antenna.properties"/>

<!-- Carrega o arquivo de propriedade -->
<property file="meubuild.properties"/>

<!-- Realiza o deploy para a Vivo -->
<target name="deployVivo">
<!-- Atribui a propriedade 'operadora' que
será utilizada no restante do script -->
<property name="operadora" value="Vivo"/>

<!-- Chama a tarefa fazerDeploy -->
<antcall target="gerarJAR" />

<!-- Chama a tarefa fazerDeploy -->
<antcall target="executarMIDlet" />
</target>

<!-- Realiza o deploy para a Claro -->
<target name="deployClaro">
<property name="operadora" value="Claro" />
<antcall target="gerarJAR" />
<antcall target="executarMIDlet" />
</target>

<!-- Gera o JAR -->
<target name="gerarJAR" depends="compilar" >
<wtkpackage
autoversion="${do-autoversion}"
bootclasspath="${wtk.libs}"
jadfile="${work.dir}/deployed/${project.name}.jad"
jarfile="${work.dir}/deployed/${project.name}.jar"
libclasspath=""
obfuscate="${do-obfuscate}"
preverify="true">

<fileset dir="${work.dir}/bin/"/>
<fileset dir="${work.dir}/resources/"/>
</wtkpackage>
</target>

<!-- Compila os arquivos *,java-->
<target name="compilar" depends="preverificar" >
<wtkbuild
bootclasspath="${wtk.libs}"
destdir="${work.dir}/bin/"
encoding="UTF-8"
preverify="false"
source="1.3"
sourcepath=""
srcdir="${work.dir}/preverified/"/>
</target>

<!-- Efetua o pré-processamento dos arquivos
*.java utilizando as diretivas -->
<target name="preverificar"
depends="copiarCodigoFonte" >

<wtkpreprocess
debuglevel="info"
destdir="${work.dir}/preverified/"
printsymbols="true"
srcdir="${work.dir}/classes"
verbose="true">

<!--Carrega o arquivo de
símbolos da operadora-->
<symbols_file name="${operadora}.symbols/"/>
</wtkpreprocess>
</target>

<!-- Copia os arquivos *.java para
o diretório de build -->
<target name="copiarCodigoFonte"
depends="copiarRecursos" >

<copy overwrite="true" todir="${work.dir}/classes/">
<fileset dir="src" includes="**/**.java"/>
</copy>
</target>

<!-- Copia os arquivos de recurso para o diretório de build -->
<target name="copiarRecursos"
depends="criarDiretorios">

<copy file="Application Descriptor"
tofile="${work.dir}/deployed/${project.name}.jad"/>

<copy todir="${work.dir}/resources/">
<fileset dir="res/${operadora}"
excludes="**/**.java"/>
</copy>
</target>

<!-- Cria os sub-diretórios do diretório de build -->
<target name="criarDiretorios" depends="limparTudo" >
<!-- Dir onde ficarão JAR e JAD -->
<mkdir dir="${work.dir}/deployed/"/>
<!-- Dir onde *.java pré-processados ficarão -->
<mkdir dir="${work.dir}/preverified/"/>
<!-- Dir onde *.java serão copiados de /src -->
<mkdir dir="${work.dir}/classes/"/>
<!-- Dir dos recursos (imagens, áudio, etc) -->
<mkdir dir="${work.dir}/resources/"/>
<!-- Dir onde os *.class serão compilados -->
<mkdir dir="${work.dir}/bin/"/>
</target>

<!-- Apaga todo o diretório de build -->
<target name="limparTudo">
<delete dir="${work.dir}" failonerror="false"/>
</target>

<!-- Executa o JAR/JAD no emulador -->
<target depends="" name="executarMIDlet">
<wtkrun
jadfile="${work.dir}/deployed/${project.name}.jad" />
</target>

</project>


Como vocês puderam notar, diversas linhas do scrpit utilizam a notação ${variavel}. Isso representa uma propriedade ou um símbolo. Os símbolos estão definidos nos arquivos *.symbols e são usados para o pré-processamento. Já as propriedades são definidas no arquivo meubuild.properties (ou individualmente como é feito com a propriedade "operadora". O arquivo meubuild.propreties ficou da seguinte forma:

# Diretório raiz do WTK
wtk.home=C\:\\WTK2.5.2_01
# Deve obfuscar?
do-obfuscate=false
# Versão do MIDP e do CLDC
wtk.midp.version=2.0
wtk.cldc.version=1.1
# MIDlet deve ser auto versionado?
do-autoversion=false
# JAR do Antenna
antenna.lib=C\:\\nglauber\\J2ME\\antenna-bin-1.2.1-beta.jar
# JARs necessários na compilação
wtk.libs=C\:\\WTK2.5.2_01\\lib\\midpapi20.jar:C\:\\WTK2.5.2_01\\lib\\cldcapi11.jar:
# Nome do projeto
project.name=ExemploAnt
# Diretório de build
work.dir=output

Para executar o script de build, arraste esse arquivo para a view Ant do Eclipse. Se não estiver visível, acesse o menu Window > Show View > Other..., na janela que for exibida escolha Ant. Feito isso, basta dar um duplo-clique sobre a tarefa deployVivo ou deployClaro.

O resultado será similar a figura abaixo:



Quem quiser mais detalhes pode dar uma olhada no artigo que escrevi pra Web Mobile 29.

4br4ç05,
nglauber

sábado, 1 de janeiro de 2011

LWUIT

Olá povo,

No primeiro post de 2011, falarei um pouquinho sobre o LWUIT (Lightweight UI Toolkit). Quem já desenvolveu alguma aplicação comercial com Java ME, sabe o como é complicado criar uma UI (User Interface) amigável com os componentes padrão. Os componentes LCDUI (Liquid Cristal Display UI) estão disponíveis no pacote javax.microedition.lcdui e trazem o benefício de manter a aparência da aplicação Java ME similar a uma aplicação nativa do aparelho. Porém, esses componentes são muito limitados dado o baixo poder de processamento dos dispositivos móveis na época em que esse framework foi concebido.

O LWUIT é um framework leve (como o próprio nome diz) e bastante poderoso para criação da interface gráfica de aplicações Java ME. Ele traz algumas similaridades com o Swing do Java SE e traz diversas funcionalidades interessantes como: uma boa quantidade de componentes; transições de tela; suporte a temas, estilos e fontes personalizadas; ajuste automático a diversos tamanhos de tela.

O LWUIT pode ser baixado separadamente a partir do site da Oracle. Clique aqui para baixar o ZIP com o JAR, documentação e exemplos de uso do framework.

Descompacte o conteúdo do arquivo em qualquer lugar da sua máquina e crie um novo projeto Java ME no Eclispe. Copie o arquivo LWUIT.jar (que está dentro do diretório lib) para seu projeto e adicione-o ao Build Path. Configure para que as classes do JAR do LWUIT sejam exportadas junto com o JAR da aplicação. Para fazer isso, clique com o botão direito sobre o projeto e clique em Properties. Ao abrir as opções do projeto, clique em Java Build Path no lado esquerdo, e na aba Order and Export, marque o checkbox do LWUIT.jar.

Uma vez com o projeto configurado, podemos executar o exemplo abaixo.


import java.io.IOException;

import javax.microedition.midlet.MIDlet;

import com.sun.lwuit.*;
import com.sun.lwuit.animations.CommonTransitions;
import com.sun.lwuit.events.*;
import com.sun.lwuit.layouts.*;
import com.sun.lwuit.plaf.UIManager;
import com.sun.lwuit.util.Resources;

public class TesteLWUIT_MIDlet extends MIDlet
// Interface genérica para tratar
// eventos dos componentes
implements ActionListener {

private Command cmdLista;
private Command cmdBack;
private Command cmdTabs;
private Command cmdExit;

private Button btn1;
private CheckBox checkbox;

private Form frmLista;
private Form frmPrincipal;
private Form frmTabs;

protected void startApp() {
iniciaLWUIT();
iniciaComandos();
iniciaFormPrincipal();
iniciaFormLista();
iniciaFormTabs();
}

protected void pauseApp() {
}

protected void destroyApp(boolean arg0){
notifyDestroyed();
}

private void iniciaLWUIT() {
// Inicializando o Display do LWUIT
Display.init(this);

try {
// Carrega o arquivo de recursos
Resources r = Resources.open("/LWUITtheme.res");

// Definindo o tema da aplicação
UIManager.getInstance().setThemeProps(
r.getTheme(r.getThemeResourceNames()[0]));

} catch (java.io.IOException e) {
}
}

// Iniciando comandos que são
// utilizados nos formulários
private void iniciaComandos() {
cmdLista = new Command("Lista");
cmdBack = new Command("Voltar");
cmdExit = new Command("Sair");
cmdTabs = new Command("Tabs");
}

// Criando tela principal
private void iniciaFormPrincipal() {
// Caixa de texto com capacidade de 20 caracteres
TextField txt = new TextField(20);

// Imagem para ser associada ao label
Image img = null;
Label imageLabel = null;

try {
// Carregando a imagem
img = Image.createImage("/duke.jpeg");
// Criando Label com a imagem
imageLabel = new Label(img);
// Define o texto do Label
imageLabel.setText("Label com Imagem");
// Define a posição do texto em relação a imagem
imageLabel.setTextPosition(Label.RIGHT);

} catch (IOException e) {
}

// Criando dois botões
btn1 = new Button("Botão 1");

// Definindo alinhamento do texto do botão
btn1.setAlignment(Label.CENTER);
// Informa que o botão pode
// receber foco com o direcional
btn1.setFocusable(true);

// Informa que a classe que
// tratará evento de clique
btn1.addActionListener(this);

// Criando RadioButtons
RadioButton rb1 = new RadioButton("Masculino");
RadioButton rb2 = new RadioButton("Feminino");
// Criando o RadioGrou e adicionando os botões
ButtonGroup group1 = new ButtonGroup();
group1.add(rb1);
group1.add(rb2);

// Checkbox
checkbox = new CheckBox("Não selecionado");
checkbox.addActionListener(this);

// Combobox
String[] content = {
"Vermelho", "Azul", "Verde", "Amarelo" };
ComboBox comboBox = new ComboBox(content);

// Inicializando e configurando o formulário
frmPrincipal = new Form();
frmPrincipal.setTitle("Formulário");
// Definindo o layout do formulário.
// BoxLayout adiciona os componentes um abaixo do
// outro (Y_AXIS) ou um ao lado do outro (X_AXIS)
frmPrincipal.setLayout(
new BoxLayout(BoxLayout.Y_AXIS));
// Adicionando componentes
frmPrincipal.addComponent(new Label("Nome:"));
frmPrincipal.addComponent(txt);
frmPrincipal.addComponent(imageLabel);
frmPrincipal.addComponent(btn1);
frmPrincipal.addComponent(rb1);
frmPrincipal.addComponent(rb2);
frmPrincipal.addComponent(comboBox);
frmPrincipal.addComponent(checkbox);
// Adicionando comandos
frmPrincipal.addCommand(cmdExit);
frmPrincipal.addCommand(cmdLista);
frmPrincipal.addCommand(cmdTabs);
// Definindo qual classe
// tratará eventos de comandos
frmPrincipal.addCommandListener(this);
// Definindo animação que será feita
// ao fechar e exibir o form
// Neste caso, Slide horizontal
frmPrincipal.setTransitionOutAnimator(
CommonTransitions.createSlide(
CommonTransitions.SLIDE_HORIZONTAL,
false, 200));
frmPrincipal.setTransitionInAnimator(
CommonTransitions.createSlide(
CommonTransitions.SLIDE_HORIZONTAL,
true, 200));
// Exibe o form
frmPrincipal.show();
}

// Inicializa uma tela de Lista
private void iniciaFormLista() {
String[] itens = {
"Opção 1", "Opção 2", "Opção 3",
"Opção 4", "Opção 5", "Opção 6",};
List lista = new List(itens);

frmLista = new Form("Exemplo Lista");
// Utilizando o BorderLayout
// Ele utiliza o conceito de NORTE,
// SUL, LESTE, OESTE e CENTRO
// Ao deixar um componente no centro
// ele ocupará o espaço restante da tela,
// como só tem um, ele preencherá toda a tela
frmLista.setLayout(new BorderLayout());
frmLista.addComponent(BorderLayout.CENTER, lista);
frmLista.addCommand(cmdBack);
frmLista.addCommandListener(this);
}

// Inicializa tela com abas
private void iniciaFormTabs() {
// Inicializa o painel de abas,
// mostrandos-as em cima
TabbedPane tabbedPane =
new TabbedPane(TabbedPane.TOP);
// Cria as abas adicionando um Label nas
// duas primeiras e um TextArea na terceira.
tabbedPane.addTab("Aba 1",
new Label("Label na primeira aba"));
tabbedPane.addTab("Aba 2", new Label("Aba 2"));
tabbedPane.addTab("Aba 3", new TextArea());

frmTabs = new Form("Exemplo Tabs");
frmTabs.setLayout(new BorderLayout());

frmTabs.addComponent(
BorderLayout.CENTER, tabbedPane);
frmTabs.addCommand(cmdBack);
frmTabs.addCommandListener(this);
}

// Tratando eventos das telas
public void actionPerformed(ActionEvent event) {
if (event.getSource() == cmdLista){
frmLista.show();

} else if (event.getSource().equals(cmdBack)){
frmPrincipal.show();

} else if (event.getSource() == btn1 ||
event.getSource() == cmdTabs){
frmTabs.show();

} else if (event.getSource() == checkbox){
if (checkbox.isSelected()) {
checkbox.setText("Selecionado");
} else {
checkbox.setText("Não selecionado");
}

} else if (event.getSource() == cmdExit){
destroyApp(true);
}
}
}


Abaixo temos um screenshot das telas da aplicação em execução:




Mas porque diabos a aplicação ficou com esse aspecto? E se eu quiser mudar o esquema de cores ou fontes ou qualquer outra coisa?

Se observarmos no método iniciaLWUIT, carregamos um arquivo de recursos chamado LWUITtheme.res. Esse arquivo já vem com o LWUIT e está localizado no diretório LWUIT_1_4\LWUITDemo\src. O LWUIT trabalha com um único arquivo de recursos que permite criar temas para definir as cores e fontes de cada elemento da UI de uma aplicação. Para criar e editar esses arquivos de recursos o LWUIT disponibiliza um editor visual que pode inclusive ser utilizado por designers. Esse editor está dentro do diretório util/ResourceEdit.exe (usuários não-windows podem executar o JAR diretamente que está no mesmo diretório). Abaixo temos um screenshot do editor, se quiser abrir o tema é só abrir o arquivo LWUITtheme.res com a ferramenta:



Alguns telefones podem não gostar do tamanho que o JAR pode ficar (em torno de 500KB) :) Para isso utilize o Proguard para obfuscar o código-fonte da aplicação e esse tamanho diminuirá sensivelmente.

4br4ç05,
nglauber

quarta-feira, 8 de dezembro de 2010

Java ME: Configuração do Ambiente

Olá povo,

Nessa sexta começo minha carreira como professor universitário :) Ministrarei a disciplina de Java ME no Curso de Especialização em Engenharia de Software com Ênfase em Tecnologias para Desenvolvimento de Aplicações Móveis do CESAR.edu. Então como vocês devem imaginar, vão vir por aí alguns post sobre o assunto. O primeiro deles será sobre como configurar o ambiente e fazer o bom e velho "Hello World".

Baixando o JDK

Precisaremos incialmente do JDK que está disponível em:
http://www.oracle.com/technetwork/java/javase/downloads/index.html

A instalação em bem simples, basta seguir o assitente. (e venhamos e convenhamos, todos que estão lendo este post já devem ter o JDK na máquina :)

Baixando o WTK (Wireless Toolkit)

Para baixar o WTK devemos acessar a seguinte URL:
http://www.oracle.com/technetwork/java/javame/downloads/index.html

A versão mais recente da plataforma é a 3.0, mas atualmente ela só está disponível para Windows. Dessa forma, utilizaremos a versão 2.5.2 que está disponível para Windows e Linux.


Após baixar o WTK, basta seguir as instruções do assistente.


Instalando a IDE

Para desenvolvermos aplicações Java ME, podemos utilizar a IDE de nossa preferência. As mais famosas são o Eclipse e o Netbeans. Ambas contam com plugins para desenvolvimento para edição móvel de Java.


O Eclipse conta com uma versão especial para desenvolvimento mobile chamada Pulsar. Ela já vem com as ferramentas necessárias para criação de aplicações Java ME, e para baixá-la basta acessar: http://www.eclipse.org/pulsar/
e descompactar em qualquer lugar do seu HD.

Mas para quem já tem seu Eclipse já todo configurado, não precisa se preocupar em instalar outra versão da IDE. Basta adicionar o plugin MTJ (Mobile Tools for Java) e você terá um ambiente pronto para criar suas aplicações Java ME. Para isso, acesse o menu Help > Install new software e adicione a URL: http://download.eclipse.org/mtj/updates/1.1.2/stable e em seguida prosseguir com o assitente.


Para os desenvolvedores que utilizam o Netbeans, a IDE já pode ser baixada com o Mibility Pack. Que permite a criação de aplicativos Java ME. Caso sua versão não conte com esse plugin, basta baixa-lo dentro da própria ferramenta acessando o menu Tools > Plugins e selecionando o plugin Mobility.

Configurando a IDE para o SDK

Uma vez que temos o SDK e a nossa IDE favorita instalados, devemos fazer a ligação de ambos.

Para o Eclipse faremos o seguinte:
1) Acesse o menu Window > Preferences;
2) Clique em Java ME e em seguida preencha o campo WTK home com o local onde o WTK está instalado;
3) Na mesma janela, clique em Device Management que é um subitem de Java ME. Clique no botão Manual Install... para informar os emuladores que iremos utilizar.
4) Abrirá a janela Manual Device Installation, clique no botão Browse... e selecione o diretório de instalação do WTK.
5) Clique em Finish para fechar a tela atual e OK para fechar a tela de configuração.

Para o Netbeans:
1) Acesse o menu Tools > Java Plaforms;
2) Clique em Add Platform. Em seguida, selecione Emulator for Java ME Platform e clique em Next;
3) O assistente deve achar o local da instalação automaticamente, caso contrário indique o local da instalação e clique em Next.
4) Clique em Finish e a configuração estará concluída.


Hello World!!!

Vamos agora satisfazer os deuses da programação e fazermos um HelloWorld com a plataforma Java ME.

Eclipse
1) Acesse o menu File > New > Project...
2) Em seguida, selecione Java ME > MIDlet Project
3) Dê o nome de HelloWorld ao projeto e clique em Finish
4) Na pasta src clique com o botão direito, e selecione New... > Java ME MIDlet
5) Abrirá o assitente de criação de classes. Dê a classe o nome de HelloWorldMIDlet e clique em Finish

Netbeans
1) Acesse o menu File > New project...
2) Na categoria Java ME, selecione Mobile Application
3) Dê o nome de HelloWorld ao projeto.
O Netbeans já disponibiliza uma opção que cria o HelloWorldMIDlet (estraga prazer:) Desmarque essa opção e clique em Finish.
4) Na pasta src clique com o botão direito, e selecione New... > MIDlet...
5) Abrirá o assitente de criação de classes. Dê a classe o nome de HelloWorldMIDlet e clique em Finish

Agora, deixe a classe HelloWorldMIDlet conforme abaixo:
public class HelloWorldMIDlet extends MIDlet {
public HelloWorldMIDlet() {
Display d = Display.getDisplay(this);

Form form = new Form("Hello!");
form.append("Olá mundo Java ME");

d.setCurrent(form);
}

protected void destroyApp(boolean unconditional) {}

protected void pauseApp() {}

protected void startApp() {}
}


No Eclipse, clique com o botão direito sobre o projeto e selecione: Run as > Emulated Java ME JAD.
No Netbeans, basta clicar no botão play verdinho :p

Quando o emulador for executado, clique na tecla do celular correspondente a opção Launch. O resultado deve ser conforme a figura abaixo:



Qualquer dúvida ou sugestão, deixem seus comentários.

4br4ç05,
nglauber

quinta-feira, 7 de outubro de 2010

Especialização em TECNOLOGIAS PARA DESENVOLVIMENTO DE APLICAÇÕES MÓVEIS

Olá povo,

O CESAR.edu está lançando o curso de Especialização em Engenharia de Software com ênfase em Tecnologias para Desenvolvimento de Aplicações Móveis (TECDAM) onde o aluno aprenderá a desenvolver aplicações para as plataformas: Android, iOS (iPhone, iPad e iPod), Windows Mobile, Windows Phone 7, BADA, Java ME, Flash Lite, .Net Compact Framework, Appcelerator, Elips, Adobe Air, W3C Widgets, Silverlight e XNA.

O curso será ministrado as sextas (das 18:30 as 22:00) e aos sábados (08:00 as 17:00) nas instalações do CESAR, com aulas práticas e com o apoio de professores que além de experiência em sala de aula, são profissionais especializados nas disciplinas que ministram.

Para obter mais informações clique aqui.

4br4ç05,
nglauber

quinta-feira, 8 de abril de 2010

Artigo "Ant + Antena com Java ME"


Olá povo,

A revista Web Mobile desse mês (edição 29) estampa em sua capa um artigo escrito por mim, juntamente com meu nobre colega Jorge Fonseca e uma outra pessoa.

O artigo mostra na prática como realizar reuso de código utilizando as ferramentas Ant e Antenna, visando customizar aplicações Java ME. Essas ferramentas permitem a criação de várias versões da mesma aplicação para vários aparelhos a partir de um único código-fonte. Na revista essas tecnologias são demonstradas através de um exemplo prático com o intuito de facilitar o seu entendimento.

Espero que os desenvolvedores Java ME gostem.

4br4ç05,
nglauber

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