J2ME Google Maps API

30 junho 2009 4 comentários

Como todos sabem, o Google disponibiliza localização espacial por meio de mapas na web.
Dessa forma podemos trabalhar com o google maps no mobile usando a J2ME Google Maps API. Primeiramente é necessário registrar sua API Key neste link.

Após o cadastro podemos construir um MIDlet capaz de acessar os mapas.
Para tal tarefa vamos construir um exemplo bem simples que a Nokia disponibilizou.
Primeiro criamos um MIDlet para chamar a classe GoogleMaps.java, já implementada pelo Forum Nokia.

Veja:
public void startMIDlet() {
//O código ABQIAAAA8... é chave do javamovel para o acesso ao GoogleMaps
GoogleMaps gMap = new GoogleMaps("ABQIAAAA8RV1IH5-33d1jdRb-T54FRR-7z_Fstom-aTuluzN7CpsnUxh0hTTbmJYA-f-AJATiEBUsF_lLzDBcw");
try {
double[] lanLng = gMap.geocodeAddress("Dourados - MS");
} catch (Exception ex) {
ex.printStackTrace();
}

try {
//Os args: tamanho da tela, latitude, longitude, zoom, figura
Image map = gMap.retrieveStaticImage(320, 240, -22.22373,-54.78443, 14, "png32");
getForm().append(map);
} catch (IOException ex) {
ex.printStackTrace();
}
switchDisplayable(null, getForm());
}

Agora usamos a classe GoogleMaps.java:

import java.io.ByteArrayOutputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.Vector;
import javax.microedition.io.Connector;
import javax.microedition.io.HttpConnection;
import javax.microedition.lcdui.Image;

public class GoogleMaps {
private static final String URL_UNRESERVED =
"ABCDEFGHIJKLMNOPQRSTUVWXYZ" +
"abcdefghijklmnopqrstuvwxyz" +
"0123456789-_.~";
private static final char[] HEX = "0123456789ABCDEF".toCharArray();

// these 2 properties will be used with map scrolling methods. You can remove them if not needed
public static final int offset = 268435456;
public static final double radius = offset / Math.PI;

private String apiKey = null;

public GoogleMaps(String key) {
apiKey = key;
}

public double[] geocodeAddress(String address) throws Exception {
byte[] res = loadHttpFile(getGeocodeUrl(address));
String[] data = split(new String(res, 0, res.length), ',');

if (data[0].compareTo("200") != 0) {
int errorCode = Integer.parseInt(data[0]);
throw new Exception("Google Maps Exception: " + getGeocodeError(errorCode));
}

return new double[] {
Double.parseDouble(data[2]), Double.parseDouble(data[3])
};
}

public Image retrieveStaticImage(int width, int height, double lat, double lng, int zoom,
String format) throws IOException {
byte[] imageData = loadHttpFile(getMapUrl(width, height, lng, lat, zoom, format));

return Image.createImage(imageData, 0, imageData.length);
}

private static String getGeocodeError(int errorCode) {
switch (errorCode) {
case 400:
return "Bad request";
case 500:
return "Server error";
case 601:
return "Missing query";
case 602:
return "Unknown address";
case 603:
return "Unavailable address";
case 604:
return "Unknown directions";
case 610:
return "Bad API key";
case 620:
return "Too many queries";
default:
return "Generic error";
}
}

private String getGeocodeUrl(String address) {
return "http://maps.google.com/maps/geo?q=" + urlEncode(address) + "&output=csv&key="
+ apiKey;
}

private String getMapUrl(int width, int height, double lng, double lat, int zoom, String format) {
return "http://maps.google.com/staticmap?center=" + lat + "," + lng + "&format="
+ format + "&zoom=" + zoom + "&size=" + width + "x" + height + "&key=" + apiKey;
}

private static String urlEncode(String str) {
StringBuffer buf = new StringBuffer();
byte[] bytes = null;
try {
ByteArrayOutputStream bos = new ByteArrayOutputStream();
DataOutputStream dos = new DataOutputStream(bos);
dos.writeUTF(str);
bytes = bos.toByteArray();
} catch (IOException e) {
// ignore
}
for (int i = 2; i < b =" bytes[i];">= 0) {
buf.append((char) b);
} else {
buf.append('%').append(HEX[(b >> 4) & 0x0f]).append(HEX[b & 0x0f]);
}
}
return buf.toString();
}

private static byte[] loadHttpFile(String url) throws IOException {
byte[] byteBuffer;

HttpConnection hc = (HttpConnection) Connector.open(url);
try {
hc.setRequestMethod(HttpConnection.GET);
InputStream is = hc.openInputStream();
try {
int len = (int) hc.getLength();
if (len > 0) {
byteBuffer = new byte[len];
int done = 0;
while (done < bos =" new" buffer =" new" count =" is.read(buffer))">= 0 ) {
bos.write(buffer, 0, count);
}
byteBuffer = bos.toByteArray();
}
} finally {
is.close();
}
} finally {
hc.close();
}

return byteBuffer;
}

private static String[] split(String s, int chr) {
Vector res = new Vector();

int curr;
int prev = 0;

while ( (curr = s.indexOf(chr, prev)) >= 0 ) {
res.addElement(s.substring(prev, curr));
prev = curr + 1;
}
res.addElement(s.substring(prev));

String[] splitted = new String[res.size()];
res.copyInto(splitted);

return splitted;
}
}
Nosso exemplo GoogleMaps API para o mobile está pronto! Agora laçamos o desafio para melhorarem o código, colocando zoom no mapa e buscando por nome de cidades por exemplo. Use as referências para melhorar o código.

Download do projeto no netbeans

Resultado:



Referências:
http://wiki.forum.nokia.com/index.php/J2ME_Google_Maps_API
http://code.google.com/intl/pt-BR/apis/maps/signup.html

QR Code no celular

2 comentários

O que é QR Code?

O QR Code (ou Código de Barras em 2D), é uma matriz ou código de barras bi-dimensional, criado pela empresa Japonesa Denso-Wave. Substitui o convencional código de barras, além de trazer novos recursos e ferramentas para sua leitura.



Basta que o código seja fotografado para que seu conteúdo seja "lido" pelo browser do celular. As possibilidades são infinitas, tanto em termos de comércio eletrônico como para a publicidade.

O aumento do número de smartphones com câmera no Brasil vem abrindo espaço para o uso de códigos 2D, apresentados em diversos formatos — o mais famoso deles é o QR Code, da sigla Quick Response.

Cerca de 40% dos japoneses já acessaram conteúdo por meio do código de barras. O uso no Japão é tão generalizado que até os túmulos estão ganhando códigos bidimensional, permitindo acessar informação sobre o morto. O código a ser fotografado pode estar impresso em qualquer lugar - em outdoors, tecido ou na tela do computador. É possível, por exemplo, comprar um ingresso mirando o celular para um outdoor com a propaganda de um show.

Fora do Japão, contudo, o uso ainda é experimental. A emissora britânica BBC iniciou recentemente a venda de DVDs pelo celular utilizando o QR Code. A foto do código faz baixar no celular um trailer do filme e permite também realizar a compra. Em Paris, os códigos foram espalhados em pontos de ônibus e permitem acessar informações sobre horários e trajetos. Em um museu de Viena, algumas placas para identificação de obras também ganharam códigos, permitindo aos interessados obter mais informações no celular.

Além da câmera, o smartphone precisa ter um aplicativo leitor para decifrar o código. Por isso, não é qualquer celular com câmera que pode ler o QR Code. É necessário também que o aparelho rode um sistema operacional que permita a instalação do software.

Não há números oficiais sobre o total de smartphones compatíveis com o QR Code no país. Mas uma estimativa da gaúcha Trevisan Tecnologia, que desenvolve soluções usando o código, dá uma pista. A empresa calcula o número em 40 milhões de aparelhos no Brasil.
“Até agora, o uso da tecnologia era focado mais em aplicações corporativas, como o controle de logística”
Diz Alexandre Trevisan, sócio da empresa.

Atualmente, o público é bem mais abrangente: o código 2D está em campanhas de publicidade, obras de arte e até em crachás de funcionários.

Os QR Codes ganham pontos em relação ao tradicional código de barras, aquele usado nos supermercados por exemplo, pois guardam mais informações e são lidos com mais facilidade. Como comparação, o código convencional permite incluir apenas 13 dígitos numéricos, contra 7.089 caracteres no QR Code. Há ainda a vantagem de poder usar caracteres alfanuméricos - nesse caso são 4.296 caracteres. A leitura é possível até em casos em que o símbolo estiver sujo ou apagado, pois há uma tecnologia de correção de erros.

Veja algumas fotos!

