Desenvolva Aplicativos Baseados em eSWT para o Telefone Inteligente Nokia S60

Aprenda a Escrever um Jogo Sudoku Remoto para a Plataforma S60

A Java™ Platform, Micro Edition (Java ME) é uma plataforma de aplicativo onipresente para dispositivos integrados, e vários telefones móveis modernos são capazes de executar esses tipos de aplicativos. O embedded Standard Widget Toolkit, ou eSWT, é uma tecnologia Eclipse que pode ser utilizada para desenvolver aplicativos Java com aspecto nativo para vários telefones móveis. O eSWT é desenvolvido como parte do projeto embedded Rich Client Platform (eRCP), que, como um todo, é suportado apenas em dispositivos em execução no sistema operacional Microsoft ® Windows® Mobile e Windows CE. Entretanto, as bibliotecas do eSWT independentes estão disponíveis em todos os dispositivos executando uma versão recente da plataforma S60 da Nokia — atualmente uma das plataformas líderes mundiais em telefonia inteligente. Este tutorial demonstra como desenvolver aplicativos baseados em eSWT com a ajuda do recém-lançado Eclipse Mobile Tools for Java (MTJ) e do SDK do S60 da Nokia.

Peter Nehrer, Software consultant, Ecliptical Software

Peter Nehrer é um consultor de software especializado em ferramentas de desenvolvimento e soluções corporativas baseadas em Eclipse. Ele é um committer no projeto Eclipse Modeling Framework Technology (EMFT) (líder do componente Mint). Ele possui diploma de mestrado em ciência da computação da Universidade de Massachusetts em Amherst, Massachusetts.



16/Dez/2008

Antes de Iniciar

Sobre Este Tutorial

Neste tutorial, desenvolvemos um aplicativo do jogo Sudoku simples baseado no eSWT. Primeiro vamos aprender sobre o framework eSWT, sua API e sua arquitetura. Também vamos descobrir como obter e configurar as ferramentas necessárias para a tarefa — isto é, o SDK do Eclipse com o Mobile Tools for Java (MTJ), bem como o SDK da Plataforma S60 da Nokia. Depois você vai criar um projeto MIDlet no Eclipse e utilizar a API do eSWT para desenvolver o jogo. Por fim, vamos construir e empacotar o produto final e implementpá-lo em um emulador de telefone móvel baseado em software fornecido com o SDK da Plataforma S60.

  • API— Interface de Programação de Aplicativos
  • CDC— Java Connected Device Configuration
  • CLDC— Connected Limited Device Configuration
  • DRM— Digital Rights Management
  • DSDP— Device Software Development Platform
  • eRCP— Embedded Rich Client Platform
  • eSWT— Embedded Standard Widget Toolkit
  • FP— Foundation Profile
  • GC— Graphical Context
  • GUI— Interface Gráfica com o Usuário
  • IDE— Ambiente de Desenvolvimento Integrado
  • J2SE— Java 2, Standard Edition
  • JAD— Java Application Descriptor
  • JDT— Java Development Tools
  • ME— Java Platform, Micro Edition
  • MID— Mobile Information Device
  • MIDP— Java Mobile Information Device Profile
  • MTJ— Mobile Tools for Java
  • OMA— Open Mobile Alliance
  • PDE— Plug-in Development Environment
  • SDK— Software Developer Kit
  • SWT— Standard Widget Toolkit

Os tópicos discutidos neste tutorial incluem:

  • Visão geral da Plataforma S60 e do eSWT
  • Obtenção do SDK da Plataforma S60 da Nokia
  • Configuração do SDK do Eclipse e Mobile Tools for Java (MTJ)
  • Criação de MIDlets
  • Programação com a API do eSWT
  • Implementação do MIDlet em um emulador S60

Pré-requisitos

Este tutorial destina-se a desenvolvedores Java familiarizados com o IDE do Eclipse. A familiaridade com o Standard Widget Toolkit (SWT) é útil, mas não é obrigatória. A experiência anterior com a programação Java integrada não é obrigatória.

Requisitos do Sistema

Java 2 Standard Edition
O Java 2 Standard Edition V5 ou superior estão disponível em Sun Microsystems.
Eclipse Ganymede
Localize a plataforma Eclipse V3.4 em Eclipse Foundation. O Eclipse é fornecido em um pacote configurável em várias versões. Para sua comodidade, faça o download do Eclipse IDE para Java Developers ou Eclipse IDE para Java EE Developers.
Eclipse Mobile Tools for Java (MTJ)
Localize o release mais recente do Eclipse Mobile Tools for Java (MTJ), V0.9, no Eclipse Foundation.
Nokia S60 Platform SDK, Terceira Edição
Localize o Nokia S60 Platform SDK, Terceira Edição com Feature Pack 2 no Forum Nokia. Este tutorial mostra como instalar o SDK.
Microsoft Windows XP ou Windows Vista®
O SDK da Plataforma Nokia S60 opera apenas no Windows, e como resultado, você não pode desenvolver aplicativos da Plataforma S60 utilizando Mac OS X ou Linux®. Alguns desenvolvedores no Forum Nokia relataram êxito ao executar o SDK no Wine, mas isso está fora do escopo deste tutorial.

Consulte Recursos para fazer o download de cada uma dessas tecnologias, com exceção do Microsoft Windows.


A Plataforma S60, eSWT, Java ME e os MIDlets

Nesta seção, você vai se ambientar. Primeiro você vai adquirir um pouco de conhecimento sobre a plataforma S60 e o eSWT, antes de examinar a implementação do Java Platform, Micro Edition e MIDlet.

Arquitetura da Plataforma S60

A plataforma S60, antes conhecida como Series 60, é uma plataforma de aplicativo para telefones móveis avançados ou telefones inteligentes. Ela é executada no S.O. Symbian, um sistema operacional empregado em vários telefones móveis. Desenvolvida principalmente pela Nokia, a S60 está licenciada para vários outros fornecedores de telefones móveis, como Samsung, Panasonic e LG. Observe que, embora a S60 em si não seja um software livre, houve uma iniciativa recente de transformar o S.O. Symbian em software livre.

A S60 consiste em um conjunto de aplicativos padrão, em uma estrutura de interface com o usuário e em componentes de middleware. Os aplicativos incluem telefonia, sistema de mensagens, navegação na Web, multimídia, gerenciamento de informações pessoais, aplicativos para escritório, gerenciamento de dispositivo remoto e muito mais. O design flexível e as bibliotecas padrão incluídas permitem que a S60 suporte o desenvolvimento de extensões e aplicativos de terceiros. A Figura 1 mostra uma visão geral arquitetural de alto nível da Plataforma S60.

