quarta-feira, 13 de agosto de 2008

Artigo na Java Magazine

Ola a todos!


Sei que estou um pouco afastado dos posts, mas as mudanças recent
es me fizeram dar uma afastada. Porém, a um tempo atrás havia enviado ao pessoal da revista um artigo sobre a biblioteca LWUIT e esse mês a revista, com o artigo, foi publicada.
A revista apresenta uma reformulação que a tornou mais atrativa ainda. Vale a pena conferir, e abaixo segue a imagem da capa, extraída do site da DevMedia.

quinta-feira, 26 de junho de 2008

Mudando o nome do blog...

Ola pessoal,

Quando fui ao Forum Nokia Tech Days em São Paulo, o Python me surpreendeu e foi realmente uma boa surpresa. Porém, ficou uma dúvida de quando utilizar, já que trabalho em uma empresa onde quando fazemos um produto não podemos focar em nenhuma plataforma especifica e aí ficou aquele gostinho de frustração.

Mas, a alguns dias a lista de Java ME do SouJava começou a ser "palco" de diversas de threads com o assunto relacionado as diversas plataformas disponíveis para o mundo móvel. Isso me fez pensar que na verdade, devemos estar preparado para criar softwares móveis independentes da plataforma. Pois a "melhor" plataforma é aquela que te atende naquele projeto e que irá trazer o melhor resultado considerando: qualidade, desempenho e custo.
E então, para "juntar" tudo, estou tendo que fazer uma pesquisa sobre uma solução para ser apresentada para um cliente e a melhor solução está parecendo ser usar aparelhos da S60 com o aplicativo feito em Python ou C++. Por isso comecei a fazer várias pesquisas e testes com diversas soluções.

Por isso, resolvi mudar o nome desse blog que era "Neto Marin JME Blog" para "Neto Marin Mobility Blog" onde irei também colocar relatos de experiências que estou fazendo com Python e outras linguagens. Espero que gostem dessa mudança também! :)

[]s
Neto

terça-feira, 24 de junho de 2008

Ajude a sustentar a Wikipédia e outros projetos, sem colocar a mão no bolso, e concorra a um Eee PC!

Ajude a sustentar a Wikipédia e outros projetos, sem colocar a mão no bolso, e concorra a um Eee PC!
…e também a pen drives, card drives, camisetas geeks, livros e mais! O BR-Linux e o Efetividade lançaram uma campanha para ajudar a Wikimedia Foundation e outros mantenedores de projetos que usamos no dia-a-dia on-line. Se você puder doar diretamente, ou contribuir de outra forma, são sempre melhores opções. Mas se não puder, veja as regras da promoção e participe - quanto mais divulgação, maior será a doação do BR-Linux e do Efetividade, e você ainda concorre a diversos brindes!

E o Android vai atrasar...

É pessoal, para aqueles quem vinham apostando no Android e falando empolgantemente que o Google iria dominar também a área de dispositivos móveis, eles jogaram um grande e cheio balde de água fria!
Ontem foi anunciado que o lançamento do Android foi atrasado do segundo para o quarto quarto do ano. Ou seja, o pessoal vai ter que continuar "brincando" com o emulador do Android. É, digo brincar porque na minha opinião é para isso que serve o Android por enquanto.

Sei que vários vão querer me jogar pedra por falar isso, mas por enquanto não é possível testar uma aplicação Android, é impossível saber o seu real desempenho (que na minha opinião não deve ser nada bom), portabilidade. Enfim, para aqueles que estão no mercado sabem que esses são aspectos determinantes para o sucesso de uma aplicação móvel. Nada adianta ela ser bonitinha (como o Android aparenta ser) se ela não for fácil de usar e não tiver um desempenho razoável.

Não que eu torça contra, mas eu acho que se o Android não "pertencesse" ao Google, já teria nascido morto!!! ;-)

Para mais detalhes, visite: http://mobhappy.com/blog1/2008/06/24/check-mate-for-googles-android/

[]s
Neto

quarta-feira, 18 de junho de 2008

Novo número: 130 milhões de celulares no Brasil !!

Ola pessoal,

Apenas para comentar a noticia que acabo de encontrar no G1 Tecnologia, que diz que em maio o número de assinantes foi de 130,5 milhões. E além disso, o mês apresentou o incrível número de 2,8 milhões de novas assinaturas. Grande parte impulsionadas pelo dia das mães. Outro dado que chama atenção é a grande proporção de telefone pré-pagos, que representam um total de 80,9% do total das habilitações no Brasil.
Claro que essa quantidade de celulares pré-pagos diminui em muito a empolgação daqueles que sonham em fazer aplicações e serviços para a rede e tal. Mas, não se pode desprezar os outros 19% que representam um total de aproximadamente 24,7 milhões !! Bom, mas isso seria conversa pra pelo menos uns 2 ou 3 posts seguidos! ;-)

Quem quiser mais informações, veja a matéria completa em: http://g1.globo.com/Noticias/Tecnologia/0,,MUL605604-6174,00-NUMERO+DE+CELULARES+NO+PAIS+SUPERA+OS+MILHOES+EM+MAIO.html

[]s
Neto

terça-feira, 17 de junho de 2008

Widgets e Code Camp !!

Ola pessoal,