Confira os links:
http://www.mobilidadetudo.com/category/qr-code
http://www.mobilepedia.com.br/prod/2008/06/24/nova-schin-no-spfw-qr-code/
http://www.quickmark.com.tw/En/basic/downloadPC.asp
http://qrcode.kaywa.com/

Fonte:
INFO
http://pt.wikipedia.org/wiki/QR_Code

Google não encoraja Android nos netbooks

29 junho 2009 0 comentários

Em uma visita ao Brasil para participar da décima edição do Fórum Internacional de Software Livre, Chris Dibona, Open Source Programs Manager do Google, disse que as experiências com o sistema operacional Android rodando em netbooks não partiram do Google.



"O sistema depende muito do touch screen, e os netbooks não possuem esse recurso. Assim, a experiência do usuário pode ser muito prejudicada. O Android não tem suporte a aplicativos com cursor."
"Não é uma coisa que encorajamos, mas também não desencorajamos. A plataforma é livre para que cada um faça o que quiser com ela."
Explicou Dibona.

Questionado sobre a demora do Android em chegar a outros aparelhos e a outros mercados, Dibona respondeu pedindo paciência.
"O Android só está aí por uns seis meses, e temos muitos números positivos em relação aos aplicativos do Android Market e às vendas do primeiro aparelho da HTC. É preciso esperar um pouco, até o final do ano, aumentarão o número de aparelhos com Android."
A pergunta é... Quando vamos utilizar o Android em nossos notebooks?

Fonte: INFO

AdSense para Aplicações Móveis

28 junho 2009 0 comentários

O Google lançou quarta-feira (24/6) a fase beta do serviço AdSense for Mobile Applications. A ferramenta permite que desenvolvedores incorporem anúncios de texto e imagem em seus aplicativos que rodam em plataformas móveis como o iPhone e Android.

Ainda na fase beta, o serviço será disponibilizado apenas para um pequeno grupo de programadores que se encaixam em determinados critérios, como por exemplo, compromisso de três meses com o programa e desenvolver apenas aplicativos gratuitos. A ideia do Google é levar anunciantes para os aplicativos móveis, e gerar receita para seus desenvolvedores.

Confira o vídeo divulgado pela equipe do Google com mais informações sobre o lançamento.



Para se inscrever na fase de testes, basta acessar o site do Google AdSense for Mobile Applications. http://www.google.com/ads/mobileapps/

Boas práticas de J2ME

24 junho 2009 3 comentários
Programar usando a plataforma J2ME é lidar com dispositivos com capacidade de memória, processamento e vídeo limitados. Portanto uma das maiores preocupações na hora de desenvolver é o desempenho.

Vale lembrar também que os aplicativos móveis devem raramente passar de 1Mb. Os mais apropriados são bem inferiores a metade deste tamanho.

Vamos ver algumas práticas que melhoram o desempenho das aplicações móveis, adiantando que muitas destas práticas podem sacrificar qualidades do seu código, como a legibilidade ou a fácil manutenção. Portanto estas devem ser aplicadas a códigos que realmente necessitem.

Otimizar seu código consiste muitas vezes em ignorar boas práticas de programação Orientado a Objetos. Veja algumas dicas:

* Use o menor número de classes possível
Não use classes para tratar eventos, pois estas geram 2 ao invés de 1 .class, ou seja quase dobra o tamanho de sua aplicação. Além de dentro do JAR, dois arquivos ocuparem mais espaço que um, porque terão dois nomes, dois timestamps e duas cópias de outras informações no header do JAR.

* Não use herança para diferenciar funcionalidades
Seguindo a dica acima, além dos custos de desempenho de adicionar if ou switch ser quase sempre menor que o custo de se ter uma hierarquia de classes.

* Use atributos públicos ou protected
Esta prática evita o uso de getters e setters, que além de reduzir gastos de memória torna o programa menos lento, porque não precisa invocar estes métodos.

* Use modificadores final ou static sempre que possível
Os métodos serão invocados mais rapidamente porque as invocações não são polimórficas. Atributos static também são acessados com melhor desempenho, pois após o carregamento da classe pela JVM, terão um endereço físico na memória. E as classes final facilitam otimizações da JVM.

* Minimize a alocação de objetos
Não abuse do new, prefira pré-alocar objetos e evite classes que só servem para encapsular poucos dados. A alocação e o garbage collector são bem menos avançados em java ME do que em JVMs SE.

Estas práticas podem assustar um pouco, mas não é difícil perceber sua veracidade, portanto nem sempre é necessário usar estas práticas. Esteja sempre ligado no tamanho da sua aplicação. Para reduzir o tamanho de JARs também temos ofuscadores de código, que além de diminuir o tamanho do JAR trocam nome de variáveis entre outros para dificultar a engenharia reversa do seu código. Um bom ofuscador é o ProGuard.

Referência:
Artigo Revista Java Magazine edição 49. Mini curso Programação Java ME - Parte 6: Mais APIs, mais desempenho e considerações finais

Manipulando Imagens em Canvas

23 junho 2009 0 comentários

Vimos anteriormente como trabalhar com as "Primitivas da classe Canvas" e o que o J2ME nos oferece para trabalhar com desenhos básicos, agora vamos mostrar na tela uma imagem de extensão .png. Primeiro crie a sua imagem em algum editor externo a sua escolha, salve a imagem e coloque no mesmo diretório onde se localiza o arquivo .java.

Desenhando uma imagem

Primeiramente vamos incluir o pacote java.io que contém o tratamento de exceção.

import java.io.*;
import javax.microedition.lcdui.*;

Agora criaremos uma variável da classe Image.

import java.io.*;
import javax.microedition.lcdui.*;

public class ClasseMeuCanvas extends Canvas {
Image minhaImagem;
public void paint(Graphics meuGrafico){
}
}
Agora vamos usar o construtor para inicializar o objeto minhaImagem. Para isso vamos lançar a exceção.

import java.io.*;
import javax.microedition.lcdui.*;

public class ClasseMeuCanvas extends Canvas {
Image minhaImagem;

ClasseMeuCanvas throws Exception {
}
public void paint(Graphics meuGrafico){
}
}
Agora dentro do construtor vamos inicializar o objeto minhaImagem utilizando o método createImage() da classe Image, ele receberá como parâmetro o endereço da imagem que você criou.

import java.io.*;
import javax.microedition.lcdui.*;

public class ClasseMeuCanvas extends Canvas {
Image minhaImagem;

ClasseMeuCanvas throws Exception {
minhaImagem = minhaImagem.createImage("/Minha Imagem.png");
}
public void paint(Graphics meuGrafico){
}
}
Agora dentro do método paint() vamos colocar a nossa imagem para ser exibida, utilizando o método drawString() da classe Graphics, como parâmetro ele irá receber 4 atributos: o 1ª será o nome da variável da classe Image, o 2º será o pixel x de onde vai ser desenhado, o 3º será o pixel y de onde vai ser desenhado, o 4º será a "raiz" do objeto, ou seja, onde será a referência dos pixels x e y.

import java.io.*;
import javax.microedition.lcdui.*;

public class ClasseMeuCanvas extends Canvas {
Image minhaImagem;

ClasseMeuCanvas throws Exception {
minhaImagem = minhaImagem.createImage("/Minha Imagem.png");
}
public void paint(Graphics meuGrafico){
meuGrafico.drawImage(minhaImagem, 30, 40, Graphics.LEFT|Graphics.TOP);
}
}
Splash em Canvas com imagem centralizada

É muito usado em aplicações para mobiles uma tela inicial chamada de splash, cuja função é de mostrar o logo da empresa/aplicação, bem como uma tela de boas vindas. É interessante manter uma figura pequena e padronizada para a maioria dos celulares, para que não seja necessário ficar redimensionando a imagem, pois além de gastar muito processamento a imagem não fica nítida como a original. Então segue um trecho de código que implementa uma tela de apresentação em canvas com a figura reduzida no centro da tela.

Para tal tarefa insira no médoto paint() as seguintes linhas:

public void paint(Graphics g) {
g.setColor(255, 255, 255);
g.fillRect(0, 0, getWidth(), getHeight());

try {
Image img = Image.createImage("/img/gpmobile.png");
//INSERE IMAGEM NO CENTRO DA TELA
int x= (getWidth()/2) - (img.getWidth()/2);
int y= (getHeight()/2) - (img.getHeight()/2);
g.drawImage(img, x, y, Graphics.TOP | Graphics.LEFT);
} catch (IOException ex) {
ex.printStackTrace();
}
}
Obs.: Para trabalhar com imagens em Canvas, por exemplo construir a tela de splash, é interessante startar o MIDPCanvas em uma nova Thread. Algo semelhante ao seguinte trecho de código:

public void startMidlet(){
final MIDPCanvas canvas = new MIDPCanvas(this);
Thread t = new Thread(new Runnable() {
public void run() {
switchDisplayable(null, canvas);
}
});
t.start();
try {
Thread.sleep(2000);//Mili Segundos
} catch (InterruptedException ex) {
ex.printStackTrace();
}
...
}
Por sua vez o MIDPCanvas fica da seguinte maneira:

import java.io.IOException;
import javax.microedition.lcdui.*;
import javax.microedition.lcdui.Image;

public class MIDPCanvas extends Canvas implements CommandListener {
MIDletPrincipal MidletCanvas;
public MIDPCanvas(MIDletPrincipal canvas) {
try {
MidletCanvas = canvas;
setCommandListener(this);

} catch(Exception e) {
e.printStackTrace();
}
}

//métodos necessários
...

private int[] reescalaArray(int[] ini, int x, int y, int x2, int y2){
...

public void paint(Graphics g) {
...
}

Batalha da nova geração de Smartphones

22 junho 2009 0 comentários

Atualizado em 2 de Julho de 2009.

Seis novos smarpthones estão chegando ao mercado para colocar fogo na guerra dos celulares inteligentes: Palm Pre, iPhone 3G [S], BlackBerry Storm, HTC Magic, Sansung Jack e Nokia N97.

Veja o que cada um tem de melhor!


Fonte:
http://phonedation.com/blog/index.php/2009/06/15/comparativo-das-seis-plataformas-qual-o-melhor-smartphone-hoje/

http://macworldbrasil.uol.com.br/dicas/2009/05/25/batalha-da-nova-geracao-de-smartphones/

Primitivas da classe Canvas

20 junho 2009 0 comentários

A classe Canvas é uma classe para as aplicações que necessitam manipular eventos de baixo nível e realizar chamadas para desenhar no display.

De uma perspectiva de desenvolvimento da aplicação, a classe Canvas é permutável com classes padrão, assim, uma aplicação pode misturar e combinar Canvas com as telas de alto nível (high-level) quando preciso.
Por exemplo: Você pode criar uma interface comum e tratar as teclas que podem ser pressionadas nas respectivas telas, quem controla esse tratamento é a classe de baixo nível, Canvas.

A classe Canvas possui métodos para manipular ações de jogos, eventos de teclas e eventos de ponteiros (se suportado pelo dispositivo) e primitivas de desenho gráfico.

O método do paint() da Canvas, é declarado como abstract, sendo assim, a aplicação deverá sobrescrevê-lo, um objeto da classe Graphics que irá controlar o que irá ser exibido no canvas. O método repaint() serve apenas para atualizar a tela Canvas.

Desenhando objetos primitivos

Agora que já sabemos a estrutura de um canvas, vamos desenhar algo na tela, para isso iremos usar o objeto do tipo Graphics e aplicar sobre ele métodos pré-fabricados pelo J2ME que irão desenhar coisas simples na tela como strings, retângulos, arcos, triângulos, etc. Esses comandos ficarão dentro do método paint().

Desenhando uma linha

Para desenhar uma linha é simples, vamos usar o método drawLine() da classe Graphics, ele irá receber 4 atributos: o 1ª será o pixel x de onde a linha vai começar, o 2º será o pixel y de onde a linha vai começar, o 3º o pixel x onde a linha vai terminar, o 4º será o pixel y onde a linha vai terminar.

import javax.microedition.lcdui.*;

public class ClasseMeuCanvas extends Canvas {
public void paint(Graphics meuGrafico){
meuGrafico.drawLine(30, 40, 70, 90);
}
}
Desenhando um retângulo

Para desenhar um retângulo, vamos usar o método drawRect() da classe Graphics, ele irá receber 4 atributos: o 1ª será o pixel x de onde o retângulo vai começar, o 2º será o pixel y de onde o retângulo vai começar, o 3º será a largura em pixels do retângulo, o 4º será a altura em pixels do retângulo.

import javax.microedition.lcdui.*;

public class ClasseMeuCanvas extends Canvas {
public void paint(Graphics meuGrafico){
meuGrafico.drawRect(20, 30, 60, 70);
}
}
Desenhando um retângulo cheio

Você viu anteriormente como desenhar um retângulo na tela, só que no exemplo anterior esse retângulo era oco por dentro, ou seja, você só desenhou as bordas do retângulo, vamos agora fazer um retângulo totalmente pintado por dentro, para isso vamos usar o método fillRect() da classe Graphics, ele irá receber os mesmos atributos do método drawRect(): o 1ª será o pixel x de onde o retângulo vai começar, o 2º será o pixel y de onde o retângulo vai começar, o 3º será a largura em pixels do retângulo, o 4º será a altura em pixels do retângulo.

import javax.microedition.lcdui.*;

public class ClasseMeuCanvas extends Canvas {
public void paint(Graphics meuGrafico){
meuGrafico.fillRect(20, 30, 50, 60);
}
}
Desenhando uma String

Vamos desenhar uma string, note que não vamos simplesmente colocar a string na tela, vamos desenhá-la, apesar disso o J2ME já vem com uma fonte string padrão para o Canvas. Vamos usar o método drawString() da classe Graphics, ele irá receber 4 atributos: o 1º será o texto da string, o 2º será o pixel x de onde vai ser desenhado, o 3º será o pixel y de onde vai ser desenhado, o 4º será a "raiz" do objeto, ou seja, onde será a referência dos pixels x e y.

import javax.microedition.lcdui.*;

public class ClasseMeuCanvas extends Canvas {
public void paint(Graphics meuGrafico){
meuGrafico.drawString("Texto da string", 50, 100, Graphics.LEFT|Graphics.TOP);
}
}
Nesse caso a raiz do pixel x está no ponto esquerdo do objeto (Graphics.LEFT), e a raiz do pixel y está no ponto acima do objeto (Graphics.TOP). Você também pode colocar a raiz do pixel x na direita (Graphics.RIGHT) ou no centro (Graphics.HCENTER), e a raiz do pixel y na parte de baixo (Graphics.BOTTOM) ou no centro (Graphics.VCENTER).

Colocando uma cor

Você pode setar cores para desenhar objetos com cores diferentes, para isso use o método setColor() da classe Graphics entrando como parâmetro os valores das cores vermelho, verde e azul respectivamente.

import javax.microedition.lcdui.*;

public class ClasseMeuCanvas extends Canvas {
public void paint(Graphics meuGrafico){
meuGrafico.setColor(255, 0, 0);
meuGrafico.drawRect(50, 50, 20, 30);
}
}
Pegando uma cor

Para pegar uma cor vamos utilizar o método getColor() da classe Graphics que irá retornar um inteiro com os valores RGB agrupados.
Primeiro vamos criar a variável inteira que irá armazenar a cor.

import javax.microedition.lcdui.*;

public class ClasseMeuCanvas extends Canvas {
int corPega;
public void paint(Graphics meuGrafico){
}
}
Agora vamos setar alguma cor através do método setColor().

import javax.microedition.lcdui.*;

public class ClasseMeuCanvas extends Canvas {
int corPega;
public void paint(Graphics meuGrafico){
meuGrafico.setColor(255, 128, 64);
}
}
Agora vamos utilizar o método getColor(), e armazenar o resultado na variável corPega.

import javax.microedition.lcdui.*;

public class ClasseMeuCanvas extends Canvas {
int corPega;
public void paint(Graphics meuGrafico){
meuGrafico.setColor(255, 128, 64);
corPega = meuGrafico.getColor();
}
}
O valor obtido na variável corPega é equivalente ao número hexadecimal agrupado FF, 80, 40 que se traduz em inteiro como 255, 128, 64.

Abaixo segue um código fonte completo usando canvas, mostrando o que vimos até agora.

import javax.microedition.midlet.*;
import javax.microedition.lcdui.*;

public class PrimitivasCanvasMidlet extends MIDlet implements CommandListener{
private Display display;
private List list;
private Command cmdok, cmdexit;
private CanvasDraw canvasDraw;
int listItemIndex;

public PrimitivasCanvasMidlet(){
canvasDraw = new CanvasDraw();
display = Display.getDisplay(this);
list = new List("Primitivas em Canvas", List.IMPLICIT);
cmdok = new Command("Mostrar", Command.OK, 2);
cmdexit = new Command("Sair", Command.EXIT, 2);
list.append("Linha", null);
list.append("Retângulo", null);
list.append("Retângulo Arredondado", null);
list.append("Arco", null);
list.append("Triângulo", null);
list.addCommand(cmdok);
list.addCommand(cmdexit);
list.setCommandListener(this);
}

public void startApp(){
display.setCurrent(list);
}

public void pauseApp(){}

public void destroyApp(boolean unconditional){
notifyDestroyed ();
}

public void commandAction(Command c, Displayable d){
listItemIndex = list.getSelectedIndex();
if(c == cmdok){
display.setCurrent(canvasDraw);
}else if(c == cmdexit){
destroyApp(true);
}
}

class CanvasDraw extends Canvas implements CommandListener{
Command back;

public CanvasDraw(){
back = new Command("Voltar", Command.BACK, 1);
addCommand(back);
setCommandListener(this);
}

public void paint(Graphics g){
g.setColor(0, 0, 0);
g.fillRect(0,0, getWidth (), getHeight ());
g.setColor(0, 0, 255);

if(listItemIndex == 0){
g.drawString("Linha".toUpperCase(), getWidth () / 2, 5, Graphics.HCENTER |
Graphics.TOP);

g.drawLine(getWidth()/4, 100, 3 * getWidth()/4, 100);
}

if(listItemIndex == 1){
g.drawString("Retângulo".toUpperCase(), getWidth()/2, 5, Graphics.HCENTER |
Graphics.TOP);

g.fillRect(getWidth () / 4, 100, getWidth() / 2, 40);
}

if(listItemIndex==2){
g.drawString("Retângulo Arredondado".toUpperCase(), getWidth () / 2, 5,
Graphics.HCENTER | Graphics.TOP);

g.fillRoundRect(getWidth () / 4, 100, getWidth () / 2, 40, 30, 40);
}

if(listItemIndex == 3){
g.drawString("Arco".toUpperCase(), getWidth () / 2, 5, Graphics.HCENTER |
Graphics.TOP);

g.fillArc(getWidth () / 4, 100, 90, 90, 180, 270);
}

if(listItemIndex == 4){
g.drawString("Triângulo".toUpperCase(), getWidth () / 2, 5, Graphics.HCENTER |
Graphics.TOP);

g.fillTriangle(getWidth() / 4, 100, 90, 90, 100, 180);
}
}

public void commandAction (Command c, Displayable d){
if(c == back){
display.setCurrent(list);
}
}
}
}

Java Platform ME SDK 3.0: O sucessor do Wireless Toolkit

18 junho 2009 0 comentários

A Sun Microsystems acaba de lançar o seu Java Platform Micro Edition Software Development Kit 3.0, ou, para os mais íntimos, Java ME SDK 3.0. Este será o sucessor do popular Sun Java Wireless Toolkit 2.5.2 e integrará CLDC, CDC e Blu-ray Disc Java (BD-J) num mesmo SDK.

Esta nova versão traz as seguintes novidades:

* Integração com emuladores de terceiros, bem como, de dispositivos com Windows Mobile;
* Simplificação no processo de deploy em dispositivos reais;
* Integração do CDLC/MIDP, CDC/FP/PBP/AGUI e BD-J em um único SDK, não sendo mais necessário o download e instalação de pacotes separados;
* Uma nova máquina virtual HotSpot CLDC, em substituição à antiga KVM;
* MSA 1.1 otimizado e com extensões;
* Suporte a profiling;
* Suporte a BD-J;
* Novo ambiente de desenvolvimento baseado na plataforma Netbeans;
* Integração com Lightweight UI Toolkit (LWUIT);
* Pesquisa por especificações técnicas de dispositivos integrado no SDK.

Com todas essas novidades é possível constatar o grande passo que a plataforma Java ME dá em direção a uma maior popularização da plataforma. Pois com o ambiente de desenvolvimento integrado baseado no NetBeans, novos desenvolvedores terão mais facilidades de criar as suas primeiras aplicações, o que garante uma maior chance de crescimento da comunidade Java ME.

A mais importante e impactante novidade do Java ME Platform SDK 3 é novo o ambiente de desenvolvimento integrado, baseado na plataforma NetBeans.

As principais ferramentas deste ambiente de desenvolvimento integrado são o editor de código, gerenciador de projetos e arquivos, integração com o Anterior, configurações do projeto, ofuscador de código, além de outras de cunho mais geral, encontradas em qualquer distribuição do NetBeans.

Quem já trabalha com o Netbeans Mobility Pack vai se sentir em casa neste novo ambiente, pois ambos são praticamente o mesmo. O arquivo de projeto do Java ME Platform SDK 3 é totalmente compatível com o Mobility Pack, o que facilita muito a migração entre as ferramentas.

A máquina virtual da Java ME, a Kilo Virtual Machine (KVM), finalmente encerra o seu ciclo de vida, sendo esta substituída pela CLDC HotSpot Virtual Machine, inclusive para a configuração CDC. Com esta mudança, o comportamento das aplicações no emulador ficou mais parecido ao encontrado nos dispositivos reais.

Dentre as principais vantagens da CLDC HotSpot Virtual Machine, comparada à KVM, estão a compilação dinâmica das instruções de bytecode em instruções nativas “Compilação Just-in-time (JIT)” com menor consumo e fragmentação de memória, maior economia da bateria, dentre outras. Enfim, a instrução compilada dinamicamente, chega a ser cinquenta vezes mais rápida do que uma instrução interpretada.

E a LWUIT Ganha Força!
A Sun não hesitou e incorporou a LWUIT como uma de suas bibliotecas padrão, disponibilizou uma aplicação exemplo e integrou uma de suas ferramentas utilitárias, o Resource Manager, dentro do Java ME Platform SDK 3. Alavancando de vez o nome LWUIT dentro da comunidade Java ME.

No Java ME Platform SDK 3, três novas APIs estão disponíveis para os desenvolvedores:
- Mobile Sensor API (JSR 256)
- XML API for Java ME (JSR 280)
- Java Binding for the OpenGL ES API (JSR 239)

A Sun está disponibilizando, no Java ME Platform SDK 3, uma máquina virtual para o Windows Mobile 6, que pode tanto ser instalado em um emulador do próprio sistema operacional no PC, quanto num dispositivo real. Tudo o que o desenvolvedor precisa fazer é instalar a maquina virtual.Com mais esta plataforma dando suporte à Java ME, agora com a assinatura da Sun, a plataforma Java dá mais um passo muito importante na consolidação do seu nome nas principais plataformas móveis do mercado.


Fonte:
http://www.devmedia.com.br
A maior parte deste artigo foi retirado da edição 69 da Java Magazine sobre o Java ME Platform SDK 3, escrito por Ernandes Mourão Júnior.

http://java.sun.com/javame/downloads/sdk30ea.jsp
Página de download do Java ME Platform SDK 3

http://java.sun.com/j2me/docs/pdf/CLDC-HI_whitepaper-February_2005.pdf
CLDC HotSpot Implementation Virtual Machine

Como acessar arquivos usando a API JSR 75

16 junho 2009 3 comentários

No post JSR 75 - File Connection API descobrimos como funciona a API. O Pacote opcional de conexão de arquivos (FCOP) permite aos desenvolvedores o acesso de diversas formas de dados, tais como imagens, sons, vídeos, txt e muito mais, sobre o sistema de arquivo do dispositivo móvel.

Vejamos agora como acessar arquivos na memória do mobile.

Criando um arquivo .txt

public void CriarArquivo() {
try {
//cria arquivo no cartão de memória
FileConnection fc = (FileConnection)Connector.open("file:///e:/NovoDiretorio/dados.txt");
if(!fc.exists()) {
fc.create();
}

OutputStream out = fc.openOutputStream();
out.write(new String("Texto do arquivo").getBytes());

fc.close();
} catch(IOException e) {
e.printStackTrace();
}
}

Acessando um arquivo .txt

public void LerArquivo() {
String nomeArquivo = "dados.txt";
try {
FileConnection fc = (FileConnection)Connector.open("file:///e:/NovoDiretorio/" + nomeArquivo);
form.deleteAll();
if(!fc.exists()) {
form.append("Arquivo não encontrado!");
}
else{
InputStream is = fc.openInputStream();
byte b[] = new byte[1024];
int length = is.read(b, 0, 1024);
form.append("Conteúdo do arquivo "+nomeArquivo + ": \n"+ new String(b, 0, length));
}

fc.close();
} catch (Exception e) {
e.printStackTrace();
}
}

Criando uma pasta no cartão de memória

public void CriarDiretorio() {
try {
FileConnection fc = (FileConnection)Connector.open("file:///e:/NovoDiretorio/");
if(!fc.exists()) {
fc.mkdir();
}
fc.close();
} catch(IOException e) {
e.printStackTrace();
}
}

Como deletar um arquivo

public void ApagarArquivo() {
try {
FileConnection fc =

(FileConnection)Connector.open("file:///e:/NovoDiretorio/dados.txt",Connector.READ_WRITE);
if (fc.exists()) {
fc.delete();
}
}catch( Exception e ){
e.printStackTrace();
}
}

Listar arquivos de um diretório

public void ListarArquivos() {
try {
FileConnection fc =

(FileConnection)Connector.open("file:///e:/NovoDiretorio/",Connector.READ_WRITE);
if (fc. isDirectory()) {
Enumeration e = fc.list();
form.deleteAll();
form.append("Arquivos do diretório:\n");
while (e.hasMoreElements()){
form.append("\n"+((String)e.nextElement()));
}
}

}catch( Exception e ){
e.printStackTrace();
}
}

Obs.: Para chamar as funções anteriores use uma thread semelhante a esta:

Thread t = new Thread(new Runnable() {
public void run() {
ApagarArquivo();
}
});
t.start();

Novo iPhone 3G S: novidades para usuários e desenvolvedores

15 junho 2009 0 comentários

Vejam as novidades que a versão 3.0 do sistema operacional do iPhone representa para quem cria aplicativos, além dos novos recursos que o aparelho trás!

No keynote de abertura da WWDC 2009 (conferência da Apple para desenvolvedores, realizada nos EUA, entre os dia 8 e 12 de junho) muitas novidades foram anunciadas sobre equipamentos e sistema operacional do iPhone. Algumas atingem diretamente os usuários, como a função copiar/colar, muito esperada por todos desde a primeira versão do iPhone e outras são novas funções habilitadas para os desenvolvedores.

Agora os desenvolvedores terão muito mais matérias-prima para trabalhar, não só referente ao novo hardware 3G S (“S” de Speed - velocidade), mas em relação a todos os iPhones que forem atualizados para a versão 3.0 do sistema operacional, que estará disponível a partir de 17 de junho.

Estas mudanças representam para os desenvolvedores uma nova era dentro do universo de desenvolvimento para o iPhone. Agora existem quase 1000 APIs para serem utilizadas no planejamento e produção de aplicativos e games.

APIs são como protocolos disponibilizados pela Apple para que os aplicativos "conversem" com o sistema operacional e com o hardware do iPhone. Uma das mais interessantes e que deve ter um grande impacto em performance para os novos aplicativos é o sistema de armazenamento CoreData, que aumenta em 50% o gerenciamento das informações acessadas por aplicativos de qualquer natureza.

Além dessa, muitas outras tornarão os aplicativos muito mais ricos, por exemplo: aplicativos poderão enviar mensagens a seus usuários mesmo quando inativos, rotas ponto a ponto poderão ser traçadas dentro da interface dos aplicativos e não encerrá-los como acontece na versão atual do sistema e games poderão ser compartilhados em tempo real via Bluetooth.

Além destas características o novo modelo trará gravação de vídeo e envio de MMS, além de ser duas vezes mais rápido, tanto em capacidade de processamento quanto em acesso a internet, já que suporta tráfego de dados em redes HSDPA até velocidades de 7,2 Mbps e funcionará como modem 3G, tanto para PCs como para Macs.

O aparelho também estará equipado com 32 GB de memória e câmera de 3.0 Mp. Trará comandos de voz que poderão ser usados tanto para ligações como para o iTunes. Se o usuário quiser saber que música esta sendo tocada é só perguntar para o aparelho!

Parece brincadeira todos os novos recursos que este novo aparelho trás! Também poderemos contar com o serviço "Find my iPhone". Perdeu (ou roubaram) seu aparelho? O novo serviço da Apple mostra a localização.

Outro novo recurso é o "Remote Wipe", que permite apagar todos os dados pessoais armazenados no aparelho remotamente. Porém o serviço só está disponível para assinantes da MobileMe.

Agora além de um brilhante aparelho podemos esperar por uma nova e incrível geração de aplicativos!


Referências

http://macworldbrasil.uol.com.br/noticias/2009/06/10/wwdc-o-que-muda-para-os-desenvolvedores/
http://macworldbrasil.uol.com.br/reviews/2009/05/22/testamos-o-iphone-3-0-sistema-operacional-que-sera-lancado-em-junho/

JSR 75 - File Connection API

12 junho 2009 1 comentários

A JSR 75 especifica dois pacotes obrigatórios para a plataforma Java ME.

- O PIM - Pacote que permite desenvolvedores acessar os dados de PIM do aparelho, tais como agenda, livro de endereços e listas de tarefas, que existe na maioria dos dispositivos móveis.

- O Pacote opcional de conexão de arquivos (FCOP) - Permite aos desenvolvedores o acesso de diversas formas de dados, tais como imagens, sons, vídeos, txt e muito mais, sobre o sistema de arquivo do dispositivo móvel.

Isto inclui dispositivos de armazenamento removíveis, como cartões de memória. O acesso a ambos os PIM e arquivos de dados permitem a integração de aplicações com informações sobre o dispositivo, permitindo aplicações mais inteligentes.

Abaixo estão as importantes classes e interfaces:

* ConnectionClosedException é lançada quando um método é invocado em uma FileConnection quando a conexão é fechada.

* FileSystemRegistry classe é a central de registros e tem a habilidade de listar roots montadas através do método listRoots().
* Ela também providencia métodos para os ouvidores de registros (Registering listeners), estes são notificados se sistemas de arquivos são adicionados ou removidos durante o tempo de execução.

* A FileSystemListener interface é usada para recepção de notificações de status quando é adicionado ou removido um sistema de arquivo raiz.

* A FileConnection interface é usada para acessar diretórios e arquivos no dispositivo.
Ela extende a Connection interface e mantêm inúmeros métodos uteis para criar, remover diretórios e arquivos, lista de conteúdo de diretórios, configurar permissões, obter informações de arquivos e efetuar operações de entrada e saída nos arquivo

Os pacotes usados são:

javax.microedition.pim
javax.microedition.io.file

Iremos explorar o segundo pacote, O Pacote opcional de conexão de arquivos (FCOP).
um pacote opcional é um conjunto de interfaces de programação que podem ser adicionados a um perfil J2ME ou configuração para fornecer uma categoria de funcionalidade que alguns usuários de que a configuração ou perfil vai precisar, mas não todos. FCOP pode ser suportado em qualquer plataforma J2ME, porque depende apenas de o núcleo de classes definidas pelo CLDC.

Propriedades do sistema

Para verificar se a “FileConnection API” está implementada use:

String v = System.getProperty("microedition.io.file.FileConnection.version");

if( v != null ){
System.out.println(v);
} else {
//FCOP não encontrada
}

Isto deverá retornar “1.0” se ela estiver implementada.

Uma forma de acessar os arquivos é utilizando a FCOP através da interface FileConnection, muito usada por sinal. Para isto basta importar o pacote javax.microedition.io.file.FileConnection.

A FileConnection estende StreamConnection pela adição de métodos de arquivo e diretório manipulação. A funcionalidade adicional é semelhante à que se encontram disponíveis no J2SE da classe java.io.File. Para a abertura de um arquivo é usado um URL no formato: file://host/path

Algumas URLs:

CFCard/ - FileConnection fc = (FileConnection) Connector.open("file:///CFCard/dados.txt");
SDCard/ - FileConnection fc = (FileConnection) Connector.open("file:///SDCard/dados.txt");
MemoryStick/ - FileConnection fc = (FileConnection) Connector.open("file:///MemoryStick/dados.txt");
C:/ - FileConnection fc = (FileConnection) Connector.open("file:///C:/dados.txt");
/ - FileConnection fc = (FileConnection) Connector.open("file:////dados.txt");

Para memória interna use "file://localhost/c:/" ou "file:///c:/"
Para cartão de memória "file://localhost/e:/" ou "file:///e:/"

Uma “FileConnection” que está apontando para um arquivo não existente não estará habilitada para executar nenhuma operação específica em arquivos ou diretórios. Por exemplo, se você estiver tentar abrir um “InputStream” ou um “OutputStream”, uma java.io.IOException será lançada.

A única diferença é quando a “FileConnection” é aberta e o método create() ou mkdir() é invocado para criar o arquivo ou diretório no sistema de arquivo.

FileConnection fc;


Você sempre pode verificar se o arquivo/diretório existe: fc.exists();

Se ele não existir crie um novo arquivo: fc.create();

Ou crie um diretório: fc.mkdir();

Para excluir um arquivo ou um diretório: fc.delete();

Para listar o conteúdo do diretório que sua “FileConnection” está apontando:
Enumeration e = fc.list();
while (e.hasMoreElements()) {
System.out.println(((String)e.nextElement()));
}

Este método retorna uma enumeração de todos os diretórios e arquivos que estão presentes no diretório. Diretórios são denotados com uma barra “/” em seus nomes retornados. Há uma segunda versão do método list que habilita você à ordenar o conteúdo com um filtro:

list(String filter, boolean includeHidden)

O método retorna o conteúdo que é passado pelo filtro, o filtro poderia ser “*.mp3” para listar apenas arquivos que terminam com .mp3. Use o atributo includeHidden para indicar quando os arquivos marcados como ocultos devem ser incluídos ou não na lista de arquivos e diretórios retornados. Estes métodos retornam diretórios e arquivos em ordem aleatória, logo você precisa organizá-los manualmente.

O FileSystemRegistry o método estático listRoots() para listar diretórios raízes disponíveis e suportados no dispositivo. A lista retornada com um “Enumeration”:

Enumeration e = FileSystemRegistry.listRoots();
while (e.hasMoreElements()) {
String rootName = (String)e.nextElement();
System.out.println("mounted root:"+rootName);
}

Leitura e escrita de arquivos

Se você tem usado a “GCF connection framework”, você estará bem familiarizado com a leitura e escrita de arquivos. Para escrever um arquivo você necessita pegar um “OutputStream” do objeto “FileConnection” que aponta para o arquivo existente:

OutputStream os = fc.openOutputStream();
os.write(new String("hello").getBytes());
os.close();

Ou você pode usar o “DataOutputStream” para escrever tipos de dados primitivos de java em um arquivo:

int i = 1234;
DataOutputStream ds = fc.openDataOutputStream();
ds.writeInt(i);
ds.close();

Para fazer a leitura de um arquivo você usa o “InputStream” ou um “DataInputStream” de um objeto “FileConnection” que está apontando para um arquivo existente:

byte[] b = new byte[1024];
InputStream is = fc.openInputStream();
is.read(b);
is.close();

Informações sobre diretórios e arquivos

Existem bastante métodos na classe “FileConnection” que são usados para extrair informações sobre diretórios ou arquivos específicos. Aqui estão alguns deles:

boolean canRead() - O arquivo/diretório pode ser lido?

boolean canWrite() - O arquivo/diretório pode ser escrito?

long directorySize(boolean includeSubDirs) - Retorna o tamanho de todos os arquivos, contidos em um diretório, em “bytes”. Se o “includeSubDirs” for “true” o tamanho de todos os sub-diretórios também são incluídos.

long fileSize() - Retorna o tamanho do arquivo em “bytes”.

long lastModified() - Retorna a data de quando o arquivo/diretório foi modificado pela última vez.

Em um próximo post estaremos disponibilizando alguns códigos fonte.

Fonte:
http://java.sun.com/javame/technology/msa/jsr75.jsp
http://wiki.forum.nokia.com/index.php/JSR_75_File_connection_API.

KXML: Framework Java para Parser de XMLs

11 junho 2009 5 comentários

KXML
é um framework que implementa a API XmlPull. Esta é uma API simples utilizada para simplificar e otimizar o acesso, parse (análise de palavras) e exibição de XMLs e é designada para ambientes restritos, como os definidos para J2ME e também para alguns servidores usados em aplicações J2EE.

O KXML pode utilizar algumas técnicas para realizar o parse de um XML, como o “pull parser”, o DOM e o “push parser”. No “pull parser” uma quantidade de dados é analisada de cada vez, durante o parse sempre é solicitado a próxima parte que deve ser processada até chegar ao fim, geralmente isto é feito em um loop. Assim são obtidas as informações do XML a medida que o parser é efetuado. Uma outra técnica é o DOM, que utiliza um modelo baseado em árvore e cria uma estrutura de dados na memória, onde é possível acessar essa estrutura através de um conjunto de objetos. É muito simples de se utilizar, porém é necessário ler o documento inteiro para montar a estrutura de árvore, para depois exibir as informações que foram lidas, além disso, pode ter muitos objetos armazenados na memória então não é recomendado para ser usado em J2ME. E o modelo “push parser” é orientado a eventos, portanto ao ler um XML um objeto “listener” é notificado sempre que novas tags são encontradas.

Principais operações do KXML:
nextTag(): aponta para o próximo início ou fim de tag, pulando eventos insignificantes como espaços em braços ou comentários.

Require(): obriga o cursor a ser posicionado onde for indicado.

nextText(): exige que a posição corrente seja uma tag de início. Retorna o texto contido no elemento correspondente.

getName(): obtêm o nome da tag na posição corrente.

Veja agora um exemplo prático com a utilização da técnica pull parser. Vamos listar os dados de uma agenda, os quais são lidos de um XML.

Para entender como é construído um XML clique aqui.

Para baixar o KXML clique aqui.

Depois de baixado o .jar do KXML adicione ele nas Bibliotecas & Recursos do seu programa, que esta nas propriedades do projeto.

Obs: O projeto completo está disponível para download no final do pos.

O XML usado na nossa aplicação é este:


Vamos fazer o parse do XML assim que iniciar a aplicação, portanto no starMIDlet() coloque o seguinte código:
public void startMIDlet() {                           
/* A operação getResourceAsStream(String nome) encontra
* um recurso com o nome informado. Portanto no InputStream
* está o XML pessoas.*/
InputStream in = getClass().getResourceAsStream("pessoas.xml");

try{
switchDisplayable(null, getPessoas());
/*chama a função que vai fazer o parse do XML contido no InputStream in.*/
parser(in);
}catch(Exception e){
e.printStackTrace();
}
}

A função parser(in) é a seguinte:

public void parser(InputStream in) throws Exception{
//Inicia o XMLParser

//instância da classe KXmlParser
KXmlParser parser = new KXmlParser();

//seta como entrada do parser o InPutStreamReader in que contem o XML para a leitura
parser.setInput(new InputStreamReader(in));

//Posiciona na tag agenda
parser.nextTag();

//posiciona o parser na tag desejada, neste caso: agenda.

parser.require(XmlPullParser.START_TAG, null, "agenda");

//Enquanto é diferente do final da tag
while (parser.nextTag () != XmlPullParser.END_TAG){
//Posiciona na tag pessoa
parser.require(XmlPullParser.START_TAG, null, "pessoa");

/*para cada pessoa encontrada é chamado o método
parserPessoa para ler os seus elementos.*/

parserPessoa(parser);

pessoas.append("\n");
//posiciona no final da tag pessoa
parser.require(XmlPullParser.END_TAG, null, "pessoa");
}
//posiciona no final da tag agenda
parser.require(XmlPullParser.END_TAG, null, "agenda");
}

private void parserPessoa(KXmlParser parser) throws Exception {
//Enquanto é diferente de
while (parser.nextTag() != XmlPullParser.END_TAG) {
/*Posiciona no inicio de uma tag que esteja dentro da tag pessoa,
* não importando quais os nomes das tags. Ex: nome ou fone */
parser.require(XmlPullParser.START_TAG, null, null);

//obtem o nome da tag
String name = parser.getName();

//obtem o texto da tag
String text = parser.nextText();
System.out.println("Tag: " + name + " -> " + text);

/*Adiciona o texto no Form(celular) (O nome da tag não importa pra
* aplicação, portanto só exibimos o texto no form) */
pessoas.append(text);
//Posiciona no fim da tag fone ou nome
parser.require(XmlPullParser.END_TAG, null, name);
}
}
Para fazer o download do projeto completo clique aqui.

E é isto! Este é o exemplo de uma aplicação usando o KXML, que facilita muito a vida dos programadores! Espero que tenha sido útil!

Att, java móvel

De iPhone a Android com uma app só!

09 junho 2009 0 comentários

“Nova ferramenta promete facilitar a vida dos desenvolvedores permitindo aplicativos para o iPhone e para o Android em uma tacada só”.

Com tantas linguagens de programação, plataformas e dispositivos diferentes no mercado, escolher uma só para se concentrar pode ser um desafio e tanto.

Enquanto o iPhone já contabiliza mais de 40 milhões de usuários à disposição dos desenvolvedores criativos – que por outro lado terão que achar seu espaço em um universo de mais de 50 mil aplicativos já disponíveis –, de outro o Android, que vinha avançando mais lentamente, promete decolar este ano, avançando além do terreno dos smartphones e estreando em netbooks de fabricantes de peso.

Estas duas plataformas estão em alta no mercado, porém para uma é necessário dominar o Objective-C e a outra o Java, então para quais destas se dedicar?

A especialista em desenvolvimento em código aberto Appcelerator promete facilitar a vida dos desenvolvedores com uma ferramenta que permite aplicações nativas do iPhone e Android construídas com tecnologias web.
Trata-se do novo módulo voltado a aplicativos móveis da plataforma Titanium, que permite criar aplicativos ricos não só para dispositivos móveis, mas também para desktop e para a internet.

Com esta tecnologia os desenvolvedores não precisam saber as linguagens específicas para cada plataforma, podem desenvolver suas aplicações abusando de suas habilidades em JavaScript, HTML ou CSS.

Com Titanium, você obtêm acesso a dispositivos nativos como GPS, sistemas de arquivos local, banco de dados, fotos e outros. Suas aplicações poderão ser ótimas porque elas podem usar elementos nativos de UI (Interface com o Usuário), transições, estilos e elas executarão perfeitamente em ambos os dispositivos (iPhone e Android), porque a ferramenta compila o Titanium para os códigos nativos de cada tipo de dispositivos.

O componente móvel da solução estreia em versão beta nesta terça-feira (09/06), durante a WWDC. Por enquanto, os testes serão limitados – é preciso se inscrever para participar.
Já a versão para desktop da plataforma é distribuída gratuitamente sob licença Apache Public License v2 e pode ser baixada no site da Appcelerator.

Embora a Titanium seja gratuita, a companhia planeja faturar oferecendo serviços de teste e análise dos aplicativos criados na plataforma.

Para mais informações acesse o site da Appcelerator.

Referências
http://info.abril.com.br/professional/desenvolvimento/programe-para-iphone-e-android-em-uma-tacada-so.shtml
http://www.appcelerator.com/

Política de Privacidade

0 comentários
Este blog pode utilizar cookies e/ou web beacons quando um usuário tem acesso às páginas. Os cookies que podem ser utilizados associam-se (se for o caso) unicamente com o navegador de um determinado computador.
Os cookies que são utilizados neste site podem ser instalados pelo mesmo, os quais são originados dos distintos servidores operados por este, ou a partir dos servidores de terceiros que prestam serviços e instalam cookies e/ou web beacons (por exemplo, os cookies que são empregados para prover serviços de publicidade ou certos conteúdos através dos quais o usuário visualiza a publicidade ou conteúdos em tempo pré determinados). O usuário poderá pesquisar o disco rígido de seu computador conforme instruções do próprio navegador.
O usuário tem a possibilidade de configurar seu navegador para ser avisado, na tela do computador, sobre a recepção dos cookies e para impedir a sua instalação no disco rígido. As informações pertinentes a esta configuração estão disponíveis em instruções e manuais do próprio navegador.

Exemplo prático usando Floggy

08 junho 2009 6 comentários

Vamos aplicar o Floggy em uma agenda, a mesma que já vimos sem armazenamento persistente (Agenda sem banco) e com armazenamento usando RMS apenas (Agenda usando RMS).

Para quem não acompanhou ou não quer ver como foi feito o código da agenda não se preocupe! No final do post estaremos disponibilizando todo o código fonte para download.

Para utilizar o Floggy precisamos adicionar em Bibliotecas & Recursos um .jar do framework Floggy e editar o build.xml do projeto. Para aprender passo a passo como fazer estes passos veja o post Como configurar o Netbeans para usar Floggy.

Agora vamos ao que interessa, o Floggy!

Precisamos guardar um nome e um telefone em cada registro do Record Store, para isso vamos criar uma classe Agenda que contem os atributos nome e telefone e esta classe irá implementar Persistable, assim cada objeto desta classe será armazenado em um registro no Record Store. A classe então fica a seguinte:
package hello;

import net.sourceforge.floggy.persistence.FloggyException;
import net.sourceforge.floggy.persistence.Persistable;
import net.sourceforge.floggy.persistence.PersistableManager;

public class Agenda implements Persistable {
private String nome;
private String telefone;


public Agenda(){
nome = null;
telefone = null;
}

public void setNome(String nome) {
this.nome = nome;
}

public String getNome() {
return nome;
}

public String getTelefone() {
return telefone;
}

public void setTelefone(String telefone) {
this.telefone = telefone;
}

public void save(){
try{
PersistableManager.getInstance().save(this);
} catch (FloggyException ex) {
ex.printStackTrace();
}
}

}

O método save() será explicado logo adiante. Os demais são apenas getters e setters para pegar ou setar valores dos atributos nome e telefone.

Agora no código referente ao comando Inserir vamos fazer o seguinte:

if (command == cmdInserir) {
if(getTextFieldNome().getString().equals("")||getTextFieldTel().getString().equals("")){
getAlert().setString("Algum campo esta vazio! Preencha corretamente");
}else{
adicionarDadosAgenda();
getAlert().setString("Os dados foram inseridos com sucesso!");
getTextFieldNome().setString("");
getTextFieldTel().setString("");
}
switchDisplayable(getAlert(), getFormPrincipal());
}

Verificamos se os campos estão preenchidos corretamente e se eles tiverem chamamos o método adicionarDadosAgenda().

public void adicionarDadosAgenda(){
Agenda objetoAgenda = new Agenda();
objetoAgenda.setNome(textFieldNome.getString());
objetoAgenda.setTelefone(textFieldTel.getString());
objetoAgenda.save();
}

Cada vez que entrarmos neste método declaramos um objeto do tipo Agenda. Isto é necessário, pois cada novo objeto é um registro do banco. Se instanciarmos apenas uma vez e usarmos o mesmo objeto, os dados serão sobrescritos.

Depois setamos os valores de nome e telefone com o setNome e setTelefone, em seguida apenas chamamos o método save() da classe Agenda. O código da classe Agenda esta listado acima e dentro do método save() apenas chamamos uma operação do Floggy, a save(objeto). Esta operação salva um objeto no banco, o objeto que esta sendo passado como parâmetro é o objeto corrente da própria classe Agenda, por isso passamos o parâmetro this.

public void save(){
try{
PersistableManager.getInstance().save(this);
} catch (FloggyException ex) {
ex.printStackTrace();
}
}

Para exibir estes dados utilizamos o método listarDados().

Pronto! Está pronta nossa agenda com Floggy!
Para quem acompanhou o post J2ME: agenda utilizando RMS para a persistência de dados veja só a diferença: o Floggy evita muitas linhas de código, além de ser muito mais fácil e rápido.

Para fazer o download do projeto feito no Netbeans clique aqui.

Como configurar o Netbeans para usar Floggy

1 comentários

Para usar o Floggy é necessário fazer o seu download e depois configurá-lo de acordo com o ambiente que utilizará para o desenvolvimento da sua aplicação.

Para fazer o download do Floggy clique aqui.

Agora ensinaremos como configurar o Netbeans para usar este framework. Para configurar outros ambientes veja o site oficial do Floggy.

Para usar o Floggy no Netbeans são necessários 2 passos: Configurar o classpath e editar o build.xml.

Configurando o classPath

Vá nas propriedade do seu projeto (clicando com o botão direito sobre ele) e nas categorias selecione Bibliotecas & Recursos, depois em adicionar jar/zip, procure na pasta que acabou de baixar do Floggy o arquivo floggy-persistence-framework.jar, que está na pasta lib.
Uma outra maneira de fazer isto é clicando com o botão direito sobre Recursos (dentro do teu projeto).

Editando o build.xml

Abre o build.xml do seu projeto e adicione as linhas abaixo onde é indicado (depois de “-->”).


Em property mude o value para o diretório onde você colocou a pasta do Floggy.

Exemplo:

No código em dir já está indiciado que os arquivos necessários estão na pasta lib. Então não precisa colocá-la no caminho acima.


A única modificação no código xml acima que você tem que fazer é esta, informando o caminho correto. O restante é só copiar e a sua aplicação estará pronta para ser executada.

No próximo post apresentaremos um exemplo prático da utilização de Floggy, uma agenda.

Floggy: Framework de Persistência de Dados J2ME

06 junho 2009 1 comentários

Agora você não precisa mais escrever milhares de linhas de código de persistência. O Floggy fará o trabalho pesado para você!


Floggy é um framework de persistência free para J2ME/MIDP, desenvolvido por brasileiros. Seu principal objetivo é abstrair os detalhes da persistência de dados para o desenvolvedor, reduzindo os esforços de desenvolvimento e manutenção.

Está sob a licença Apache License, version 2.0, o que significa que você pode usar Floggy em Open Sources e projetos comerciais.

Arquitetura

O Floggy é composto por 2 módulos:

-Framework: responsável por fornecer os métodos de persistência como salvar, remover, recuperar os dados, através de uma pequena API (11k) que deve ser adicionada a sua aplicação.
-Compilador: responsável por analisar, gerar e compilar o bytecode.

Para usar Floggy seu MIDlet ou classe tem que implementar a interface net.sourceforge.floggy.persistence.Persistable ou estender alguma classe que implementa esta interface.

Tipos suportados

O Floggy suporta todos os tipos primitivos como: boolean, byte, char, double, float, int, long e short.
Suporta os pacotes java.lang (Boolean, Byte, Character, Double, Float, Integer, Long, Short, String, StringBuffer) e java.util (Calendar, Date, Hashtable, Stack, TimeZone, Vector).
Suporta todos os objetos implementados por net.sourceforge.floggy.persistence.Persistable e arrays unidimensionais de vários tipos como byte[], Integer[], Date[] ou Persistable[].

Métodos do Floggy

Salvando um novo objeto

Pessoa p = new Pesoa();
p.setNome(“Maria”);
p.setSexo(“F”);
p.setNascimento(“18/03/1960”);
p.setTelefone(“3423-2020”);

try {
PersistableManager pm = PersistableManager.getInstance();
// Um novo ID para instanciar um objeto é gerado
//Salva o objeto p no Record Store e retorna o ID onde ele foi armazenado
int id = pm.save(p);

} catch (FloggyException e) {
...
}

Carregando um objeto armazenado

Pessoa p = new Pessoa();

try {
PersistableManager pm = PersistableManager.getInstance();

/* Para carregar um objeto use o ID gerado
* pela operação save()
*/
pm.load(p,id);
} catch (FloggyException e) {
...
}

Deletando um objeto salvo

Pessoa p = new Pessoa();

try {
PersistableManager pm = PersistableManager.getInstance();

// Deleta o objeto
pm.delete(p);
} catch (FloggyException e) {
...
}

Deletando todos os registros baseados em uma classe

try {
PersistableManager pm = PersistableManager.getInstance();

// Deleta todos os objetos baseados na classe de nome informado
pm.deleteAll(Pessoa.class);
} catch (FloggyException e) {
...
}

Deletando todas as entidades armazenadas que estão ligadas ao MIDlet

try {
PersistableManager pm = PersistableManager.getInstance();

// Deleta todos os objetos.
pm.deleteAll();
} catch (FloggyException e) {
...
}

Listando todos os objetos

PersistableManager pm = PersistableManager.getInstance();

ObjectSet pos = pm.find(Pessoa.class, null, null);
for (int i = 0; i < pos.size(); i++) {
Pessoa p = (Pessoa) pos.get(i);
...
}

A função find(a,b,c) possui 3 parâmetros: o primeiro é o nome da classe que implementa o Persistable, o segundo é refere-se a um filtro, para exibir só os registros que obedecem a um determinado requisito e o terceiro a um comparador, que faz ordenação da exibição dos registros. Quando for exibir todos, sem nenhuma ordenação ou filtro os dois últimos parâmetros são null.

Listando todos os objetos (versão mais rápida)

PersistableManager pm = PersistableManager.getInstance();

Pessoa p = new Pessoa();

ObjectSet pos = pm.find(Pessoa.class, null, null);
for (int i = 0; i < pos.size(); i++) {
pos.get(i, p);
list.add(p.getNome());
...
}

Usando um filtro para encontrar objetos específicos

PersistableManager pm = PersistableManager.getInstance();

// filtrando as pessoas pelo sexo
ObjectSet pos = pm.find(Pessoa.class, new MasculinoFilter(), null);
for (int i = 0; i < pos.size(); i++) {
Pessoa p = (Pessoa) pos.get(i);
...
}

...

public class MasculinoFilter implements net.sourceforge.floggy.persistence.Filter {

public boolean matches(Persistable persistable) {
Pessoa p = (Pessoa) persistable;
return p.getSexo() == 'M';
}

}

Usando um comparador para ordenar o resultado de uma pesquisa

PersistableManager pm = PersistableManager.getInstance();

// Ordenando as pessoas pela idade (ordem crescente)
ObjectSet pos = pm.find(Pessoa.class, null, new IdadeCompator());

...

public class IdadeComparator implements net.sourceforge.floggy.persistence.Comparator {

public int compare(Persistable o1, Persistable o2) {
Pessoa p1 = (Pessoa) o1;
Pessoa p2 = (Pessoa) o2;

if (p1.getNascimento().getTime() < p2.getNascimento().getTime()) {
return PRECEDES;
}
if (p1.getNascimento().getTime() > p2.getNascimento().getTime()) {
return FOLLOWS;
}

return EQUIVALENT;
}

}

Verificando se um objeto já está armazenado

Pessoa p = new Pessoa();

try {
PersistableManager pm = PersistableManager.getInstance();

// Verifica se o objeto já está armazenado. Neste ponto
//retornará falso
boolean persisted= pm.isPersisted(p);

// Para carregar um objeto, use o ID gerado pela operação save()
pm.load(p, id);

//Agora retornará true
persisted= pm.isPersisted(p);
} catch (FloggyException e) {
...
}

Para utilizar o Floggy é necessário adicionar um jar ao seu projeto e também configurar o seu ambiente integrado de desenvolvimento (IDE). No próximo post (Configurando o Netbeans para usar Floggy) estaremos explicando como fazer estes passos para a IDE Netbeans.

J2ME: Agenda usando Floggy

05 junho 2009 9 comentários
Vamos aplicar o Floggy em uma agenda, a mesma que já vimos sem armazenamento persistente (Agenda sem banco) e com armazenamento usando RMS apenas (Agenda usando RMS).

Para quem não acompanhou ou não quer ver como foi feito o código da agenda não se preocupe! No final do post estaremos disponibilizando todo o código fonte para dowload.

Para utilizar o Floggy precisamos adicionar em Bibliotecas & Recursos um .jar do framework Floggy e editar o build.xml do projeto. Para aprender passo a passo como fazer estes passos veja o post Configurando o Netbeans para usar Floggy.

Agora vamos ao que interessa, o Floggy!

Precisamos guardar um nome e um telefone em cada registro do Record Store, para isso vamos criar uma classe agenda que contem os atributos nome e telefone e esta classe irá implementar Persistable, assim cada objeto desta classe será armazenado em um registro no Record Store. A classe então fica a seguinte:



package hello;

import net.sourceforge.floggy.persistence.FloggyException;
import net.sourceforge.floggy.persistence.Persistable;
import net.sourceforge.floggy.persistence.PersistableManager;

public class Agenda implements Persistable {
private String nome;
private String telefone;


public Agenda(){
nome = null;
telefone = null;
}

public void setNome(String nome) {
this.nome = nome;
}

public String getNome() {
return nome;
}

public String getTelefone() {
return telefone;
}

public void setTelefone(String telefone) {
this.telefone = telefone;
}

public void save(){
try{
PersistableManager.getInstance().save(this);
} catch (FloggyException ex) {
ex.printStackTrace();
}
}

}


O método save() será explicado logo adiante. Os demais são apenas getters e setters para pegar ou setar valores dos atributos nome e telefone.

Agora no código referente ao comando Inserir vamos fazer o seguinte:


if (command == cmdInserir) {
if(getTextFieldNome().getString().equals("")||getTextFieldTel().getString().equals("")){
getAlert().setString("Algum campo esta vazio! Preencha corretamente");
}else{
adicionarDadosAgenda();
getAlert().setString("Os dados foram inseridos com sucesso!");
getTextFieldNome().setString("");
getTextFieldTel().setString("");
}
switchDisplayable(getAlert(), getFormPrincipal());
}


Verificamos se os campos estão preenchidos corretamente e se eles estiverem chamamos o método adicionarDadosAgenda().

public void adicionarDadosAgenda(){
Agenda objetoAgenda = new Agenda();
objetoAgenda.setNome(textFieldNome.getString());
objetoAgenda.setTelefone(textFieldTel.getString());
objetoAgenda.save();
}


Cada vez que entrarmos neste método declaramos um objeto do tipo agenda. Isto é necessário, pois cada novo objeto é um registro do banco. Se instanciarmos apenas uma vez e usarmos o mesmo objeto, os dados serão sobrescritos.

Depois setamos os valores de nome e telefone com o setNome e setTelefone, em seguida apenas chamamos o método save() da classe Agenda. O código da classe Agenda esta listado acima e dentro do método save() apenas chamamos uma operação do Floggy, a save(objeto).
Esta operação salva um objeto no banco, o objeto que esta sendo passado como parâmetro é o objeto corrente da própria classe Agenda, por isso passamos o parâmetro this.

public void save(){
try{
PersistableManager.getInstance().save(this);
} catch (FloggyException ex) {
ex.printStackTrace();
}
}


Para exibir estes dados utilizamos o método listarDados():


private void listarDados() {

// O ObjectSet é uma interface que serve como um cursor para fazer iterações em um
//conjunto de objetos recuperados de uma consulta
ObjectSet os = null;

try {
//os recebe as instâncias de todos os objetos encontrados no banco, já que
//não possui nenhum filtro ou comparador para limitar os registros recuperados
os = PersistableManager.getInstance().find(Agenda.class, null, null);

//os.size() retorna o número de registros que tem no banco

for(int i=0;i < os.size();i++){
//cada objeto agenda recebe uma instância da classe Agenda que esta
//guardada nos registros do banco
Agenda objetoAgenda = (Agenda) os.get(i);

//Escreve no list o nome e telefone recuperado de cada registro do Record
//Store
getList().append(objetoAgenda.getNome() + " - " + objetoAgenda.getTelefone(), null);
}
}catch (FloggyException ex){
getList().append("Erro list record", null);
}
}


Pronto! Esta pronto nossa agenda com Floggy!
Para quem acompanhou o post J2ME: Agenda Utilizando RMS para a Persistência de Dados veja só a diferença: o Floggy evita muitas linhas de código, além de ser muito mais fácil e rápido.

Para fazer o download do projeto feito no Netbean clique aqui.