Figura 1. Arquitetura da Plataforma S60
Arquitetura da Plataforma S60

Fornecedores de software podem utilizar uma variedade de linguagens de programação e tecnologias para desenvolver aplicativos para a plataforma S60. Além de C/C++, você pode utilizar o Java Mobile Information Device Profile (MIDP) V2.0 e também Python, Adobe Flash e outras tecnologias de navegador da Web avançadas para criar widgets da Web. A plataforma S60 facilita a interoperabilidade do fornecedor empregando inúmeras especificações abertas desenvolvidas por Open Mobile Alliance (OMA), como OMA Multimedia Messaging e OMA Digital Rights Management (DRM).

Cada release da plataforma S60 é nomeado como uma edição. Além disso, pequenos upgrades em uma edição, bem upgrades específicos de um dispositivo, são publicados como pacotes de recursos. Atualmente, o release mais recente da plataforma S60 é a quinta edição. Entretanto, a terceira edição com Feature Pack 2 é o primeiro release que suporta eSWT. Ela também está disponível em vários outros telefones móveis. Normalmente, novas edições são instaladas apenas em telefones móveis recém-liberados; dispositivos existentes não são atualizados para a edição mais recente. Entretanto, o upgrade para um pacote de recursos mais novo pode ser possível. Além disso, este tutorial utiliza a terceira edição do FP2 como plataforma de implementação de destino.

Aplicativos Remotos Java, o Jeito Eclipse

Provavelmente, o Eclipse é mais conhecido como Ambiente de Desenvolvimento Integrado (IDE) de primeira classe. Entretanto, o IDE do Eclipse abrange inúmeras tecnologias reutilizáveis. Algumas dessas tecnologias são ferramentas, como Java Development Tools (JDT) e Plug-in Development Environment (PDE). Outras são tecnologias de tempo de execução, como Equinox Framework (implementação de tempo de execução OSGi do Eclipse) e Standard Widget Toolkit (SWT). De fato, é o SWT que fornece ao Eclipse sua aparência e seu comportamento nativos.

O SWT é considerado uma alternativa para o Swing do Java, uma estrutura de GUI que é uma parte padrão do Java. O SWT foi desenvolvimento em um momento no qual o Swing não era considerado uma tecnologia de GUI adequada para um IDE avançado. O recurso peculiar do SWT é que ele é essencialmente um wrapper do Java em torno do kit de ferramentas do widget nativo do sistema operacional. Essa abordagem não só confere ao aplicativo baseado em SWT a aparência e o comportamento de aplicativos (não Java) nativos, mas também impulsiona seu desempenho, já que as bibliotecas de widget nativas provavelmente são otimizadas para o sistema operacional de destino dos mesmos.

Dentro do eSWT

A versão integrada do SWT, ou eSWT, é o SWT essencialmente adaptado para uso em ambientes limitados por recursos. O eSWT implementa um subconjunto da API do SWT, bem como extensões remotas projetadas para uso em dispositivos remotos.

O conceito central de SWT (e eSWT) é o widget. Um widget é a menor unidade de uma interface com o usuário. Janelas, diálogos, botões, barras de ferramentas, menus, itens de menu, tabelas, árvores e tabela e itens de árvore são todos widgets. Widgets que são capazes de receber eventos são chamados controles. Por exemplo, janelas, diálogos, botões, tabelas e árvores são todos controles. Entretanto, menus e itens árvore e tabela não são.

A maioria dos widgets do SWT é suportada diretamente por seu sistema operacional nativo equivalente. Ou seja, os desenhos, os eventos, o comportamento e a lógico do widget são delegados a uma biblioteca nativa que, por sua vez, utiliza a API nativa do sistema operacional de destino. Widgets indisponíveis em uma determinada plataforma são "emulados", ou desenhados de modo customizado. Como resultado, o SWT só é suportado em plataformas para as quais existe uma implementação do SWT específica para a plataforma. Entretanto, como o SWT mantém cuidadosamente sua API e sua compatibilidade comportamental entre plataformas e versões, muitas vezes é possível reutilizar componentes da UI baseados no SWT que são desenvolvidos para uma plataforma em uma ou mais outras plataformas.

Uma UI típica baseada no SWT é composta de uma árvore de widgets. Cada widget deve ser contido por seu pai (exceto para o widget de nível superior, que não precisa ter um pai). No nível superior, geralmente existe um shell, que representa uma janela. O cliente da janela é representado por um composto, que é o filho do shell da janela. O composto contém outros controles, como rótulos, controles e texto e botões. Compostos utilizam classes de Layout para controlar o posicionamento de seus filhos. Controles são capazes de responder a eventos do usuário e do S.O. Cada tipo de controle documenta quais eventos ele suporta. Clientes podem registrar listeners para controles para eventos específicos. Por exemplo, um KeyListener pode ser registrado com um controle para receber um KeyEvent sempre que o controle receber entrada do teclado do usuário. Clientes podem até interceptar o PaintEvent do controle para desenhar diretamente na superfície da tela do controle. Entretanto, normalmente isso não é necessário, já que a aparência nativa do widget é aquilo que é desejado. Um tipo de controle utilizado para desenhos customizados é o Canvas, que, ao contrário, não possui uma representação visual nativa. Ao responder ao PaintEvent do controle, o implementador pode utilizar inúmeras APIs de primitivas gráficas (por exemplo, para desenhar linhas, texto, etc.) fornecidas pela classe Graphical Context (GC), um exemplo do que está disponível a partir do PaintEvent.

Como cada widget do SWT representa um recurso de S.O. raro, a API requer que você descarte o widget assim que ele deixar de ser necessário. Portanto, você deve se lembrar de chamar o método dispose() do widget no momento apropriado. Se você não fizer isso, provavelmente o resultado será uma fuga de recursos. Recursos que não são widget, como cores e fontes, também devem ser descartados quando não forem mais utilizados.