De volta a Campinas, resolvi fazer um resumo de como foi o code camp e sobre o tema desse code camp: Widgets!!

O Code Camp:
O dia começou com o pessoal chegando cedo, principalmente pra achar uma tomada e pegar uma vaguinha na rede ;-) e além disso, estava todo mundo querendo achar uma grande idéia para conseguir ganhar um N95 com 8 GB :D
No inicio a idéia era fazer algo utilizando a API do GoogleCalendar ou algum tipo de rede "social". Mas ai, surgiu uma idéia que parecia boa: um "navegador" pelos bookmarks do del.icio.us, exibindo os links salvos, as tags e etc. Acabamos tendo alguns problemas com a integração XML + JavaScript + CSS e ai no final conseguimos fazer apenas a listagem dos links salvos e ai abrir o navegador ao clicar no link.

Várias aplicações interessantes foram mostradas, mas a vencedora foi uma onde o pessoal executava um comando no widget (notepad, calc, cmd, etc) e o pc que era o servidor executava o comando, tirava uma "foto" (screenshot) e então enviava para o celular.

Widgets
No site do Forum Nokia há bastante material sobre como criar os widgets. Mas, resumindo é uma página HTML onde você pode utilizar JavaScript e CSS para fazer as interações e executar ações com o usuário. Nada que você já não tenha visto em páginas de internet comum. E alem disso, para ajudar, a Nokia oferece um kit básico que contém elementos que facilitam sua interação, como por exemplo: TextField, UIManager, Label, ListSelections e outros.

Para saber mais sobre widgets acesse http://www.forum.nokia.com/main/resources/technologies/browsing/widgets.html e tenha acesso a "getting started", exemplos, APIs e muito mais.

E o futuro?
Olha pessoal, eu não sou fã de HTML e muito menos (mas muito menos mesmo) fã de JavaScript. Porém, não tem como não dizer que os widgets são a forma mais simples para se criar uma pequena aplicação móvel. Ele pode servir como a porta de entrada para um serviço qualquer da web, ou até para difundir mais facilmente um serviço que você queira oferecer.
Além disso, a Nokia parece estar apostando muito nessa nova "leva" de aplicativos móveis e inclusive através do site Mosh (http://mosh.nokia.com) você pode publicar seu widget e assim ter muitos usuários acessando seus serviços.

Logo que acertar o que ficou errado no meu widget eu posto pra vocês aqui.

[]s
Neto

Começando o segundo dia...

Bom dia pessoal,

Estamos começando o segundo dia e no momento estamos ouvindo Ravi e Daniel falando sobre a criação de widgets para a S60, na verdade está primeiro mostrando o site do Forum Nokia. É bem interessante pois se trata de um novo conceito de "aplicativo" móvel e forma de interação com o usuário.
Na parte da tarde haverá um code camp e o melhor widget dará a dupla vencedora um device N95 para cada um. Ainda estou sem idéias, mas até a hora do almoço alguma irá aparecer =)

Material do evento
Para aqueles que querem material do Nokia Forum Tech Days e saber mais sobre o que está acontecendo pode visitar a página do evento em: http://wiki.forum.nokia.com/index.php/Tech_Days_Brasil_08

Quando acabar o meu widget e tiver mais detalhes faço um novo post contado como se faz e etc.

[]s
Neto

segunda-feira, 16 de junho de 2008

Desenvolvimento em C++ ou Python para Symbian S60

Ola pessoal,

Já tivemos hoje uma palestra sobre desenvolvimento em C++ com o Ravi Belwal e depois uma outra palestra muito interessante com o Daniel Rocha falando sobre o desenvolvimento com Python e inclusive com alguns exemplos. E até o exemplo de um player de música onde é possível trocar de faixa "balançando" o celular.

Desenvolvimento com C++
O que podemos resumir da programação com C++ é que, não é tão complexo quanto se acha que é, porém ainda possui suas particularidades. Mas, sempre vai ser possível ter acesso as mais novas bibliotecas disponíveis até porque é a linguagem nativa do SO.

Python e Symbian S60
É indiscutível que a produtividade e simplicidade de se programar em Python é muito melhor em relação ao C++ ou ao próprio JME, pois inclusive é possível ter acesso a "trechos" do sistema que não são alcançados pelo Java porém, na minha humilde opinião, é mais um passo em direção a segmentação!!!
Afinal, se você tem uma empresa e cria um produto com certeza irá querer que esse produto alcance o maior número de dispositivos possíveis, mas, programando com Python você verá a quantidade de dispositivos "alvos" diminuirem muito.

Então não vale a pena usar Python ?!?!
Eu diria que tudo DEPENDE. Vamos supor a sequinte situação: Você possui um escopo fechado e um alvo bem definido. E além disso você precisa de recursos que te permitam acessar funcionalidades especificas de algum dispositivo, então, use Pyton e seja feliz!!
Agora, você quer desenvolver um produto corporativo onde você não possui muita influência sobre o que seus clientes vão usar, então prefira Java ME ! :D

Mais tarde volto com mais "flashes" aqui do evento.

[]s
Neto

Forum Nokia Tech Days - Brasil

Ola pessoal,

Estou aqui no hotel Gran Meliá em São Paulo participando do primeiro dia do Forum Nokia Tech Days. A primeira vista parece ser bem empolgante, principalmente por mais uma vez a Nokia estar mostrando que realmente se preocupa com a comunidade de desenvolvedores e além de tudo, ajudar a gerar negócios com isso.

Uma coisa que me chamou bastante atenção foi o portal "OVI" (http://www.ovi.com) que busca trazer diversos serviços e formar de integrar os serviços que a Nokia oferece a sua plataforma. E como os próprios palestrantes disseram, a Nokia está se reformulando e oferencedo diversas novas oportunidades!

Bom, vou indo porque minha bateria está se acabando e ainda não consegui achar uma tomada!! =( Mas logo, volto com mais alguns detalhes e dicas para aqueles que estão curiosos sobre esse evento!!

[]s
Neto

quarta-feira, 11 de junho de 2008

Classe Properties para JME

Ola pessoal,

Esses dias tive que armazenar e trafegar algumas configurações de aplicações móveis. E ai, pra facilitar minha vida resolvi usar o esquema de properties. Ou seja, uma chave = valor.
E você pode pensar que estou ficando louco né!!! Afinal nem a implementação da classe Properties existe e além disso o dispositivo deve implementar a JSR 75 para que seja possível salvar esse properties em "formato" de arquivo.

Mas utilizando properties eu tenho algumas vantagens:

  • Padronização na forma de montagem de dados.
  • Não há necessidade de fazer muitos parses, afinal a forma de composição é bem simples!
  • Causa pouco acréscimo de dados. Compare com XML ! =)
E além das vantagens, não é somente possivel salvar em arquivo. Assim como a implementação da classe Properties em JSE, você consegue obter um OutputStream e ai, gerar um ByteArrayOutputStream obtendo um array de bytes e salvar em um RMS! =)
Também é possível receber um arquivo properties enviado através de um HTTP e utilizando InputStream, carregar o properties de forma automática e transparente!

Quem se interessar, basta clicar aqui para fazer o download do zip que contém o .java da classe que implementei! Fiquem a vontade para usar, alterar e etc.
A classe não implementa TODOS os métodos da original porque não tive tempo e porque não me interessava quando a criei. Mas, acho que pode facilitar a vida de alguns!

Se tiver interesse em exemplos de como utilizar, deixe seu comentário!!!

[]s
Neto

segunda-feira, 26 de maio de 2008

FishEyeList com LWUIT

Ola pessoal,

Continuando com minhas experiências com a biblioteca LWUIT, fiz agora um outro tipo de menu: um FishEyeList !!
Ou seja, conforme você alterna entre os itens da lista, o ícone correspondente fica maior, dando um destaque e indicando que item está selecionado. Esse tipo de lista ficou muito conhecida com o uso de Ajax e também com iPhone. E agora, você vai poder ter essa lista, fácil... fácil... na sua aplicação Java ME! ;-)



A lista
Esse tipo de menu em relação ao apresentado antes tem uma vantagem, usar menos imagem. Isso porque para dar o efeito de que a imagem está maior que a "normal" não é necessário gerar outra, mas sim utilizar o método image.sclaed(nova_larga, nova_altura).

O exemplo
Esse exemplo também foi todo feito em uma única classe MIDlet, FishEyeListMIDlet, e que tem o método montaFishEyeList que é chamado no startApp para que seja exibido o Form com o menu. E as ações dos botões são tratadas no actionPerformed, como vc já está se acostumando a ver aqui nesse blog! ;-)

montaFishEyeList( )
É o método que monta o menu com a FishEyeList. Para que ele faça a montagem, o método recebe 2 parametros:

  • Image[] icone: Array com os ícones a serem utilizados nos botões.
  • String[] label: Strings com os labels a serem utilizados nos botões.
No inicio do método há a criação do Form e a definição da figura de fundo. Também nesse ponto é definido o layout para o Form, que nesse caso será utilizado o layout BoxLayout e com a orientação no eixo Y, ou seja, cada item adicionado será colocado em uma linha dando a "impressão" de uma lista. O código relativo a essa parte se encontra abaixo:
Form fishEyeForm = new Form("FishEye List");
fishEyeForm.setLayout(new BoxLayout(BoxLayout.Y_AXIS));
try {
fishEyeForm.setBgImage(Image.createImage("/background.png"));
} catch (IOException e) {}
Depois disso, é a hora de adicionar os botões e definir o comportamento de cada um. Isso será feito dentro de um loop que irá percorrer cada item dos arrays recebidos e em cada iteração serão executadas as seguintes ações:
  • Criação de um novo botão, com o texto e a imagem do array (utilizando o indice do loop). A forma de instanciar o novo botão é new Button(label[i], icone[i]).
  • Quando um botão é selecionado, o LWUIT coloca automaticamente uma cor indicando a seleção do botão. Para isso não acontecer e "atrapalhar" o comportamento usamos o método setBgTransparency(0).
  • O comportamento do botão precisa ser controlado por alguém e nesse caso, o midlet do exemplo é quem implementa a interface ActionListener e que deverá ser passado como parametro para o método addActionListener.
  • O efeito de FishEye (aumento da imagem) é feito alterando a imagem que é exibida quando o item está selecionado, através do método setRolloverIcon, e nesse caso aumentando o tamanho da imagem. No exemplo o aumento é de 30% da imagem utilizando o método scaled da imagem passada.
  • Além disso, o ícone também tem seu tamanho diminuido em 20% quando é clicado. Isso também é feito com o método scaled sendo passado para o método setPressedIcon.
  • O normal de um botão é ter sua borda desenhada para melhorar a visualização do componente. Porém, como estamos utilizando em um menu e o foco é a imagem a ser mostrada, a borda pode não ser desenhada. Para providenciar isso, iremos utilizar o método setBorderPainted(false).