Todas as operações do widget — criação de widgets, processamento de evento e descarte — são executadas no contexto de uma exibição. A exibição é o ponto de entrada do tempo de execução no SWT. Um aplicativo típico baseado em SWT cria uma única instância da exibição, constrói a UI desejada e implementa o que é chamado de loop de eventos da UI. Esse loop de eventos sonda continuamente a exibição de mensagens do S.O. recebidas e as despacha para os destinatários-alvo (isto é, os controles) até que recebam instrução para parar. O encadeamento que executa essa função é chamado encadeamento de exibição. Todas as interações do SWT devem ocorrer nesse encadeamento. Se outro encadeamento quiser interagir com o SWT de qualquer forma (com algumas exceções), ele deverá postar um Runnable (para executar a função desejada) no encadeamento utilizando os métodos syncExec(Runnable) e asyncExec(Runnable) da exibição. Esses pedidos são enfileirados e processados no loop de eventos da exibição.

eSWT e Java ME

Ao desenvolver software para dispositivos remotos, você deve estar ciente dos limitadores de recurso normalmente existentes no software integrado. Aplicativos remotos Java não são uma exceção. Além de pequenas telas com diferentes graus de resolução e suporte de cores, os aplicativos integrados devem lidar com memórias pequenas, energia de bateria e processamento limitados, além de dispositivos de entrada limitados.

O Java Platform, Micro Edition (Java ME) está disponível em várias configurações com base nos recursos da plataforma de destino. Esses destinos impõem limites sobre serviços de tempo de execução disponíveis, APIs e níveis de linguagem. Uma configuração representa uma Java Virtual Machine (JVM) e um conjunto de APIs comuns para uma classe de dispositivos. Um perfil é um conjunto de APIs específico de uma configuração que aborda uma classe limitada de dispositivos da mesma categoria. A Connected Limited Device Configuration (CLDC) com Mobile Information Device Profile (MIDP) é a configuração implementada com mais frequência em telefones móveis. Ela destina-se às plataformas que só podem aceitar de 128 a 512 KB para a execução de processos Java. A Figura 2 ilustra onde a CLDC e o MIDP se encaixam na pilha arquitetural de um Mobile Information Device (MID).

Figura 2. Arquitetura do MID com CLDC e MIDP
Arquitetura do MID com CLDC e MIDP

Uma diferença notável entre o eSWT e as versões de desktop do SWT é que enquanto o primeiro se satisfaz apenas com CLDC/MIDP, o segundo requer, pelo menos, uma Java Connected Device Configuration (CDC) V1.0 com Foundation Profile (FP) V1.0. A CDC destina-se a ambientes com pelo menos 2 MB de RAM e 2,5 MB de ROM disponíveis para Java. Isso possibilita a implementação do eSWT em uma variedade muito maior de dispositivos remotos, o que normalmente fornece suporte para Java CLDC/MIDP, mas não CDC/FP. Exigir CDC/FP como ambiente de tempo de execução mínimo suportado é o que também impede o eRCP de ser executado na S60. Além disso, aplicativos baseados em S60 podem utilizar eSWT, mas não o eRCP num todo. A Figura 3 descreve a arquitetura de alto nível do eSWT e sua posição em relação à plataforma nativa subjacente, Java CLDC/MIDP, e aplicativos remotos (MIDlets).

Figura 3. eSWT na Pilha Java CLDC/MIDP
eSWT na Pilha Java CLDC/MIDP

Outras implicações do desenvolvimento para CLDC envolvem o conjunto limitado de APIs. Enquanto a CDC é projetada para ter compatibilidade de API com Java 2, Standard Edition (J2SE) V1.3.1 (pelo menos em termos de API de tempo de execução básico), a CLDC fornece apenas um subconjunto de API muito menor (por exemplo, Coletas Java não estão disponíveis em CLDC). Além disso, a migração desses aplicativos J2SE para CLDC costuma envolver muito esforço. Felizmente, a API do SWT é projetada de uma maneira que não faz referência a classes ou interfaces que estão indisponíveis na CLDC.

MIDlets

Devido aos limitadores da plataforma de destino, os aplicativos gravados para o perfil do MIDP devem ser estruturados como componentes cujo tempo de vida é gerenciado pela estrutura. O ponto de entrada para um aplicativo MIDP é um MIDlet. Um MIDlet é uma classe que estende a classe abstrata javax.microedition.midlet.MIDlet. A subclasse concreta do MIDlet deve implementar três métodos abstratos: startApp(), pauseApp() e destroyApp(boolean). Esses métodos são chamados pela estrutura em diferentes pontos do tempo de vida do MIDlet. Além disso, o MIDlet deve fornecer um construtor sem argumento público. A Listagem 1 mostra uma implementação do esqueleto do MIDlet.

Listagem 1. Implementação do Esqueleto do MIDlet
package org.eclipse.eswt.sudoku;

import javax.microedition.midlet.MIDlet;
import javax.microedition.midlet.MIDletStateChangeException;

public class Sudoku extends MIDlet {

    protected void startApp() throws MIDletStateChangeException {
        // Stub de método gerado automaticamente TODO
    }

    protected void pauseApp() {
        // Stub de método gerado automaticamente TODO
    }

    protected void destroyApp(boolean unconditionally)
            throws MIDletStateChangeException {
        // Stub de método gerado automaticamente TODO
    }
}

Quando o MIDlet é construído pela primeira vez, ele encontra-se no estado pausado. Quando o software de gerenciamento de aplicativo do host decide iniciar o MIDlet, ele chama seu método startApp(). Neste ponto, o aplicativo se torna ativo. Depois o gerenciador de aplicativos pode optar por pausar o MIDlet, e nesse ponto ele vai chamar seu método pauseApp(). Quando pausado, o aplicativo libera quaisquer recursos temporários e se torna passivo. Tanto no estado ativo quanto pausado, o aplicativo pode receber uma chamada para destroyApp(boolean), pedindo que ele pare de trabalhar. O argumento booleano indica se o pedido é incondicional. Ao terminar, o aplicativo deve se tornar passivo e liberar quaisquer recursos do sistema adquiridos.

A classe abstrata MIDlet fornece métodos que permitem ao extensor verificar suas permissões (checkPermission(String)), recuperar propriedades do aplicativo do software de gerenciamento (getAppProperty(String)) e notificar o gerenciador sobre mudanças de estado, como ser retomado (notifyResumed()) ou destruído (notifyDestroyed()). O MIDlet também pode emitir pedidos para a plataforma para acessar URLs arbitrárias (platformRequest(String)); a forma como essas URLs são tratadas é dependente de plataforma. Finalmente, o MIDlet pode solicitar sua ativação quando no estado pausado (por exemplo, ao receber alguns eventos externos) chamando resumeRequest().