O código do loop e criação do botão segue abaixo:
//criando os botões
Button b = null;
for ( int i = 0; i < icone.length; i++ ) {
b = new Button(label[i], icone[i]);
b.getStyle().setBgTransparency(0);
b.addActionListener(this);
b.setRolloverIcon(icone[i].scaled((int)(icone[i].getWidth()*1.3),
(int)(icone[i].getHeight()*1.3)));
b.setPressedIcon(icone[i].scaled((int)(icone[i].getWidth()*0.8),
(int)(icone[i].getHeight()*0.8)));
b.setBorderPainted(false);
fishEyeForm.addComponent(b);
}
Tratando o uso do botão
Pessoal, nesse ponto para não perder muito tempo e não extender muito o post, veja esse mesmo tópico no post anterior, pois essa parte é exatamente igual a anterior! ;)

Download e código completo
Para facilitar, todo o código do exemplo pode ser baixado em um ZIP, clicando AQUI, e dentro da pasta deployed é possível encontrar o JAR e JAD da aplicação para você ver o exemplo funcionando ou até instalar no seu celular.

[]s
Neto

sábado, 24 de maio de 2008

Ola pessoal,

Continuando no assunto da biblioteca LWUIT, resolvi fazer um menu e assim comparar também com o menu em canvas que fiz a um tempo aqui e que é o post mais acessado... disparado!!! :)
O menu também será bem simples, como foi o seu antecessor. Seu comportamento será da seguinte forma: na navegação há mudança na imagem indicando que o item está selecionado e quando clicado é disparado alguma ação, no nosso exemplo um Alert ("convencional"). Abaixo, imagens de como ficou:


As imagens do menu
Para deixar o menu com uma visualização melhor, para cada opção eu escolhi um icone e criei uma outra imagem com uma iluminação para dar impressão de que está apagado. Então, a cada vez que um icone é selecionado a imagem que foi indicada na criação do botão é trocada pela imagem que parece "acesa".
O único cuidado com essa prática é a questão de desempenho, pois se você escolher muitos ícones e icones muito grandes o desempenho pode cair muito e ao invés de ajudar, apenas piorar.

O exemplo
Para ilustrar, o exemplo consiste em apenas um MIDlet que contém um método chamado montaMenuForm( ) e que é chamado no startApp para retornar o Form que será exibido para o usuário. As imagens são carregadas no construtor.

montaMenuForm( )
É o método responsável por montar o Form com o menu e retornar para que ele seja exibido. Esse método recebe três parametros:

  • Image[] icones: Array com todos os icones que serão utilizados quando o itens estão selecionados.
  • Image[] iconesOff: Array com todos os icones que serão utilizados na criação do botão e quando o mesmo não está selecionado.
  • String[] label: Array de String para o label do botão.
Dentro do método, no inicio há a criação do Form, definição do background e configuração do layout a ser utilizado. No exemplo foi definido que será exibido 4 icones por linha e a quantidade de linhas do menu foi calculado de acordo com o número de itens do array, o trecho do código é o seguinte:
//Criando form
//Criação do Form
Form menu = new Form("Menu LWUIT");
try {
//definindo background
menu.setBgImage(Image.createImage("/background.jpg"));
} catch (IOException e) {}

//Montagem do layout
//4 colunas
int cols = 4;
//Calculando quantidade de linhas
int rows = (int)Math.floor(icones.length/4);
//Layout de exibição em grids
menu.setLayout(new GridLayout(rows,cols));
Depois de montado o layout, é hora de adicionar os botões e definir o comportamento de cada botão. Para isso será feito um loop pelo array de imagens e em cada interação serão executadas as seguintes ações:
  • Criação de um novo botão, com o texto e a imagem do array de imagens "não-selecionadas" (utilizando o indice do loop). A forma de instanciar o novo botão é new Button(label[i], iconesOff[i]).
  • Definir a imagem que será exibida quando o item do menu estiver selecionado, através do método setRolloverIcon passando como parametro a imagem do array de imagens selecionadas, também de acordo com o indice do loop.
  • Definir a imagem que é exibida quando o item é clicado, através do método setPressedIcon passando como parametro a imagem do array de imagens selecionadas, também de acordo com o indice do loop.
  • Quando um botão é selecionado, o LWUIT coloca automaticamente uma cor indicando a seleção do botão. Para isso não acontecer e "atrapalhar" o comportamento usamos o método setBgTransparency(0).
  • O normal de um botão é ter sua borda desenhada para melhorar a visualização do componente. Porém, como estamos utilizando em um menu e o foco é a imagem a ser mostrada, a borda pode não ser desenhada. Para providenciar isso, iremos utilizar o método setBorderPainted(false).
  • E por fim, o comportamento do botão precisa ser controlado por alguém e nesse caso, o midlet do exemplo é quem implementa a interface ActionListener e que deverá ser passado como parametro para o método addActionListener.
O código do loop e criação do botão segue abaixo:
//Criando botões e adicionando ao grid
for ( int i = 0; i < icones.length; i++ ) {
b = new Button(label[i], iconesOff[i]);
//imagem para exibir ao selecionar botão
b.setRolloverIcon(icones[i]);
//imagem para exibir ao clicar no botão
b.setPressedIcon(icones[i]);
//Removendo o fundo de seleção do botão
b.getStyle().setBgTransparency(0);
//alinhamento e posição do texto do botão
b.setAlignment(Button.CENTER);
b.setTextPosition(Button.BOTTOM);
//não desenhar borda no botão
b.setBorderPainted(false);
//indicando o listener do botão
b.addActionListener(this);
//adicionando o botão ao form
menu.addComponent(b);
}
Tratando o uso do botão
Quando o usuário clica no botão é necessário tratar esse botão. Esse tratamento é feito através do método actionPerformed na classe que implementar a interface ActionListener. No nosso exemplo isso é feito no midlet da aplicação.
A programação desse método pode ser feita conforme cada programador desejar, o importante nesse ponto é identificar qual botão foi clicado e ai direcionar corretamente o usuário. O método recebe o objeto ActionEvent que permite que através do método getSource() seja recuperado o objeto que originou a chamada, e no nosso caso o botão cliclado.
Com o botão clicado, para distinguir qual botão foi clicado usaremos o texto que foi indicado na criação do botão através do método getText() e ai então, exibir um Alert. Nesse caso, customize qual ação deseja tomar. Um trecho desse método segue abaixo:
public void actionPerformed(ActionEvent evt) {
//Obtendo botão que disparou o evento
Button b = (Button) evt.getSource();
//Verificando pelo titulo qual botão é
if ( b.getText().equals("Bluetooth")) {
Alert a = new Alert("Selecionado", "Bluetooth", null, AlertType.INFO);
javax.microedition.lcdui.Display.getDisplay(this).setCurrent(a);
} else if ( b.getText().equals("Pesquisar")) {
Alert a = new Alert("Selecionado", "Pesquisar", null, AlertType.INFO);
javax.microedition.lcdui.Display.getDisplay(this).setCurrent(a);
}
//Continua comparações
//definindo focus
menu.setFocused(b);
}
Download e código completo
Para facilitar, todo o código do exemplo pode ser baixado em um ZIP, clicando AQUI, e dentro da pasta deployed é possível encontrar o JAR e JAD da aplicação para você ver o exemplo funcionando ou até instalar no seu celular.

Conclusão e comparação
Bom, quem já viu o outro exemplo e esse agora pode de cara perceber que esse tem um melhor acabamento e é muito mais facil de ser criado e customizado. Porém, o overhead causado pela quantidade de imagens necessárias e pela inclusão da biblioteca LWUIT. Para ver isso, basta comparar o tamanho das duas aplicações.
Mas, na minha opinião, se for um menu pequeno e com imagens não tão complexas, o uso vale a pena!! E além disso, você pode estudar e fazer o menu de uma forma que atenda melhor suas necessidades!

[]s
Neto

terça-feira, 20 de maio de 2008

Uma pequena análise da LWUIT

Ola pessoal!!

Essa semana eu tive a oportunidade de escrever um artigo sobre essa interessante biblioteca e para ilustrar o artigo acabei montando uma aplicação de exemplo e então consegui tirar algumas conclusões e vou dar algumas opiniões aqui para vocês! :)

Nova forma de programar
Como os próprios autores declararam no site do projeto, a LWUIT foi feita pensada no Swing, então a forma de utilizar alguns componentes é bem parecida com seus "similares" no Swing, como por exemplo um Button. Abaixo, um exemplo onde se cria um botão e define a chamada de um método estático qualquer quando um botão é clicado:

Button botao = new Button("Processar");
botao.addActionListener(new ActionListener(){
public void actionPerformed(ActionEvent evt) {
//chamada para um método qualquer...
}});
Para alguns que não possuem muita vivência com Swing (como é o meu caso), algumas coisas podem soar estranhas, mas considero ser apenas questão de costume pois apesar de diferente são bem simples.

Novos recursos interessantes
Algumas das principais funcionalidades que o LWUIT oferece, podem ser consideradas como novas versões de funcionalidades já existentes no pacote javax.microedition.lcdui. Porém, a biblioteca traz algumas novidades como por exemplo: caixa de diálogo, abas, transição entre telas, novas opções de fonte, criação de temas. Além de automatizar (facilitando também é claro) alguns comportamentos, como por exemplo o scrol de uma tela.
Acima imagens retiradas da aplicação demo fornecida pelo projeto.

Estabilidade
É claro que por se tratar de um "lançamento" ainda há alguns pequenos ajustes a serem feitos. Como é o caso do TabbedPane que aceita um Component como paramêtro e então, eu resolvi criar um Form com diversos componentes e colocar esse Form dentro de uma aba. Compilou, executou e foi exibido corretamente, mas quando tentei usar não conseguia entrar na aba que eu queria e a navegação pelas abas ficava completamente perdida.
O que fazer então? Mandei um e-mail na lista de users do projeto e recebi a resposta de que realmente isso não funciona, e que eles iriam colocar uma exception de illegalargument no caso de alguém tentar fazer a mesma coisa, já que eu não era o primeiro a perguntar sobre isso.
Enfim, a melhor coisa a fazer é entrar em contato com o pessoal e repassar os problemas e assim ajudarmos a biblioteca a evoluir!!