MIDlets normalmente são empacotados em arquivos JAR. Entretanto, um JAR do MIDlet deve conter entradas especiais em seu manifesto (META-INF/MANIFEST.MF), que descreve os MIDlets contidos no JAR. Os atributos obrigatórios incluem o nome do MIDlet (MIDlet-Name), sua versão (MIDlet-Version) e seu fornecedor (MIDlet-Vendor). Outros atributos condicionalmente obrigatórios incluem o nome de classe para cada MIDlet no JAR (MIDlet-<n> em que "n" começa em 1 e aumenta em um para cada MIDlet adicional), a configuração de Java ME necessária (MicroEdition-Configuration) e seu perfil (MicroEdition-Profile). Esses atributos são condicionalmente obrigatórios porque podem ser fornecidos em um Java Application Descriptor (JAD) externo.

O arquivo JAD é um arquivo de texto opcional que acompanha o arquivo JAR do MIDlet. Ele é utilizado pela plataforma de destino para determinar se o JAR que ele acompanha contém MIDlets compatíveis; o JAR real é transferido por download somente se todos os pré-requisitos forem atendidos. O arquivo JAD suporta os mesmos atributos que o manifesto JAR do MIDlet. Além de um MIDlet-Name, MIDlet-Version e MIDlet-Vendor correspondentes, o arquivo JAD deve conter a URL (MIDlet-Jar-URL) e o tamanho (MIDlet-Jar-Size) do arquivo JAR que ele descreve.


Preparando Seu Ambiente de Desenvolvimento

Quando o assunto é ser produtivo durante o desenvolvimento de um software — seja ele para o desktop, para um dispositivo integrado ou para a Web — mais do que nunca, são as ferramentas que fazem toda a diferença. Felizmente, existem ferramentas efetivas disponíveis para ajudar na gravação de aplicativos baseados em eSWT, e elas estão disponíveis gratuitamente.

SDK da Plataforma S60 da Nokia

O primeiro kit de ferramentas que você precisa para desenvolver um software para a plataforma S60 é o SDK da plataforma S60 da Nokia (consulte Recursos). Este kit de ferramentas fornece ferramentas, bibliotecas e documentação para o desenvolvimento de aplicativos em execução na plataforma S60 e no S.O. Symbian. O suporte para desenvolvimento de C/C++ e Java é fornecido. Entretanto, o recurso mais relevante para este tutorial é o emulador de telefone móvel rico em recursos capaz de executar o mesmo software que é executado no telefone móvel real. O emulador permite que você desenvolva e teste software em um ambiente de implementação simulado sem a necessidade de adquirir um hardware adicional.

O SDK está disponível para download gratuitamente no Web site da Nokia. Entretanto, a Nokia exige que você se registre como um membro do Forum Nokia. O Forum Nokia fornece uma variedade de recursos para desenvolvedores de software remoto, incluindo documentação, ajuda, comitês de discussão de usuários e kits de ferramentas de desenvolvimento. A associação ao Forum Nokia também é gratuita.

Após ter se registrado como um membro do Nokia Forum, você pode prosseguir com o download do SDK necessário. Existem vários tipos de SDK da plataforma S60: um para C++, um para Java e um pacote configurável multifuncional. A melhor opção é a versão all-in-one, já que ela garante que você tenha tudo que precisa para seguir adiante. Além disso, o SDK do qual você deve fazer o download é o SDK terceira edição da S60 para S.O. Symbian, Feature Pack 2 V1.1. Extraia o archive ZIP transferido por download em um diretório temporário e ative o instalador do SDK (setup.exe).

Figura 4. Instalador do SDK da Plataforma S60
Instalador do SDK da Plataforma S60

Logo após iniciar o processo de instalação, você pode receber uma mensagem informando que o Perl V5.6.1 é necessário para que tudo funcione corretamente. Você pode ignorar essa mensagem porque o Perl não é necessário para o uso do SDK para este propósito. Entretanto, você pode optar por fazer o download e instalar o Active Perl mais recente e reiniciar o processo de instalação, conforme instruções. Caso contrário, clique em Sim para continuar.

Após aceitar o contrato de licença, você pode manter as opções selecionadas para você por padrão até o final do processo de instalação. A Figura 4 mostra uma captura de tela do tipo de instalação do instalador e a tela de destino. Observe que quando for solicitado, você não precisará integrar o SDK ao IDE do Eclipse. Você vai configurar o IDE do Eclipse mais tarde e, no final, essa integração acontece até a instalação do plug-in de documentação do SDK no Eclipse (essa documentação também está disponível como um aplicativo independente). Responda Não quando aparecer um prompt sobre a instalação do CSL Toolchain (GCCE); ele não é necessário para desenvolvimento Java. Por fim, ignore quaisquer avisos relacionados ao Perl que você possa receber.

Quando a instalação for concluída, você vai encontrar um menu Ferramentas do Desenvolvedor da S60 incluído em seus programas no menu Iniciar. Você pode tentar ativar o SDK FP2 Terceira Edição > V1.1 > Emulador para verificar se a instalação foi bem-sucedida. Você vai precisar do emulador em uma condição funcional para executar o código que desenvolver.

SDK do Eclipse e Mobile Tools for Java (MTJ)

Com o SDK da plataforma S60 instalado, você pode continuar configurando o IDE. É possível utilizar uma instalação de SDK do Eclipse existente, contanto que ela seja V3.3.2 ou posterior. O Ganymede Service Release 1 (isto é, Eclipse SDK V3.4.1) é o release estável mais recente do Eclipse (consulte Recursos). Você pode transferi-lo por download em um archive ZIP pronto para uso no Web site do Eclipse e extrai-lo em um diretório de sua escolha; o ativador do Eclipse (eclipse.exe) estará no diretório eclipse.

Observe que o Eclipse requer um Java Runtime Environment (V1.5 ou posterior) recente para funcionar. Se você ainda não tiver um instalado, é possível transferi-lo por download no Web site da Sun Microsystems (consulte Recursos). Atualmente, o release estável mais recente do Java é V1.6. Siga as instruções de instalação disponíveis no Web site da Sun.