Ferramenta deskotp
Como dito antes, é possivel se criar temas para o LWUIT e isso é feito através de uma aplicação desktop bem simples de usar, onde você vai configurando cada tipo componentes a ser utilizado e seu estilo. Permitindo assim um alto nivel de acabamento da sua aplicação.

Performance
É claro que a performance em alguns casos deixa a desejar, porém isso acontece principalmente se você sobrecarregar sua aplicação com tudo que o LWUIT lhe oferece. Mas você pode fazer a mescla de componentes LWUIT e componentes high level.
Por exemplo: Pode ser feito um menu utilizando um Form com o Layout grid e com diversos botões, e após isso, utilizar os forms (ou lists) comuns e sua aplicação continuará "leve".

Conclusão
É uma biblitoeca que me surpreendeu, assim como a mais pessoas, e que com certeza colaborará com a melhoria da qualidade das interfaces e na facilidade do desenvolvimento. Mas, deve ser utilizado com muito cuidado, pois pode comprometer a sua aplicação. Tente sempre testar em dispositivos reais para ter uma noção desse comprometimento. E é claro, contribua enviando sugestões e notificando possiveis bugs. Pois assim, ela vai sendo "polida" e cada vez mais melhorada!

E atenção, estou preparando um menu utilizando um Form com Button e que teria o comportamento similiar a um menu que publiquei a muito tempo atrás aqui e que é o post mais acessado. E assim, poderemos comparar a facilidade e agilidade no desenvolvimento. Aguardem!!!

[]s
Neto

sábado, 17 de maio de 2008

Usando StringItem para fazer listagens.

Ola pessoal,

Algumas vezes queremos fazer algumas listagens em nossos Forms, ou mesclar conteúdo e permitir uma navegação pelos itens e a sua seleção e o uso da lista compromete a usabilidade ou simplesmente não funciona!
Por exemplo, aqueles que já tiveram a oportunidade de usar o JustJava mobile no ano passado (com a grade horária) ou já deu uma olhada no CoSMo (que "nasceu" do JustJava Mobile), viram que na listagem das palestras do dia é possível clicar em uma determinada palestra e ver o detalhe dessa palestra, como nas figura abaixo:

O problema nesse caso é que os nomes dos locais e o título das palestras poderia ser grande, e como eu não confio muito no comportamento do List em diferentes dispositivos, a solução intuitiva era usar StringItem !!
Mas ai eu tinha um problema: Como "descobrir" em qual palestra o usuário clicou para exibir o detalhe corretamente?
No List (ou ChoiceGroup) seria fácil, já que eu tenho o indice selecionado. Então, o mais fácil era ter um indice próprio para que eu pudesse recuperar o registro certo no RMS, nesse caso o próprio ID no RMS.

Criando um novo "StringItem"
Bom, nesse caso então a minha idéia foi criar um novo componente que extendia de um StringItem, portanto eu tinha todo o comportamento já conhecido, e adicionar um atributo de código "escondido", para poder armazenar o ID e depois usar. E a nova classe que criei ficou assim:


public class HiddenIdStringItem extends StringItem {
private int hiddenId;

public HiddenIdStringItem(String label, String text) {

//Uso normal como se fosse um simples StringItem...
super(label, text);
}

public HiddenIdStringItem(int toHiddenId, String label,
String text) {

//construtor da superclasse
super(label, text);
//salvando o ID que se deseja "esconder"
this.hiddenId = toHiddenId;
}

public HiddenIdStringItem(String label, String text,
int appearanceMode) {

//Uso normal como se fosse um simples StringItem...
super(label, text, appearanceMode);
}

public int getHiddenId() {
return hiddenId;
}

public void setHiddenId(int sessionId) {
this.hiddenId = sessionId;
}
}


Como habilitar o click?
Para que o usuário possa clicar no seu novo componente, basta você usar o método setDefaultCommand (no seu item do tipo HiddenIdStringItem), passando como parâmetro algum comando e depois o método setItemCommandListener (também no seu item), passando a instância de uma classe que implementa a interface ItemCommandListener, para que alguém "trate" esse comando que você adicionou.
A classe que implementa a interface, deverá então implementar o método commandAction que recebe o comando associado ao seu item e qual item que se trata. No nosso caso, um item do tipo HiddenIdStringItem. Então, você faz o cast adequado (de item para HiddenIdStringItem) e pode utilizar o método getHiddenId para obter o id que você associou quando criou o componente.

Vantagens
  • Utilizando esse componente você evita problemas com Lists e Choice Groups.
  • Você não precisa ficar comparando o label ou o text para saber qual item é aquele.
  • Ja herda todo o comportamente conhecido do StringItem.
Cuidados:
  • Adicionar o comando e seu listener corretamente.
  • Utilizar os layouts corretamente para não ter surpresas desagradáveis com a exibição dos itens na tela.
Bom pessoal, espero que isso possa ajudar alguém ou que facilite a vida de seus usuários! ;-)

[]s
Neto

quinta-feira, 8 de maio de 2008