Embora seja excelente para o desenvolvimento de aplicativos Java comuns, o SDK do Eclipse sozinho não oferece muita ajuda quando se trata de desenvolvimento de aplicativo remoto. Entretanto, foi disponibilizado recentemente um novo conjunto de ferramentas de desenvolvimento que estende o IDE do Eclipse com apenas essa capacidade. O Mobile Tools for Java, ou MTJ, é um subprojeto relativamente novo do projeto Device Software Development Platform (DSDP) hospedado no Eclipse (consulte Recursos). Mesmo que o MTJ tenha publicado seu release inicial (V0.9) apenas recentemente, ele já está bem maduro, já que é uma continuação de um projeto do Eclipse ME muito bem-sucedido (não hospedado pelo Eclipse Foundation), que existe desde 2003.

O MTJ permite que você grave aplicativos Java que são executados no Java Micro Edition. Mais especificamente, ele fornece assistentes e editores para a criação de MIDlets do Java ME. Ele também permite que você controle vários aspectos do pacote MIDlet e permite a execução e a depuração de MIDlets em uma grande variedade de emuladores ou dispositivos remotos reais. Inúmeros SDKs remotos são suportados.

Você pode instalar o MTJ diretamente o SDK do Eclipse apontando o Update Manager para o site de atualização do MTJ. Alternativamente, é possível fazer o download do MTJ como um archive zip e extrai-lo no diretório de instalação do SDK do Eclipse (isto é, o pai do diretório eclipse). Observe que o pacote do qual você precisa é o MTJ Runtime V0.9.

Figura 5. Importando Dispositivos do SDK da Plataforma S60
Importando Dispositivos do SDK da Plataforma S60

Após ter instalado o MTJ, você deve configurá-lo para trabalhar com o SDK da plataforma S60:

  1. Inicie o IDE do Eclipse com uma área de trabalho vazia e alterne para a nova perspectiva do Java ME.
  2. Edite suas Preferências clicando em Janela > Preferências
  3. No diálogo Preferências, selecione Java ME>Gerenciamento de Dispositivo. Isso mostra os SDKs remotos instalados e deve estar vazio no momento.
  4. Clique no botão Importar. No diálogo Importar Dispositivos, especifique o caminho para a instalação do SDK da plataforma S60 (por exemplo, c:\S60). Um S60Emulator e um S60Device deve ser descobertos e exibidos na tabela Dispositivos, conforme mostrado na Figura 5. Clique em Concluir para importar ambos.
  5. De volta ao diálogo Preferências, o SDK da Plataforma S60 agora deve estar selecionado na parte superior da página e os dispositivos recém-descobertos devem estar listados na tabela. Marque o S60Emulator como o dispositivo padrão.

Algumas preferências adicionais devem ser ajustadas para facilitar o desenvolvimento do Java ME:

  1. No diálogo Preferências, selecione Java ME.
  2. Ajuste o Tempo Limite do Servidor de Depuração para 90000.
  3. Selecione Java > Depurar no lado esquerdo.
  4. Desmarque Suspender Execução em Exceções Não Capturadas e Suspender Execução em Erros de Compilação.
  5. Incremente o Tempo Limite do Depurador para 30000 e o Tempo Limite de Ativação para 60000.
  6. As preferências de Depuração Java ajustadas devem ser semelhantes às mostradas na Figura 6. Clique em OK para aplicar e salvar as preferências.
Figura 6. Preferências de Depuração Java Ajustadas
Preferências de Depuração Java Ajustadas

Agora você está pronto para iniciar o desenvolvimento do jogo Sudoku remoto.


Escrevendo o Jogo Sudoku

Após ter instalado e configurado todas as ferramentas de pré-requisito, você pode configurar o desenvolvimento do jogo Sudoku (consulte Download para conhecer o código fonte). Caso não esteja familiarizado com o Sudoku, ele é um quebra-cabeça numérico baseado em lógica que se tornou absolutamente popular nos últimos anos. Ele consiste em uma grade com nove linhas e nove colunas. O objetivo é preencher as células da grade com números de 1 a 9 de modo que cada número ocorra exatamente uma vez em cada linha, coluna e em cada uma das nove caixas 3x3. Inicialmente, a grade é preenchida parcialmente (o suficiente para fornecer um conjunto inicial de limitadores). As células pré-preenchidas não podem ser modificadas.

Em vez de gravar todo o código do zero, você pode utilizar uma das implementações disponíveis gratuitamente como ponto de partida. O projeto Exemplos do Eclipse fornece uma implementação baseada no Eclipse RCP. Um ponto de partida ainda melhor é a versão do eRCP do mesmo exemplo disponível no repositório do projeto DSDP. Embora o código por trás de um simples jogo Sudoku não seja muito complexo, o uso de uma implementação existente permite que você direcione o foco para as tarefas relevantes para este tutorial, como adaptar o código para execução na CLDC e utilizar a API do eSWT.

Criando o MIDlet do Sudoku

Para implementar um aplicativo Java na plataforma S60, ele deve ser construído e empacotado como um conjunto do MIDlet. O Eclipse MTJ permite que você crie novo projetos MIDlet utilizando um simples assistente. Na perspectiva do Java ME, clique em Arquivo > Novo > Projeto MIDlet. Insira o nome do projeto apropriado (por exemplo, sudoku) e certifique-se de que o Dispositivo de Destino correto seja especificado (isto é, o SDK da Plataforma S60 como o SDK e o S60Emulator como o Dispositivo). A Figura 7 mostra a página do assistente preenchida com valores de amostra. Quando você clicar em Concluir, você deverá ver o editor Descritor de Aplicativo aberto no ambiente de trabalho.

Figura 7. Assistente Novo Projeto MIDlet
Assistente Novo Projeto MIDlet

O editor Descritor de Aplicativo é utilizado para editar o arquivo JAD do projeto. Inicialmente, a única parte preenchida com dados é a página de visão geral, conforme mostrado na Figura 8. Você pode modificar o nome do MIDlet, seu fornecedor e sua versão, se quiser. Um clique na guia Descritor do Aplicativo no editor revela a visualização textual do arquivo JAD.

Figura 8. O Editor Descritor de Aplicativo do MIDlet
O Editor Descritor de Aplicativo do MIDlet

A próxima etapa lógica no desenvolvimento é criar a classe MIDlet real. No Project Explorer, clique com o botão direito do mouse na pasta src no projeto MIDlet e escolha Novo > MIDlet do Java ME no menu de contexto. Insira o nome do pacote desejado (por exemplo, sudoku) e especifique o nome de classe do MIDlet (por exemplo, Sudoku). A Figura 9 mostra a página do assistente preenchida. Quando você clica em Concluir, o assistente cria uma implementação do esqueleto do MIDlet para você. Além disso, o MIDlet recém-criado é incluído no Descritor de Aplicativo. Você pode verificar isso na página MIDlets do editor.

Figura 9. Assistente Novo MIDlet
Assistente Novo MIDlet

Antes de ir direto ao eSWT, você deve gravar um código para implementar a lógica do jogo Sudoku. Utilizando o exemplo do Sudoku do eRCP como ponto de partida, você precisa de classes que modelem o estado do jogo. Por exemplo, uma Célula representa uma célula de grade única. Ela possui um valor atual (isto é, entre 1 e 9, inclusivo); uma célula com o valor de 0 é considerada vazia. Uma Célula pode ser "fornecida", o que significa que ela vem pré-preenchida quando o jogo começa e não pode ser alterada pelo usuário. Uma Célula é considerada "válida" quando a linha, a coluna e a caixa às quais ela pertence são válidas. Por fim, uma Célula também pode fornecer uma lista de valores válidos, que são, essencialmente, qualquer valor que ainda não esteja na linha, na coluna ou na caixa da célula.

Outras classes de modelo incluem Coluna, Linhae Caixa, sendo que cada uma é uma representação direta do que elas significam. Uma Coluna representa nove células verticais na grade. Ela é válida quando não contém valores duplicados. Da mesma forma, uma Linha representa nove células horizontais na grade e é válida quando não contém valores duplicados. Uma Caixa representa uma região de células 3x3 sem sobreposição no painel. Ela também é válida quando contém somente valores exclusivos.

A classe SudokuBoard serve de contêiner da Célula, da Coluna e da Linha. Ela monitora Colunas, Linhas e Caixas inválidas (o painel é válido quando nenhuma delas é inválida). Ele é concluído quando não existem mais Células vazias. SudokuBoard também fornece métodos para se acessar várias partes de um painel, como a Célula por seu número de coluna e linha, bem como para determinar à qual Caixa uma Célula pertence. A classe SudokuBoard também suporta um mecanismo notificação simples: Objetos interessados em ser notificados sobre mudanças no painel podem se registrar no painel como listeners, contanto que implementem a interface SudokuBoardStateListener. Esse mecanismo é útil para separar a lógica do jogo de sua UI.

Finalmente, SudokuGame serve de ponto de entrada para o modelo de jogo. Ele fornece os meios para se criar novos painéis, bem como para se obter board factories e solucionadores disponíveis. Um SudokuBoardFactory é uma abstração de um algoritmo gerador de painel. Da mesma forma, um SudokuBoardSolver é uma abstração de um algoritmo solucionador do Sudoku. Uma simples implementação de um solucionador de backtracking é fornecida como gerador e solucionador. SudokuBoard também suporta um mecanismo de notificação (através de SudokuBoardChangeListener registrado) para notificar os clientes sobre mudanças no jogo, como, por exemplo, quando um novo painel for criado.

Ao comparar o código adaptado do exemplo do eRCP com a implementação original, você vai observar que alguns deles devem ser refatorados para a CLDC. Especificamente, todos os usos das classes de Coleta Java tiveram que ser refatorados para o uso de uma classe Vector muito mais simples. Da mesma forma, todos os usos de Agente Iterativo tiveram que ser convertidos em Enumeração.

Codificando a UI com o eSWT

Até aqui, você não encontrou nenhuma referência ao eSWT. O código de exemplo mantém uma boa separação de interesses. Você já aprendeu que todos os widgets do eSWT existem no contexto de uma exibição. O encadeamento que cria a instância Display do singleton se torna o encadeamento de exibição, e todas as chamadas de API do eSWT devem ser feitas de dentro dele. Além de criar widgets e controles, a tarefa do encadeamento de exibição é processar quaisquer eventos e mensagens postados nele. Quando a exibição é descartada, o encadeamento é finalizado e o aplicativo pára.

Como o tempo de vida do MIDlet é gerenciado pela estrutura, você não pode criar sua exibição e implementar seu loop de eventos da UI no método startApp() do MIDlet. Isso interceptaria efetivamente o encadeamento de chamada, que pertence ao gerenciador de aplicativos, e o bloquearia até depois do encerramento do aplicativo. Além disso, seu MIDlet deve criar um encadeamento separado e utilizá-lo como o encadeamento de exibição designado. Retornando à classe do MIDlet, você deve criar e iniciar uma nova instância de Encadeamento na primeira vez que o método startApp() for chamado. O método de execução do encadeamento é o lugar certo para você criar sua exibição e implementar o loop de eventos da interface com o usuário. A Listagem 2 mostra como isso é feito.

Listagem 2. Implementação do MIDlet Inicial com Encadeamento de Exibição do eSWT e Loop de Eventos da Interface com o Usuário
public class Sudoku extends MIDlet implements Runnable {

    private Thread thread;
    private Display display;
    private MobileShell shell;

    protected void startApp() throws MIDletStateChangeException {
        if (thread == null) {
            thread = new Thread(this);
            thread.start();
        }
    }

    public void run() {
        display = new Display();
        shell = new MobileShell(display);
        shell.setLayout(new FillLayout());
        shell.setText("Sudoku");
        shell.open();

        try {
            while (!shell.isDisposed()) {
                if (!display.readAndDispatch())
                    display.sleep();
            }
        } finally {
            display.dispose();
            notifyDestroyed();
        }
    }

    protected void pauseApp() {
        // não faz nada
    }

    protected void destroyApp(boolean unconditional)
            throws MIDletStateChangeException {
        display.asyncExec(new Runnable() {
            public void run() {
                if (!shell.isDisposed())
                    shell.close();
            }
        });
    }
}

O método run do encadeamento de exibição começa criando a Exibição e seu shell de nível superior. A classe MobileShell pode ser utilizada no lugar do shell padrão do SWT porque fornece recursos específicos para telefone móvel, como texto de status, modo tela cheia e mudanças de borda dinâmicas. O shell recém-criado pode ser utilizado como contêiner para todos os outros widgets e gráficos utilizados em todo o aplicativo. E o mais notável é que a interface com o usuário do jogo é implementada na classe SudokuView, que cuida da criação de widgets necessários na inicialização e no descarte dos recursos após a finalização. Além disso, você deve instanciar essa classe e permitir que ela crie seus widgets chamando seu método createPartControl(Composite), passando o shell de nível superior como seu contêiner. A Listagem 3 demonstra como fazer isso.