Melhore o visual da sua aplicação com LWUIT !!

Ola pessoal,

Eu já tinha lido uma prévia do projeto LWUIT no blog do Terrence na "Mobile & Embedded Community" e já tinha me deixado empolgado, pois até o título do post era promissor: "Em Breve: Swing para mobile, mas melhor" (em tradução livre). E não era para menos, deem uma olhada nos screenshots que divulgaram:


E hoje, durante o JavaOne, o pessoal do projeto apresentou o primeiro release dessa biblioteca que promete melhorar e muito o visual dos aplicativos em Java ME. Além disso, é um projeto apoiado pela Sun (interno) e que está sob a licença GPL, porém com o classpath exception, ou seja, você pode usá-lo tranquilamente em aplicações fechadas.
Tem algumas features interessantes:

  • Swing-like MVC
  • Layouts
  • Suporte look-and-feel e temas
  • Fontes
  • Suporte Touch screen
  • Animações e transições
  • Integração 3D
  • Suporte I18N/L10N (internacionalização)
  • Performance moderada e baixo footprint.
  • Multi-plataforma (MIDP/CDC/FP/PBP)
  • Compatibilidade com SVG (scalable vector graphics)
Eu acabei de ler o tutorial que eles publicaram e estou fazendo uma pequena aplicação para controle de despesas pessoais e irei utilizar LWUIT para testar e posteriormente implementar também no projeto CoSMo. Então, assim que concluir esse pequeno aplicativo eu posto aqui uma avaliação, tutorial e o aplicativo para vocês usarem e testarem!!

Para saber mais, visitem o site do projeto LWUIT !

Abraços
Neto Marin

quinta-feira, 1 de maio de 2008

Tooltip para listas.

Ola pessoal,

Seguindo a idéia de apresentar alguns problemas que encontrei no desenvolvimento JME e soluções que utilizei, segue uma funcionalidade que pode ser incorporada a listas e ajudar o seu usuário durante a utilização da sua aplicação. Trata-se de um "tooltip" que é exibido quando o usuário fica um determinado tempo parado "em cima" de um determinado item da lista.

A idéia
A idéia era que quando o usuário ficasse um tempo parado em um item da lista fosse exibido algo onde pudesse ser exibida alguma explicação para o usuário sobre esse item que ele esta "selecionando". Alguns celulares Nokia possuem esse recurso e quando bem utilizado pode trazer um alto grau de usabilidade!

O Exemplo
No exemplo que vou mostrar aqui (e que o código está disponivel), eu optei por utilizar um Alert. Mas, fica ao gosto do fregues! =) E se achar que fica melhor utilizar um Ticker, ou um CustomItem e mostrar um aviso no meio da tela, fique a vontade, eu mostrarei o trecho que você deve alterar! ;-)
A aplicação está dividida em 3 classes (ListTooltipMIDlet, ListSelectionListener e TooltipTimer) que terão o seu funcionamento básico explicado abaixo.

ListSelectionListener
Essa classe, que implementa a interface Runnable, recebe como parametro para seu construtor a instância do Display atual da aplicação e a lista que terá suas ações "controladas" e o tooltip exibido. Essa classe é feita como uma thread pois ela tem que ficar o tempo todo verificando a mudança de seleção da lista.
Sua tarefa consiste básicamente em um loop (eterno) dentro do corpo do método run, que a cada interação é verificado se o indice de seleção da lista foi alterado desde a ultima execução. Caso o indice tenha sido alterado (o usuário mudou de opção dentro da lista), a variável de controle é atualizada, o schedule antigo de exibição é cancelado e uma nova instância da classe TooltipTimer é criada e schedulada para 2 mil milisegundos, ou seja, 2 segundos. Em seguida, a thread recebe o comando de sleep de 500 milisegundos (meio segundo).

TooltipTimer
Essa classe, que extende de uma TimerTask, assim como a ListSelecionListener recebe como parametro do seu construtor a instância do Display e da lista. Essa classe será executada 2 segundos após ela ter sido schedulada na classe ListSelectionListener e caso não tenha seu timer cancelado.
Sua tarefa a ser executada está dentro do método run e, nesse caso, é mostrar um alert com um texto. É justamente esse ponto que você deve alterar caso deseje que ele faça uma ação diferente, como por exemplo atualizar um ticker da sua List, chamar um novo form ou o que você achar interessante! =)

ListTooltipMIDlet
Bom, essa midlet nada mais é que apenas uma simples classe para poder fazer o exemplo funcionar. Aqui eu somente criei uma lista com alguns itens (que chamei de itens), exibi e depois fiz a utilização das classes que criei aqui, através da seguinte linha:

Thread t = new Thread(new ListSelectionListener(Display.getDisplay(this),
itens));
t.start();

Fiquem a vontade para usar o código, modificar ou até ignorar !! =)

Downloads

Projeto completo (Eclipse) com código fonte, clique aqui!
Aplicação exemplo (.jar), clique aqui!

[]s
Neto

quarta-feira, 30 de abril de 2008

Internacionalização com solução "caseira"

Ola pessoal,