Listagem 3. Instanciando SudokuView e Descartando-o Quando o Shell For Descartado
final SudokuView view = new SudokuView();
view.createPartControl(shell);
view.setFocus();
shell.addDisposeListener(new DisposeListener() {
    public void widgetDisposed(DisposeEvent event) {
        view.dispose();
    }
});

Com os widgets necessários, você deve fornecer ao usuário uma maneira de encerrar o jogo. A classe Command fornece apenas esse tipo de funcionalidade; ela permite que você anexe um listener de seleção a um dos botões padrão do telefone móvel. O botão Sair é o lugar perfeito para o comando exit. Quando esse comando for invocado (ou seja, o botão for pressionado), o shell de nível superior deve ser simplesmente fechado. A Listagem 4 mostra o trecho de código para a criação do comando Exit.

Listagem 4. Criando o Comando Exit
Command exitCmd = new Command(shell, Command.EXIT, 0);
exitCmd.setText("Exit");
exitCmd.addSelectionListener(new SelectionListener() {
    public void widgetDefaultSelected(SelectionEvent event) {
        // não faz nada
    }

    public void widgetSelected(SelectionEvent event) {
        shell.close();
    }
});

Depois que tiver cuidado da criação do widget e da configuração do comando, você poderá abrir o shell e executar o loop de eventos da interface com o usuário padrão. Contanto que o shell não seja descartado (isto é, como resultado de um fechamento), você deverá ler e despachar eventos da interface com o usuário (chamando o método readAndDisplay()). Quando esse método retornar false, você poderá colocar a exibição no modo suspenso (chamando sleep()), que a faz aguardar até ser reativada por um evento recém-chegado. Quando o shell de nível superior for descartado, você deverá descartar a exibição e sair do encadeamento.

Normalmente, o aplicativo é encerrado quando o usuário opta por fazer isso. Entretanto, quando é executado como um MIDlet, pode ser solicitado que o aplicativo seja encerrado pelo gerenciador de aplicativos (por exemplo, em um esforço para liberar alguns recursos, etc). Além disso, o método destroyApp(boolean) do MIDlet deve sinalizar para o encadeamento de exibição que ele deve ser encerrado. Uma maneira de se fazer isso seria postar uma mensagem para o encadeamento de exibição pedindo ao shell de nível superior para fechar, parando assim o loop de eventos, descartando a exibição e encerrando o encadeamento.

Como você pode ver na Listagem 2, esse tipo de implementação de MIDlet é mais genérica e poderia suportar um aplicativo completamente diferente, contanto que toda a construção da sua UI e o processamento de eventos do usuário estejam encapsulados em uma classe do tipo SudokuView. De fato, a classe SudokuView trata da criação dos widgets necessários para desenhar o painel do jogo Sudoku, criando comandos adicionais para permitir que o usuário controle o jogo e conectando o listener do evento para tratar de eventos do teclado, bem como redimensionando e repintando. Esse padrão é resultado da refatoração do exemplo de Sudoku do eRCP, que exibe o jogo em uma visualização do eRCP, e não em um shell de nível superior (embora o conceito de contêiner separado seja aplicável).

Como o Sudoku tem natureza gráfica, sua interface com o usuário é desenhada através de primitivas de Graphical Context (GC), como linhas, planos de fundo e texto. A implementação do eRCP já fornece três classes "desenhistas" — a CellDrawer para desenhar células individuais, a BoxDrawer para desenhar caixas e BoardDrawer para desenhar o painel do jogo Sudoku inteiro. A classe DrawingContext é usada para gerenciar recursos gráficos, como cores e fontes utilizados pelas operações de desenho. O desenho do painel consiste em desenhar cada uma de suas nove caixas e todas as suas 81 células. O painel também acompanha e desenha a célula em destaque — aquela com que o usuário está interagindo no momento. Desenhar a caixa envolve o preenchimento de seu retângulo com uma cor do plano de fundo (utilizando setBackground(Color) e fillRectangle(int, int, int, int de GC), respectivamente).

Por fim, desenhar uma célula consiste em desenhar seu quadro utilizando drawRectangle(int, int, int, int), bem como seu valor atual utilizando drawText(String, int, int, int). A fonte do texto é configurada através de setFont(Font) e a cor de primeiro plano através de setForeground(Color). As células em destaque (com o mouse sobre elas) são desenhadas com uma cor diferente e com uma linha mais grossa, e seus valores disponíveis são impressos em texto pequeno junto com o quadro da célula. A Listagem 5 mostra o corpo do método drawCell de CellDrawer.

Listagem 5. Método drawCell de CellDrawer Utilizando a API de GC para Desenhar a Célula
public void drawCell(GC gc, DrawingContext context) {
    if (cell.isMarked()) {
        gc.setBackground(context.getMarkedCellColor());
        gc.fillRectangle(left, top, cellSize, cellSize);
    } else if (!cell.isValid()) {
        gc.setBackground(context.getInvalidCellColor());
        gc.fillRectangle(left, top, cellSize, cellSize);
    }

    gc.setLineWidth(1);
    gc.setForeground(context.getFrameColor());
    gc.drawRectangle(left, top, cellSize, cellSize);

    if (!cell.isEmpty()) {
        if (cell.isGiven())
            gc.setFont(context.getStaticCellFont(cellSize / 3));
        else
            gc.setFont(context.getCellFont(cellSize / 3));

        String text = String.valueOf(cell.getValue());
        Point textExtent = gc.textExtent(text);

        try {
            gc.drawText(text, left + (cellSize - textExtent.x) / 2,
                top + (cellSize - textExtent.y) / 2,
                SWT.DRAW_TRANSPARENT);
        } finally {
            gc.setFont(null);
        }
    }
}

O GC utilizado para desenhar o painel é obtido através da implementação de PaintListener em um widget de tela. A classe SudokuView cria esse controle como um filho direto do shell de nível superior. Ela também conecta um PaintListener a ele. O painel é então desenhado durante o processamento do evento de pintura da tela, que fornece acesso a seu contexto gráfico.

A interação do usuário com o jogo é manipulada através de uma combinação de KeyListener e outro comando. O KeyListener é usado para navegação no painel quando o usuário pressiona um botão de navegação direcional (esquerda, direita, para cima e para baixo). Ele também manipula o teclado numérico — o pressionamento de um número configura a célula atualmente em destaque para esse valor. Um comando select é utilizado quando o usuário pressiona o botão Selecionar (no meio do teclado de navegação). Isso aumenta em um o valor da célula atualmente em destaque. A Listagem 6 ilustra como conectar um listener de evento principal para tratar da entrada do teclado numérico.