Depois de um "longo e tenebroso inverno", consegui um tempinho para voltar a escrever algumas coisas que acho interessante sobre o desenvolvimento de aplicativos para dispositivos móveis, e principalmente utilizando Java ME! :)
E já que o espirito desse blog é passar para vocês algumas das minhas experiências e também soluções que encontro para algumas situações, vou mostrar hoje como resolvi um "problema" de internacionalização para aplicativos em Java ME.

** ATTENTION: This is a portuguese version of http://weblogs.java.net/blog/netomarin **

O problema:
Queria fazer um aplicativo que chegasse no maior número de usuários, mas antes da aplicação em si eu tinha uma barreira: Idioma!
Não gostaria de ter uma versão diferente para cada idioma que eu fosse  distribuir minha aplicação. Então, minha primeira idéia foi utilizar a JSR 238 (Mobile Internationalization API), porém ao consultar a matriz de dispositivos que implementam essa API, adivinhem só ? Poucos aparelhos e somente da Sony Ericsson.
Nesse caso, a saída então era utilizar algum "walk around" que permitisse o usuário ter a opção de escolher entre diversos idiomas, dentro de uma única distribuição do aplicativo, o que com certeza, iria facilitar a minha vida.

Solução "caseira":
Sei que a JSR 238 trata a internacionalização como um todo, e não somente a questão do idioma, mas como no meu caso o problema era SOMENTE o idioma da aplicação, minha solução caseira é com foco no suporte a diversos idiomas.
Então, criei uma classe LanguageManager que possui dois métodos estáticos para o uso dos idiomas, a interface MessagesKey que contém todas as chaves para as mensagens utilizadas no aplicativo e, claro, arquivos properties para cada idioma que se deseja disponibilizar.

Arquivos de properties:
Esse arquivo não tem nenhum mistério. Trata-se do clássico formato "CHAVE=VALOR", de forma que cada par deve estar em uma linha própria. Para facilitar a leitura desse arquivo, ele pode ter comentários em linhas iniciadas com "#".
Além da regra de "composição" do conteúdo do arquivo, o nome do arquivo também deve seguir uma regra: Ele deve estar em um diretório separado chamado "properties" e seu nome deve ser composto do código do idioma com a extensão ".properties", como por exemplo "pt-br.properties". Abaixo, exemplo de um trecho de um propertie que utilizo:

pt-br.properties
#COMMANDS
CMD_CONTINUE=Continuar
CMD_EXIT=Sair
CMD_SEARCH=Pesquisar

A interface MessagesKey
Para que o seja possível encontrar a mensagem desejada, essa classe deve conter a chave desejada, pois é através de uma referência para uma constante dessa classe que será buscada a mensagem desejada. Cada chave existente no arquivo de properties deve ter o seu correspondente nessa classe. Abaixo, exemplo da classe contendo as chaves indicadas no trecho acima do properties:

public interface MessagesKey {
    /**
     * Command Label
     */
    public static final String CMD_CONTINUE = "CMD_CONTINUE";
    public static final String CMD_EXIT = "CMD_EXIT";
    public static final String CMD_SEARCH = "CMD_SEARCH";
}

A classe LanguageManager
Essa classe é a responsável pela carga do idioma desejado e também é a classe que deverá ser utilizada pelo desenvolvedor para obter o texto desejado de acordo com a chave informada. Para fazer esse "trabalho", ela tem dois métodos:
  • public static boolean loadLanguage(String language) throws LanguageNotFoundException
Esse método é o responsável for fazer a "carga" do idioma desejado. O parâmetro que ele recebe é o prefixo do idioma (no caso do português do Brasil, seria pt-br), que é utilizado para carregar o propertie correspondente (pt-br.properties, no nosso exemplo). Essa carga é feita percorrendo cada linha do arquivo texto e então atribuindo o par chave/valor a um Hashtable stático (privado) da classe.
Atenção: Esse método deve ser executado ao menos uma vez antes de você tentar usar as mensagens internacionalizadas, pois ele é o responsável por carregar o Hashtable com as mensagens, senão, você com certeza terá uma exceptions de NullPointer !!! =)
  • public static String getMessageText (String messageKey)
Para acessar o Hashtable que possui as mensagens que devem ser exibidas, o acesso é feito por esse método que irá simplesmente devolver a String que tiver associada a chave fornecida no parâmetro. Para evitar erros de execução e simplesmente facilitar o tratamento, esse método não possui nenhum excessão, apenas retorna null caso não haja valor nenhum para a chave indicada.

Exemplo de como usar:

Abaixo, vai exemplo de como utilizar a solução indicada acima:

  • Carregando o idioma: Esse passo deve ser feito de preferência quando você carrega a aplicação pela primeira vez. Para facilitar meu trabalho, eu criei um parâmetro no meu JAD que indica o idioma padrão, e lá coloquei pt-br. Exemplo:
LanguageManager.loadLanguage(this.getAppProperty("DefaultLanguage"));

ou usando o idioma "explicitamente":

LanguageManager.loadLanguage("pt-br");

  • Criando um novo Command, onde o label dele é "internacionalizado":
Command continueCmd = new Command(LanguageManager.getMessageText(MessagesKey.CMD_CONTINUE), Command.OK, 1);

Bom pessoal, espero que tenha ficado fácil e que isso possa ajudar a alguém!! :)
Código fonte exemplo do que utilizo na minha aplicação (apenas o pacote internationalization): internationalization.zip

Abraços a todos!
Neto Marin