Listagem 6. Snippet KeyListener Mostrando como Responder à Navegação com Seta
canvas.addKeyListener(new KeyListener() {
    public void keyPressed(KeyEvent e) {
        Cell hoverCell = drawer.getHighlightedCell();
        if (hoverCell == null)
            return;

        if (e.character == SWT.BS || e.character == SWT.DEL) {
            hoverCell.clear();
        } else if (Character.isDigit(e.character)) {
            hoverCell.setValue(e.character - '1' + 1);
        } else if (e.keyCode == SWT.SHIFT) {
            hoverCell.mark();
        } else if (e.keyCode == SWT.ARROW_LEFT) {
            Cell cell = hoverCell;
            do {
                int column = cell.column==0 ? 8 : cell.column-1;
                cell = board.getCell(cell.row, column);
            } while (cell.isGiven());

            drawer.highlightCell(cell);
            canvas.redraw();
...

Execução de Teste do Aplicativo

Agora que você gravou todo o código necessário, é possível fazer uma execução de teste do aplicativo no emulador de telefone móvel fornecido pelo SDK da plataforma S60 (entretanto, certifique-se de que o emulador não esteja em execução no momento).

Construindo, Empacotando e Implementando no Emulador

Graças ao Eclipse, MTJ e S60 SDK, isso é um processo relativamente direto. No editor Descritor de Aplicativo, selecione a página de visão geral e clique em Ativar como MIDlet do Java ME emulado no modo Depuração na seção Depuração. Isso criará uma configuração de ativação de depuração chamada Sudoku e a ativará. Não clique nesse link mais de uma vez, pois isso cria uma nova configuração de ativação toda vez. Você pode simplesmente escolher a mesma configuração de ativação do Histórico de Depuração novamente. Observe que o ativador cuida de qualquer pacote necessário.

Figura 10. SDK da Plataforma S60 Mostrando o Progresso da Ativação do Emulador
SDK da Plataforma S60 Mostrando o Progresso da Ativação do Emulador

Após ativar o aplicativo, você verá uma nova janela do SDK informando-o sobre o progresso, conforme mostrado na Figura 10. Durante esse tempo, o SDK inicia o emulador e ativa o aplicativo Agente de Depuração nele. Esse agente aguarda as conexões do depurador e trata da instalação e da inicialização do MIDlet. Você verá esse progresso registrado na tela do telefone móvel emulado. Quando esse processo inteiro for concluído, o que pode levar mais de um minuto, você deverá ver seu aplicativo aparecer na tela emulada. Uma captura de tela do aplicativo Sudoku em execução é mostrada na Figura 11. Observe que você precisa encerrar o emulador para reativar o aplicativo nele. Simplesmente reative a configuração de ativação do Sudoku e o SDK (e o Agente de Depuração em execução no emulador) cuidará do restante. Além disso, observe que reinicializações subsequentes levam muito menos tempo.

Figura 11. Sudoku em Execução no Emulador S60
Sudoku em Execução no Emulador S60

Em vez de ativar o MIDlet específico, você pode ativar o projeto como um JAD do Java ME emulado. Isso pode ser feito criando-se outra configuração de ativação utilizando o link Ativar como JAD do Java ME emulado na página de visão geral do editor Descritor de Aplicativo. Essa configuração de ativação é diferente da primeira porque não precisa especificar qual classe do MIDlet iniciar; o arquivo JAD é utilizado para esse fim.

Por fim, você pode deixar o MTJ construir e empacotar o jogo Sudoku para implementação em dispositivos remotos reais. Na página de visão geral do editor Descritor de Aplicativo, clique em Criar Pacote na seção de pacote. Isso criará os arquivos JAR e JAD na pasta implementada do projeto. Você pode então publicar esses arquivos em um servidor da Web que esteja disponível para os usuários do telefone móvel. Usuários podem instalar o jogo Sudoku em seus telefones móveis apenas abrindo o arquivo JAD e utilizando seu navegador da Web remoto.


Resumo

Neste tutorial, você se familiarizou com eSWT, o kit de ferramentas do widget próprio do Eclipse adaptado para uso em dispositivos remotos. Você viu como o eSWT permite que você aproveite a força da plataforma S60, que é instalada em uma grande variedade de telefones móveis. O jogo Sudoku que você desenvolveu é simples, mas serve para demonstrar as etapas que são necessárias para se gravar aplicativos baseados em eSWT para a plataforma S60. O SDK do Eclipse e o Mobile Tools for Java simplificam muito esse processo. Graças ao SDK da plataforma S60, você pode desenvolver e testar aplicativos em um ambiente emulado sem a necessidade de adquirir um telefone móvel real.


Download

DescriçãoNomeTamanho
Example Sudoku codeos-eclipse-eswt-sudoku_src.zip288KB

Recursos

Aprender

Obter produtos e tecnologias

Discutir

Comentários

developerWorks: Conecte-se

Los campos obligatorios están marcados con un asterisco (*).


Precisa de um ID IBM?
Esqueceu seu ID IBM?


Esqueceu sua senha?
Alterar sua senha

Ao clicar em Enviar, você concorda com os termos e condições do developerWorks.

 


A primeira vez que você entrar no developerWorks, um perfil é criado para você. Informações no seu perfil (seu nome, país / região, e nome da empresa) é apresentado ao público e vai acompanhar qualquer conteúdo que você postar, a menos que você opte por esconder o nome da empresa. Você pode atualizar sua conta IBM a qualquer momento.

Todas as informações enviadas são seguras.

Elija su nombre para mostrar



Ao se conectar ao developerWorks pela primeira vez, é criado um perfil para você e é necessário selecionar um nome de exibição. O nome de exibição acompanhará o conteúdo que você postar no developerWorks.

Escolha um nome de exibição de 3 - 31 caracteres. Seu nome de exibição deve ser exclusivo na comunidade do developerWorks e não deve ser o seu endereço de email por motivo de privacidade.

Los campos obligatorios están marcados con un asterisco (*).

(Escolha um nome de exibição de 3 - 31 caracteres.)

Ao clicar em Enviar, você concorda com os termos e condições do developerWorks.

 


Todas as informações enviadas são seguras.


static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=80
Zone=Linux
ArticleID=387208
ArticleTitle=Desenvolva Aplicativos Baseados em eSWT para o Telefone Inteligente Nokia S60
publish-date=12162008