Java - .NET - Games - PalmSource - Mercado - J2ME - Asp.NET
inas g á p 84
A revista do desenvolvedor Web e Wireless
Web Services a Fundo Conheça as protocolos SOA, SOAP, WSDL e UDDI
Tutorial PocketStudio Desenvolva para PALM como se estivesse usando Delphi!
ASP .NET na prática Edição 02 . Ano 01 . R$ 11,90 . Publicação Bimestral
Introdução a J2ME
Mini-curso
Pocket Pc
Construindo uma aplicação que acessa dados no SQL Server CE
Smartphone
Conheça esse dispositivo e construa suas primeiras aplicações
Aprenda a criar um cadastro de usuários
Monte passo a passo o ambiente de desenvolvimento J2ME no Windows e no Linux
HTTP e J2ME
Construa uma aplicação para celular que se comunica com uma aplicação Web
TV Digital
Games em J2ME Estamos preparados?
Aprenda passo a passo como construir um jogo com Java
wm02.indb 1
6/4/2005 22:16:50
WebM
ANO I .
Publicaรง Fevereir
Atendim
A DevM dimento
seu exem
exemplar
em conta
Aline Sa
webmobi
(21) 228
Kaline D
kalined@
(21) 228
Publicid
Para i
entre em
Luiz Clรก
publicida
Para fec
DevMedi
Gerente
Kaline D kalined@
Assisten
Jeff Wen
jeff@de
wm02.indb 2
6/4/2005 22:16:52
WebMobile
Editorial
ANO I . 02ª Edição Publicação Bimestral Fevereiro/Março . 2005
I
Editor Geral Rodrigo Spinola editorwebmobile@devmedia.com.br
Editores Técnicos Arilo Cláudio acdn@cos.ufrj.br
Guinther Pauli guinther@devmedia.com.br
Rafael Barcelos Barcelos@cos.ufrj.br
Redatores desta edição Manoel Carvalho Marques Neto, Lile Palma Hattori, Sylvio Siqueira, Juliano D. Carniel, Daniel Kúhl, Renato Haddad, Guinther Pauli, Thomas Erl, Fábio Mesquita Póvoa, Robison Cris Brito, Marcio Alexandroni Tradução Técnica Raphael Har-Zahav Jornalista Responsável Kaline Dolabella kalined@terra.com.br
Capa e Ilustrações Felipe Natividade Machado Felipe@phdesign.com.br
Diagramação e Direção de Arte Jaime Peters Junior Jaime@phdesign.com.br
Tarcisio Bannwart
nicialmente, gostaria de agradecer a você, leitor, pela aceitação que teve à WebMobile Magazine. Estamos muito felizes com os resultados obtidos com a primeira edição e continuaremos trabalhando duro para que a revista continue sendo um grande sucesso. Afinal, mobilidade é um campo que ainda deve ser bastante explorado e tem muito a crescer nos próximos meses (e anos). Estamos trabalhando para lhe trazer as principais novidades e também matérias que o auxiliem a entrar no mundo mobile. Vale aqui lembrar que quando falo mobile, me refiro também à Web, grande facilitadora desta nova perspectiva para desenvolvimento de software. Nesta edição estamos dando continuidade aos assuntos abordados na primeira edição tentando, quando possível, atender a diversas sugestões que temos recebido. Por exemplo, incluímos uma matéria apresentando o que o desenvolvedor deve ter instalado em casa para começar o desenvolvimento em J2ME. Destaco também a segunda parte da excelente matéria sobre construção de jogos que a equipe da Inova Mobile tem escrito. O mais interessante é que eles utilizam um tema tão interessante, jogos, para nos transmitir conceitos importantes sobre o desenvolvimento em J2ME. Temos ainda um artigo bastante interessante sobre a integração do J2ME com o http. Mudando de tecnologia, damos continuidade à discussão sobre a criação de aplicações .NET para a Web e Pocket PC. Nesta edição trazemos também uma novidade, o SmartPhone. Mais um dispositivo para você conhecer e explorar o mercado de desenvolvimento de software. Além disto, temos também uma matéria sobre Palm onde você aprenderá a construir uma aplicação acessando uma base de dados. Por fim, gostaria de destacar a matéria sobre TV Digital. Fiquem atentos pois esta tecnologia promete vir para ficar. Embora o governo brasileiro ainda esteja discutindo a questão da padronização do sistema para TV Digital, o momento de estudar o assunto para estar vários passos à frente quando a tecnologia se consolidar é agora. Gostaria de convidá-lo a fazer uma visita no site da WebMobile através do site www.devmedia.com.br. Ele está repleto de artigos e vídeo-aulas que complementam o conteúdo da revista – tudo gratuito! Também disponibilizamos o fórum com uma sala dedicada à mobilidade contendo os assuntos J2ME, .NET Compact Framework e Palm. Por fim, gostaria de parabenizar os ganhadores do concurso Entre no Mundo Mobile. Na categoria artigos tivemos Eloi de Souza Junior, Edgar Marçal e Roselli Martins. Na categoria aplicativos: Alexandre Gomes, Roberto Soares e Fernando Closs. Parabéns pelo excelente trabalho. Reforço aqui o meu convite para você nos acompanhar nesse novo e interessante campo da computação onde a distância e a mobilidade se tornam cada vez menos uma barreira para a troca de informação. Desejo uma ótima leitura.
Tarcisio@phdesign.com.br
Um abraço e até a próxima!!! Rodrigo Oliveira Spínola
WEB www.portalwebmobile.com.br
editorwebmobile@devmedia.com.br
Índice
Distribuição Fernando Chinaglia Dist. S/A Rua Teodoro da Silva, 907 Atendimento ao Leitor A DevMedia conta com um departamento exclusivo para o atendimento ao leitor. Se você tiver algum problema no recebimento do seu exemplar ou precisar de algum esclarecimento sobre assinaturas,
04. News
48. Introdução às tecnologias Web Services: SOA, SOAP, WSDL e UDDI Parte 2
por Rodrigo Spínola
08. Tv Digital. por Manoel Carvalho Marques Neto,
exemplares anteriores, endereço de bancas de jornal, entre outros, entre
Lile Palma Hattori e Sylvio Siqueira
em contato com: Aline Saldanha – Atendimento ao Leitor
12. J2ME Como começar? por Juliano D. Carniel e Daniel Kühl
webmobile@devmedia.com.br
21. Acesso a dados no Pocket?
(21) 2283-9012 Kaline Dolabella – Gerente de Marketing e Atendimento kalined@terra.com.br
por Renato Haddad
por Guinther Pauli
por Fábio Mesquita Póvoa
67. Conexão HTTP com J2ME
75. Desenvolvimento PalmOS utilizando PocketStudio
36. Smartphone com .NET Publicidade
55. Incrementando um jogo J2ME/MIDP usando RMS
por Robison Cris Brito
31. ASP.Net, Primeiros Passos
(21) 2283-9012
por Thomas Erl
por Marcio Alexandroni
por Renato Haddad
Para informações sobre veiculação de anúncio na revista ou no site entre em tcontato com:
Fale com o Editor!
Ícones Internos
Luiz Cláudio Barreto
É muito importante para a equipe saber o que você está achando
publicidade@devmedia.com.br Para fechar parcerias ou ações específicas de marketing com a
Atenção
Download
Editorial
Figura
Jogos
DevMedia, entre em contato com: Gerente de Marketing e Atendimento Kaline Dolabella kalined@terra.com.br Assistente de Marketing Jeff Wendell
Entrevista Links
Livros
News
Nota
Tabela
Listagem
jeff@devmedia.com.br Realização
da revista: que tipo de artigo você gostaria de ler, que artigo você mais gostou e qual artigo você menos gostou. Fique a vontade para entrar em contato com os editores e dar a sua sugestão! Se você estiver interessado em publicar um artigo na revista ou no site WebMobile, entre em contato com os editores, informando o
Minibriografia
Quadro
Tutoriais
título e mini-resumo do tema que você gostaria de publicar: Rodrigo Spinola - Editor da Revista editorwebmobile@devmedia.com.br Alfredo Ferreira - Editor do Site alfredo@clubedelphi.net
Projeto Gráfico
WebMobile 3 wm02.indb 3
6/4/2005 22:17:05
News
por Rodrigo Spinola
Vírus em celular será ameaça em dois anos Nos próximos dois anos, os vírus devem se tornar sérias ameaças aos usuários de telefones celulares, PDAs (Personal Digital Assistants) entre outros dispositivos móveis, prevê Tim Mather, diretor-chefe de segurança de informação da Symantec - Chief Information Security Officer (CISO). Conforme destaca Mather, a disseminação dos vírus móveis vai além da comunicação sem fio por meio da tecnologia Bluetooth, como tem ocorrido com o Cabir, que chegou esta semana à França e ao Japão, infectando celulares com o sistema Symbian em 17 países desde agosto de 2004. Para Mather, as pragas de dispositivos móveis devem se tornar mais complexas com o aumento da dependência dos usuários destes equipamentos. “Vamos ter algo em mente: o mundo está dependendo cada vez mais dos celulares do que dos telefones fixos. Isso cria um alvo de impacto muito maior. Se as pessoas já não têm mais telefones tradicionais em casa, o que acontece se uma rede de telefonia móvel fica indisponível?”, avalia.
Finep libera R$ 36 milhões para TV Digital Oito projetos para criação de um modelo de TV Digital brasileiro receberão o auxílio de R$ 14,5 milhões, obtidos de acordos assinados pelo Ministério da Ciência e Tecnologia e Comunicações. Outros oito projetos, que estão em fase de contratação, vão receber da Financiadora de Estudos e Projetos (Finep) R$ 14,9 milhões. Neste mês, também devem ser confirmados outros cinco projetos, em que serão investidos R$ 7 milhões. Os recursos serão liberados pelo Fundo para o Desenvolvimento Tecnológico das Telecomunicações (Funttel), que é operado pela Finep e pelo Banco Nacional de Desenvolvimento Econômico e Social (BNDES). O governo brasileiro afirma que quer criar um padrão de TV Digital diferente dos de outros países, que são essencialmente comerciais. A meta é desenvolver um modelo voltado à inclusão digital. Fonte: ComputerWorld
4 1º Edição
wm02.indb 4
6/4/2005 22:17:51
News
JBuilder 2005 A Evolução no Desenvolvimento JAVA O JBuilder representa um conceito revolucionário em ferramentas de desenvolvimento, onde se integram tecnologias de produtividade corporativa e individual, resultando em uma produção acelerada e de máxima qualidade. Um ambiente completo, com suporte consistente para todas as plataformas Java™ - seja Standard, Enterprise ou Micro Edition.
www.borland.com.br WebMobile 5
wm02.indb 5
6/4/2005 22:18:29
News Claro e Trend anunciam antivírus para celular A Claro anunciou recentemente uma parceria com a empresa de segurança Trend Micro para o fornecimento de antivírus e antispam para telefones móveis e PDAs. A parceria prevê que os assinantes da Claro utilizem o Trend Micro Mobile Security (TMMS) sem nenhum custo até junho de 2005. A partir de então, a solução deverá ser tarifada. Até o momento, o valor não foi informado. Segundo Rodrigo Pellicciari, gerente de marketing da Trend Micro, as ferramentas têm a intenção de conter as ameaças que chegam ao aparelho por meio da sincronização do celular ou PDA com o computador, por cartões de memória infectados, pela navegação na internet ou por mensagens transmitidas via Bluetooth de um smartphone para outro. A ferramenta antivírus mapeia os arquivos que estão sendo baixados no aparelho e informa ao usuário por meio de um alerta sobre a existência de vírus. Já o anti-spam é responsável por bloquear as mensagens de texto (SMS) indesejadas. Os dois sistemas cobrem tanto o sistema operacional Symbian quanto o Windows Mobile e estarão disponíveis na internet para download para o PC ou diretamente para o celular. Até o momento, a Claro não informou a página na web que oferecerá o programa. Fonte: IDGNow
Descoberto novo cavalo-de-tróia para celular A F-Secure anunciou recentemente a descoberta de uma nova variante do Cabir, mas que é diferente o suficiente para receber uma nova classificação: Dampig.A. Segundo a empresa de segurança finlandesa, a nova praga chega a celulares equipados com sistema operacional Symbian por meio de conexões Bluetooth. O Dampig, a exemplo do Cabir, se apresenta ao usuário como um aplicativo de segurança, mas desabilita diversas aplicações e gerenciadores de arquivos instalados. Outra má notícia é a chegada de uma variante do Cabir à França. Um jornalista daquele país informou que seu chefe foi infectado pela praga enquanto fazia a cobertura da feira de telecomunicações 3GSM, ocorrida de 14 a 17 de fevereiro em Cannes. Até o momento, o número de países oficialmente infectados pelo Cabir é de 17.
Motorola investe US$ 5 mi em centros de P&D O Brasil sediará os primeiros centros mundiais de desenvolvimento da Motorola nas áreas de novas aplicações para telefonia móvel e na plataforma SoftSwitch, nova versão das centrais de comutação, que já tem como cliente a operadora Vivo. Ambos os centros demandarão um investimento total de 5 milhões de dólares e empregarão 20 técnicos, informou Maurício Gomes, diretor de Soluções de Rede da Motorola Brasil, durante o
lançamento realizado na Telexpo 2005, em São Paulo. O Centro de Desenvolvimento de SoftSwitch, que será localizado em Jaguariúna, no interior de São Paulo, inicia suas operações entre junho e julho deste ano. Segundo Gomes, o centro foi impulsionado pela demanda da Vivo e será voltado inicialmente para inovações na tecnologia CDMA (Code Division Multiple Access), mas a intenção é buscar parcerias com outras operadoras em todas as tecnologias. O centro de desenvolvimento de novos aplicativos, que concorreu com países como Índia, China e Japão, receberá 3 milhões de dólares do total investido nos dois centros da Motorola. A operação ainda não tem local definido, será criada até o final do ano e se concentrará em aplicações de telefonia celular de próxima geração, o que inclui o desenvolvimento em Java e sistemas de código aberto. Entre as cidades cotadas para sediar o centro está Campinas, no interior de São Paulo. Os novos centros fazem parte do Programa de Desenvolvimento Tecnológico da Motorola Brasil, que recebeu mais de 175 milhões de dólares desde sua criação em 1997 e contempla três centros próprios, além de oito em parceria com universidades brasileiras. Fonte: IDGNow
Palm se aproxima do Linux A PalmSource, fornecedora de sistemas operacionais para equipamentos portáteis, apresentou recentemente uma linha de softwares para telefones móveis e Personal Digital Assistants (PDAs) que pode ser o primeiro passo da empresa para a criação de plataformas em padrões abertos. No total foram quatro novas aplicações próprias que incorporam ferramentas desenvolvidas pela China MobileSoft, empresa recém-adquirida pela PalmSource e que produz Linux para telefones celulares. Os anúncios da PalmSource foram feitos durante o congresso mundial 3GSM, que aconteceu no dia 17/02, em Cannes, na França. Fonte: www.palmland.com.br
HP e Nokia lançam caneta digital com Bluetooth A Hewlett-Packard e a Nokia lançaram um sistema de documentos eletrônicos que possui uma caneta que é capaz de armazenar o que o usuário escreve no papel e transferir o conteúdo sem fio para PDAs, celulares e computadores. O dispositivo tem memória para guardar até 100 páginas do tamanho de blocos de anotação. A caneta faz parte do Sistema de Automação de Formulários da HP, tecnologia criada para eliminar a tarefa de digitalização de documentos, como pedidos de produtos ou prontuários médicos, que precisavam passar por um scaner ou ter os dados redigitados do papel no computador. Outro uso é escrever e-mails no papel e enviá-los aos destinatários via conexão sem fio com o celular. A caneta, Nokia Digital Pen, tem tecnologia de transmissão de dados Bluetooth, que pode enviar as anotações para o servidor da empresa ou para o celular de um funcionário sem necessidade de cabos. Fonte: www.palmland.com.br
6 1º Edição
wm02.indb 6
6/4/2005 22:18:48
wm02.indb 7
6/4/2005 22:18:52
TV Digital Estamos preparados?
por Manoel Carvalho Marques Neto, Lile Palma Hattori e Sylvio Siqueira Silva
A
televisão digital é mais um grande avanço tecnológico que deverá chegar aos lares brasileiros em poucos anos. Mas o que a torna tão diferente da atual televisão analógica? A transmissão digital oferecerá a possibilidade de interação entre o telespectador e os novos serviços oferecidos como a escolha de programas independente de horário, acesso à internet e compras pela TV. Outra característica importante é que o sinal digital pode ser capturado por receptores móveis, o que torna possível, por exemplo, assistir televisão pelo telefone celular. A grande questão é saber se estamos preparados para usufruir desta nova tecnologia. Este artigo descreve algumas das peculiaridades da TV digital, as dificuldades presentes na implantação e as oportunidades que esta tecnologia trará para o mercado de desenvolvimento de hardware e software.
O padrão brasileiro O governo brasileiro está investindo em pesquisas para disponibilizar o Sistema Brasileiro de TV Digital com custo reduzido para a população. Para isto, está contando com grupos de pesquisadores de diversas universidades para definir o padrão de transmissão que será adotado. Atualmente, os padrões mais utilizados no mundo são o americano ATSC (Advanced Television Systems Committee), o europeu DVB (Digital Video Broadcasting) e o japonês ISDB (Integrated Services Digital Broadcasting). O ATSC foi definido pela U.S. Federal Communication Commission (FCC) e adotado pelos países da América do Norte, Coréia do Sul, Argentina, dentre outros. O padrão refere-se a uma grande variedade 8 2º Edição
wm02.indb 8
6/4/2005 22:18:54
Tv Digital
de subsistemas necessários para geração, codificação, transmissão, transporte, recepção de vídeo, áudio e dado. Possui apenas os tipos de transmissão ATSC-T e ATSC-C. Adota o padrão Audio Compression (AC-3) para codificação de áudio e o MPEG-2 para vídeo. Apesar de estar bastante difundido, possui algumas limitações como a impossibilidade de ser utilizado em receptores móveis e ser controlado pelas companhias Zenith e LG, que não dispensam o pagamento de royalties. Já o DVB foi adotado por aproximadamente 15 países europeus, além da Austrália e Nova Zelândia. Definiu os padrões DVB-C, DVB-S e DVB-T. Ainda encontra-se em processo de desenvolvimento o padrão DVB-H. Emprega o MPEG-2 para codificação de áudio e vídeo e adotou o middleware Multimedia Home Plataform (MHP) para dar suporte a aplicações interativas. O japonês ISDB foi desenvolvido pelo Digital Experts Group (DiBEG) e define os padrões ISDB-C, ISDB-S e o ISDB-T. É atualmente o padrão mais flexível, permitindo que aplicações variadas sejam disponibilizadas ao usuário. É, também, o mais tecnologicamente avançado, oferecendo a possibilidade de transmissão para aparelhos móveis, possuindo convergência total com telefones celulares da terceira geração. O Ministério das Comunicações, através do decreto no 4.901, de 26 de novembro de 2003, instituiu o Sistema Brasileiro de Televisão Digital (SBTVD) e criou um comitê de desenvolvimento, um comitê consultivo e um grupo gestor, para dar início às pesquisas que optariam por definir a criação de um padrão brasileiro ou a adoção de um dos três acima citados. Esta decisão seria tomada em março deste ano, porém até fevereiro, às vésperas do encerramento das pesquisas, menos de um terço dos recursos tinham sido liberados aos pesquisadores e o Grupo Gestor de TV Digital recomendou ao Comitê de Desenvolvimento a prorrogação do prazo para 12 de dezembro.
canal de televisão e é formado por vários streams elementares. O MPEG transmite somente partes da imagem que mudaram de um frame para o próximo, ao invés de enviar o próximo frame completo, reduzindo a quantidade de dados que precisam ser enviados para reconstruir a imagem original. Este tipo de compressão permite uma melhor utilização do espaço do canal de transmissão e o conseqüente aumento do poder de envio de informação. Outro serviço oferecido, o acesso à internet, já é familiar a parte da população. Isso já ameniza outra preocupação do governo brasileiro, que é prover acesso à rede mundial de computadores. Porém, este acesso será diferente da navegação convencional via PC. Provavelmente essa navegação será baseada na infra-estrutura disponível na televisão, que não dispõe dos periféricos de um computador, tais como: teclado, mouse, etc. Comprar pela TV será um atrativo tanto para o telespectador quanto para o mercado. Atualmente, os produtos anunciados pela televisão são geralmente vendidos por telefone. Com a TV digital, o telespectador terá a comodidade de comprar utilizando simplesmente o controle remoto. Este serviço será de fundamental importância para o mercado brasileiro, pois haverá uma grande possibilidade de alavancar as vendas dos mais diversos setores de comércio e indústria. Além destes, serão oferecidos diversos outros serviços que proverão entretenimento, informação e atividades familiares. Jogos, pay-per-view, vídeos sob demanda serão formas de entretenimento enquanto acesso a banco e compras serão serviços que facilitarão o dia-a-dia do usuário. Um outro serviço viável a partir da utilização de TV digitais consiste no relacionamento com outros aparelhos de comunicação móveis, como telefones celulares, palmtops, dentre outros dispositivos.
Os novos serviços
A depender do padrão de TV digital a ser adotado pelo Brasil, será possível efetuar a recepção de sinal por celulares 3G (terceira geração). O padrão americano que está sendo fortemente cogitado não oferece suporte a transmissão para receptores móveis. Caso este padrão seja adotado, um mercado em potencial de desenvolvimento de aplicativos específicos para telefones celulares deixará de ser explorado. Em contrapartida, se o padrão japonês for adotado, ou até mesmo se o padrão brasileiro venha a ser desenvolvido, com suporte a transmissão para receptores móveis, o desenvolvimento de navegadores que adaptem as imagens para o tamanho do visor do celular será de grande importância.
O advento do sinal digital em conjunto com um canal de retorno possibilitará o fornecimento dos mais variados serviços. O principal é, sem dúvida, a liberdade que o usuário terá em fazer sua própria programação. Atualmente, o telespectador está preso à programação determinada pela emissora e precisa esperar o horário em que começa seu programa preferido. A TV digital permitirá que este usuário assista ao programa no horário mais conveniente às suas atividades diárias. Aliado a isso, a transmissão digital permite a disponibilização de um número cinco vezes maior de canais de TV em relação aos analógicos, trazendo muito mais opções para os telespectadores do que hoje em dia. Isto é possível porque a transmissão digital é feita de forma otimizada. Cada canal é comprimido e convertido num stream de dados, chamado de transport stream, utilizando o Moving Pictures Experts Group (MPEG-2). Um transport stream corresponde a um
TV digital em celulares
Desenvolvimento de aplicações O desenvolvimento de aplicações para TV digital tem características distintas do desenvolvimento para PC. Alguns aspectos precisam ser considerados quando pensamos em propor uma WebMobile 9
wm02.indb 9
6/4/2005 22:18:55
aplicação para esta nova tecnologia. Um telespectador, por exemplo, costuma posicionar-se a uma distância da televisão no mínimo três vezes maior do que uma pessoa em relação a seu PC, porém a resolução de uma TV é inferior à de um monitor. Isto força a utilização de fontes grandes além da adaptação das dimensões gráficas de aplicações ao dispositivo. Em um PC existem periféricos como o mouse e o teclado que facilitam a interação do usuário com os diversos aplicativos. Na TV, um fator limitante na construção de aplicações é a existência, na maioria dos casos, do controle remoto como único periférico. Além disso, é importante levar em consideração aspectos como o perfil do usuário. O telespectador não irá tolerar aplicações com uma navegação complexa como, a utilização demasiada de menus em cascata. No momento, as duas principais API’s para desenvolvimento de aplicação para TV digital são: Microsoft TV e Java TVTM. Microsoft TV A Microsoft TV é uma plataforma fechada, desenvolvida especialmente para operadoras de televisão pagas. A Microsoft TV Foundation Editon 1.7 oferece gravação de vídeo digital (DVR), suporte a televisão de alta definição (HDTV) e vídeo sob demanda. Além disso, também oferece uma grade de programação interativa (IPG) para que os usuários possam navegar nos diversos programas de forma fácil e rápida. Suas principais características são: personalização da interface; buscas por título, descrição, categoria, tópico ou dia e hora; bloqueio de certos canais; autorização para pacotes pay-per-view; DVR inteligente dentre outros. A Microsoft está desenvolvendo uma nova solução baseada no protocolo de redes IP para comunicação: Internet Protocol TV (IPTV). Tal solução se propõe a trazer uma melhora em diversos serviços, tais como: seleção de conteúdo, navegação, troca de canais, vídeo sob demanda, gravação de vídeo digital e qualidade da definição da imagem. Pouco se sabe sobre a implementação do Microsoft Foundation Edition, contudo, a Microsoft fornece uma ferramenta para desenvolvimento de aplicações para o seu produto. O Microsoft Tools Suite é baseado na ferramenta de desenvolvimento Microsoft Visual Studio® .Net, que inclui exemplos de esquema para conteúdos digitais, exemplos de códigos de aplicações e um ambiente de debug de fácil uso com um emulador para simular o comportamento de set-top boxes. Um set-top box é uma interface entre a TV e um centro retransmissor (satélite, cabo terrestre, etc). Em um nível mais básico, ele é apenas um sintonizador de canais, fazendo a conversão dos sinais de TV. Porém, este dispositivo pode ser utilizado ainda como mecanismo para implementar aplicativos nos mais diversos domínios (segurança, comércio eletrônico, telefonia etc.). Um set-top box pode ser considerado a parte “computacional” de um sistema de TV digital. É como se um computador com um poder de processamento baixo fosse acoplado ao aparelho de TV.
Java TV A Java TV é uma API aberta que estende a plataforma Java. Foi desenvolvida pela Sun para prover acesso em receptores de televisão digital às seguintes funcionalidades: fluxo de áudio e vídeo, acesso condicional, acesso a dados nos canais de transmissão, acesso aos dados do serviço de informações, controle de sincronizador de canais e gerenciamento do ciclo de vida das aplicações. A 1 mostra uma típica pilha de software para um receptor de televisão digital. A camada de hardware é o chamado set-top box. Acima da camada de hardware está a camada RTOS (sistema operacional de tempo real). A camada da tecnologia Java consiste no ambiente de software, que é formado pela plataforma Java e a API Java TV. Esta última oferece uma camada de abstração que permite aos programadores de aplicações explorarem as funcionalidades de um set-top box ignorando os detalhes específicos deste dispositivo. As bibliotecas da Java TV permitem o desenvolvimento de conteúdo interativo como vídeo sob demanda, guias eletrônicos de programação e transmissão de eventos esportivos em múltiplos ângulos. A biblioteca J2ME poderá ser combinada com a Java TV para criar aplicativos para aparelhos celulares.
Primeiros passos para a construção de uma aplicação O primeiro passo para iniciar o desenvolvimento de uma aplicação para TV digital é a escolha do padrão de transmissão a que ela será destinada. Esta escolha é importante, pois os metadados, que fornecem informações sobre o que é transmitido, variam entre cada padrão. Estas informações são essenciais para a construção de qualquer aplicativo nesta área que promova interação, pois estes necessitarão interpretar estas informações de forma correta para transmitir ao telespectador. Por ser open-source, recomendamos a utilização da tecnologia Java ao iniciar o desenvolvimento de uma aplicação para a TV digital. O Java oferece as seguintes API’s que dão suporte à construção destes sistemas: J2ME, JMF e Java TV. Tanto a documentação quanto as API’s podem ser encontradas no site da Sun (www.sun.com). Seria interessante simular um ambiente de TV digital para realização de testes da aplicação criada. Este ambiente pode ser montado conectando-se o aparelho de TV a uma placa de vídeo do computador. O computador então funcionaria como um set-top box.
1.Típica Pilha de Software em um receptor de TV Digital.
10 2º Edição
wm02.indb 10
6/4/2005 22:18:57
Tv Digital
Para aprimorar esta simulação é possível programar um controle remoto universal fazendo com que ele se comunique com o computador via infravermelho. Existe uma API que dá suporte a este tipo de comunicação. Ela está disponível no site da HP (www.hpl.hp.com/personal/Jean_Tourrilhes/IrDA/docs/index.html).
A transição Existem muitas perguntas sobre como a televisão digital chegará ao lar de todos os brasileiros. Discutiremos a seguir algumas delas: Como os novos serviços serão disponibilizados ao brasileiro sem que ele tenha que trocar de televisão? O brasileiro leva em média 15 anos para trocar de televisão. Por causa desta estimativa, pesquisas estão sendo realizadas no intuito de desenvolver um aparelho que fará a tradução do sinal digital para o sinal analógico dos televisores convencionais. Além disso, este aparelho tornará acessíveis todos os serviços disponíveis na transmissão digital. Para que este aparelho se torne de fácil aquisição pela população, o governo tem o intuito de subsidiar sua fabricação. O usuário brasileiro está apto a utilizar estes novos serviços? É certo que o brasileiro, em geral, não está familiarizado com serviços deste tipo. Apenas 10% da população tem acesso a internet, enquanto que 87% faz uso da televisão convencional, e ainda 27% dos televisores não são a cores. Além disso, existem problemas quanto ao perfil dos usuários. Assim, o desenvolvimento de interfaces navegacionais interativas deverá levar em consideração os diversos perfis de usuários existentes. Será que o sistema terá aceitação da população? Diferente do problema do usuário querer usar os serviços e não ser capaz, é ele não querer utilizá-los. Há um grande risco da população rejeitar o novo sistema, quer seja pela dificuldade de uso ou pela falta de interesse. Segundo o CPqD (Centro de Pesquisa e Desenvolvimento em Telecomunicações), os consumidores acreditam que, de início, os preços dos receptores serão elevados, mas devem cair com a sua disseminação. Acreditam ainda que a aceitação do serviço está intimamente ligada à qualidade de som e de imagem esperada, que deve ser semelhante à do DVD. Qual o estado de desenvolvimento da TV digital no Brasil e quais as perspectivas? A perspectiva é que até março de 2006 o primeiro sinal de TV digital seja emitido no Brasil. O presidente Luis Inácio Lula da Silva afirmou que gostaria de assistir a copa do mundo da Alemanha já na sua TV digital. Fabricantes de eletroeletrônicos estimam que vai levar um período de dez a vinte anos até que o televisor analógico seja definitivamente aposentado e substituído pelo digital.
de Televisão Digital. Existem diversos trabalhos sendo desenvolvidos nesta área. Atualmente estamos desenvolvendo uma interface de navegação visual, chamada provisoriamente de TV Navigator, que facilite a interação do usuário com os diversos serviços oferecidos pela tecnologia de TV digital. Ainda há muito a ser discutido e muito trabalho a ser realizado até que o sistema esteja pronto e funcionando, mas certamente esta é uma área muito promissora.
Glossário ATSC-T, DVB-T, ISDB-T: padrões de transmissão via broadcast terrestre (Broadcast é a transmissão para todos, como acontece na TV aberta). ATSC-C, DVD-C, ISDB-C: padrões de transmissão via cabo. DVB-S, ISDB-S: padrões de transmissão via satélite. DVB-H: padrão que define a transmissão do sinal digital para dispositivos móveis. AC-3: padrão para compressão de áudio. MPEG-2: padrão para compressão de áudio e vídeo.
Manoel Carvalho Marques Netol (manoelnetom@bol.com.br) é mestre em Redes de Computadores pela Universidade Salvador – UNIFACS. Trabalha com desenvolvimento de aplicações em para dispositivos móveis. É professor da Faculdade Ruy Barbosa e Universidade Salvador UNIFACS. É também pesquisador do CEPERC – Centro de Pesquisas em Redes de Computadores – UNIFACS.
Lile Palma Hattori (lile@terra.com.br) é estudante de Ciência da Computação pela Faculdade Ruy Barbosa em Salvador-BA. Trabalha com desenvolvimento de aplicações em Java na Fábrica de Software da Unitech Tecnologia de Informação Ltda.
Sylvio Siqueira Silva (sylvio@frb.br) é estudante de Ciência da Computação pela Faculdade Ruy Barbosa em Salvador-BA. Trabalha com desenvolvimento de aplicações em Java na Fábrica de Software da Unitech Tecnologia de Informação Ltda.
Conclusão
Faça o download no site:
Este artigo abordou alguns dos temas vastamente discutidos pelas entidades envolvidas na implantação do Sistema Brasileiro
www.portalwebmobile.com.br/revista/ed2
WebMobile 11
wm02.indb 11
6/4/2005 22:19:02
: Er? U
a M ç 2ome
Jmo c
Co r
po
hl
r
l nie
no
J
a uli
Ca D.
e
ü l K e i n Da
Leitura Obrigatória
Web Mobile 1 Introdução ao J2ME.
ma das dificuldades encontradas para se iniciar um projeto para dispositivos móveis está justamente ligado a como começar, o que utilizar e o que fazer. É justamente isso que iremos abordar nesta matéria. Para isso, discutiremos: como instalar, configurar e iniciar o desenvolvimento em J2ME; a instalação básica do J2SE (kit de desenvolvimento Java) no Linux e no Windows; a instalação do Java Wireless Toolkit 2.2 (WTK22) que é a plataforma de desenvolvimento Java para dispositivos móveis; algumas ferramentas que nos auxiliam em um melhor desenvolvimento de aplicações; a instalação e configuração do plug-in EclipseME no IDE Eclipse. As plataformas abordadas neste tutorial serão Windows e Linux (SuSE 9.0).
O que é necessário? Os elementos básicos para iniciarmos o desenvolvimento em J2ME, segundo a abordagem descrita neste artigo são: Windows 2000 ou Linux (Fedora Core 2, SuSE 9.0, Debian 3.0r2, RedHat 9.0); J2SE (SDK); Wireless Toolkit (WTK); E um IDE qualquer para codificarmos nossos programas. É importante ressaltar aqui que o WTK não é um editor de código, ou seja, você não consegue escrever seus códigos Java através dele. Ele possibilita utilizar o IDE de sua preferência para desenvolvimento para dispositivos móveis. O IDE escolhido para este artigo foi o Eclipse. A escolha se deu por ele ser um ótimo IDE, ser OpenSource e também por possuir um plug-in para o desenvolvimento em J2ME. Contudo, poderíamos usar qualquer outro IDE ou até mesmo um editor de texto qualquer. Com relação a hardware, o mínimo necessário para um bom funcionamento das aplicações utilizadas nesta abordagem é: 50 MB de espaço em seu HD; 128MB de memória RAM; Pentium III com 800MHz. 12 2º Edição
wm02.indb 12
6/4/2005 22:19:26
Java
Instalando e configurando o J2SE Para a instalação e configuração do J2SE em sua máquina, dois passos deverão ser seguidos de acordo com o sistema operacional que você esteja utilizando.
variáveis de ambiente) adicione essa linha (apontando para o diretório onde se encontra a sua instalação do J2SDK): JAVA_HOME=$JAVA_HOME:/usr/java/j2sdk export JAVA_HOME
Passo 1: Download e instalação do SDK Primeiramente você precisa fazer o download do SDK no site da Sun. Você pode encontrá-lo em http://java.sun.com/j2se/ downloads.html. No site, clique no link J2SE 5.0 para baixar a última versão do Java Standart Edition. O link para download nos redirecionará para uma página com os termos de uso. Após aceitá-lo, seremos redirecionados para uma outra página contendo várias versões do SDK para diversos sistemas operacionais, baixe então o que condiz com o seu. Caso já o tenha instalado em sua máquina, este tópico pode ser ignorado. Instalação do J2SE no Linux Após ter feito o download do arquivo, execute os seguintes comandos (você deve estar logado como root). O arquivo baixado chama-se jdk-1_5_0_02-linux-i586.bin. Onde lê-se # é o shell do root. # chmod 755 jdk-1_5_0_02-linux-i586.bin
É importante também adicionar o caminho para os binários do Java ao seu $PATH. Adicione então a seguinte linha ao /etc/profile: PATH=$PATH:/usr/java/j2sdk/bin
Antes de verificar se a instalação foi feita corretamente é necessário recarregar as variáveis de ambiente. Existem duas opções para isso. A primeira é dar um logout e logar novamente, a segunda é executar o comando: # source /etc/profile
Este comando recarrega todas as variáveis definidas no arquivo /etc/profile. Feito isso, para verificar se a instalação do J2SE no linux foi bem sucedida, execute o comando:
# ./jdk-1_5_0_02-linux-i586.bin # java –version
Quando executado o arquivo instalador no Linux, ele ira extrair os arquivos para o diretório jdk1.5.0_02 a partir do diretório onde você o executou. Aconselho mover esse diretório para um outro mais fácil. Por exemplo, executando o seguinte comando moveremos o diretório extraído para o diretório /usr/java:
A saída deverá ser: java version “1.5.0_02” Java(TM) 2 Runtime Environment, Standard Edition (build 1.5.0_02-b09) Java HotSpot(TM) Client VM (build 1.5.0_02-b09, mixed mode, sharing)
# mv jdk1.5.0_02 /usr/java ira ficar /usr/java/jdk1.5.0_02
Caso apareça algum erro do tipo: Guarde bem o diretório onde mandou instalar o j2sdk, pois iremos precisar dele para os próximos passos. Instalação do J2SE no Windows Depois de efetuar o download do arquivo, basta instalarmos ele e seguirmos as instruções de instalação. Guarde bem o diretório onde mandou instalar o j2sdk pois iremos precisar dele para os próximos passos. Passo 2: Configuração das variáveis de ambiente Quando a instalação estiver pronta, precisaremos configurar nossas variáveis de ambiente para que o Java possa ser reconhecido como comando válido em seu ambiente. Para isso siga os passos referentes ao seu sistema operacional.
-bash: java: command not found
certifique-se de que o caminho informado para os binários do j2sdk foi relacionado corretamente na variável de ambiente $PATH no arquivo /etc/profile. Windows Vá até o Meu Computador e clique em Propriedades. Na aba Avançado, clique no botão Variáveis de Ambiente. Vá até o grupo Variáveis de Sistema e adicione as seguintes variáveis com os seguintes valores: JAVA_HOME = c:\j2sdk (ou o local onde você o instalou) CLASSPATH = . (ponto para indicar o diretório corrente)
Linux No arquivo /etc/profile (utilizado pela shell bash. Caso você utilize outro, consulte a documentação referente para alterar as
E edite a seguinte variável, adicionando o seguinte valor: PATH = %JAVA_HOME%\bin (diretório que contém os binários do Java)
WebMobile 13
wm02.indb 13
6/4/2005 22:19:39
Lembrando que o separador de valores é um ; (ponto-e-vírgula). Para verificar se o Java foi corretamente instalado, abra um novo Prompt de Comando e digite:
Linux Você deverá executar os seguintes comandos como root. O arquivo baixado para seu computador chama-se:
# java –version
j2me_wireless_toolkit-2_2-bin-linuxi386.bin.
A saída deverá ser: java version “1.5.0_02”
Para começar a instalação, devemos atribuir o atributo de execução ao arquivo de instalação. Isso é feito executando o seguinte comando como root:
Java(TM) 2 Runtime Environment, Standard Edition (build 1.5.0_02-b09) Java HotSpot(TM) Client VM (build 1.5.0_02-b09, mixed mode, sharing)
Caso apareça algum erro do tipo:
# chmod a+x j2me_wireless_toolkit-2_2-bin-linuxi386.bin
Depois de dada a permissão de execução, execute o arquivo baixado:
‘java’ is not recognized as an internal or external command, operable program or batch file.
# ./j2me_wireless_toolkit-2_2-bin-linuxi386.bin
certifique-se de que o caminho informado para os binários do j2sdk foi relacionado corretamente na variável de ambiente $PATH.
Feito isto, será dado inicio à instalação do WTK 2.2 (ver 1). Caso ocorra algum erro indicando que instalador não está encontrando o arquivo jar, crie um link simbólico para o caminho que o instalador está tentando procurar, por exemplo, se o erro for:
Instalando e configurando o WTK Assim que tivermos o SDK instalado e perfeitamente configurado, podemos realizar o download do WTK no endereço http://java.sun.com/products/j2mewtoolkit/download-2_2.html. No final da página encontramos o link para download, o qual nos levará para uma nova página contendo os termos da licença. Clique em Accept caso você aceite os termos. Feito isto, serão apresentados dois links, um para download da versão para Windows e outra para Linux. Faça o download que condiz com o seu sistema operacional.
# ./j2me_wireless_toolkit-2_2-linux-i386.bin: line 362: /usr/ java/jdk1.5.0_02/bin/jar: No such file or directory
a solução seria: # ln -s `which jar` /usr/java/jdk1.5.0_02/bin
O executável encontra-se no diretório bin de onde você instalou o WTK. No nosso exemplo ele se encontra em:
/usr/java/WTK2.2/
1. Instalação do WTK 2.2.
JVM Folder /usr/java/jdk1.5.0_02/bin/
Do you agree to the above license terms? [yes or no] yes
Testing /usr/java/jdk1.5.0_02/bin/java...
Please choose one of the following options: 0) Begin copying files if you are satisfied with the settings
A suitable Java interpreter was detected
. 1) Cancel the installation.
0) Use /usr/java/jdk1.5.0_02/bin/
Select a choice [0-1]: 0
1) Specify a path to a Java interpreter directory.
Checksumming...
2) Cancel this installation. Select a choice [0-2]: 0
Extracting the installation files... Documentation for the J2ME Wireless Toolkit version 2.2 is in
Please enter a directory into which you would like to install the J2me Wireless Toolkit, 2.2. [ default is /usr/java/WTK2.2 ]:/usr/java/WTK2.2 Current Settings:
the file /usr/java/WTK2.2/index.html In order to start using the J2ME Wireless Toolkit, please run /usr/java/WTK2.2/bin/ktoolbar
Destination Directory
14 2º Edição
wm02.indb 14
6/4/2005 22:19:40
Java
definido na combo (Device) abaixo dos botões; Clear Console: limpa a tela de saída.
/usr/java/WTK2.2/bin/ktoolbar
Com a instalação completa, estamos prontos para iniciar o desenvolvimento em J2ME. Execute o comando na tela de console do Linux: /usr/java/WTK2.2/bin/ktoolbar
Lembrando que você deve estar dentro do ambiente gráfico do Linux e este comando pode ser executado como usuário comum. Este será o programa mais usado por você no desenvolvimento de aplicativos. Windows Após ter
sido
feito
o
download do arquivo execute-o para dar início à instalação do WTK. Após a aceitação dos termos de licença, você deverá escolher a base de onde estão instalados os arquivos do JDK. Se ele não mostrar automaticamente (foi configurado nas variáveis de ambiente) você terá que indicar a base de instalação do SDK. No próximo passo, escolha onde instalar o WTK propriamente dito. A instalação transcorrerá sem problemas. Caso ocorra algum problema de não encontrar os arquivo do JDK, você deve se certificar de que instalou o JDK e o configurou corretamente. Caso tenha dúvidas, volte à sessão onde explico esse procedimento. Com a instalação completa, estamos prontos para iniciar o desenvolvimento em J2ME. Vá até o menu Iniciar Programas J2ME Wireless Toolkit 2.2 KtoolBar. Este será o programa mais usado por você, e todos os outros que aparecem no menu podem ser acessados a partir deste. j2me_wireless_toolkit-2_2-windows.exe,
Para iniciarmos o uso da ferramenta, vamos criar um novo projeto de exemplo. Clique então no botão New Project, defina o nome do seu projeto e como se chamará a sua classe MIDlet, conforme 2.
Configurações básicas de uma aplicação Após termos criado um novo projeto, automaticamente o WTK nos abre a tela de Settings do projeto ( 3). Esta tela pode ser chamada posteriormente, a partir do botão Settings na tela principal (ver 1). A janela de configurações ( 3) é aberta com a opção JTWI no item Target Platform, que é o padrão Java para aplicativos de dispositivos móveis. Contudo, podemos customizar nosso projeto de acordo com o dispositivo para o qual iremos integrar e o que definimos que iremos precisar em nossa aplicação. Selecionando a opção Custom podemos escolher cada customização de Profile, Configuration ou API’s opcionais, como habilitar/desabilitar opções como: MMAPI (Mobile Media API) ou ainda qual versão do
Criando projetos no WTK Agora que já abrimos a nossa ferramenta KToolBar, vamos conhecê-la um pouco. A tela inicial ( 1) nos traz praticamente todas as funcionalidades básicas que precisamos, e que teremos nessa ferramenta. Temos as principais funcionalidades definidas em botões, sendo eles: New Project: cria um novo projeto dentro do WTK; Open Project: abre um projeto já existente no WTK; Settings: abre uma tela para diversas configurações; Build: compila o projeto que está aberto no WTK; Run: roda o projeto com o emulador
1. Tela principal do Wireless Toolkit.
2. Criação de um novo projeto no WTK.
WebMobile 15
wm02.indb 15
6/4/2005 22:19:43
MIDP iremos utilizar. Para saber mais sobre Profiles, Configurations e API’s opcionais, leia o artigo sobre J2ME publicado na primeira edição da Web Mobile. Esta tela nos permite fazer outras configurações como manipular comportamentos sobre o Push Registry, que serve para podermos definir se nossa aplicação será ativada quando determinado evento acontecer, como a chegada de um SMS. Na segunda aba (Required), conforme a 4, temos todos os campos que devem ser definidos pelo desenvolvedor - eles já vêm com alguns valores padrões. As informações de configurações serão lidas e mantidas nos arquivos .JAR e .JAD da aplicação. Nesta aba temos algumas informações que são interessantes de serem comentadas, como é o caso do campo que contém uma informação muitas vezes desprezada pelos desenvolvedores, que é o campo MIDlet-Vendor. Através do valor setado para este campo é que podemos reconhecer e compartilhar, por exemplo, RecordStores entre as aplicações, assim como o MIDlet-Name, que contém o nome com o qual sua aplicação será reconhecida no dispositivo. Os demais campos são auto-explicativos. Na aba MIDlets temos a descrição de cada MIDlet que estaremos disponibilizando em nosso pacote, e você será requisitado a selecionar uma delas quando pedir para abrir a aplicação, pois somente uma MIDlet pode estar ocupando a VM por vez. As outras abas contêm informações configuráveis que renderiam uma longa explanação, porém não o impedem de começar a desenvolver em J2ME. Quando um projeto é criado pelo WTK, ele automaticamente cria uma estrutura de diretórios dentro da pasta apps, que está dentro da pasta onde foi feita a instalação do WTK, conforme a 5. Os diretórios possuem funções específicas: Bin: conterá os arquivos .jad e .jar depois que empacotarmos nossa aplicação; Classes: usado pelo WTK para guardar as classes compiladas do projeto; Lib: conterá pacotes extras que desejarmos usar em nosso projeto; Res: imagens, sons, vídeos e outros arquivos que serão usados pela aplicação; Src: conterá todos os códigos java de sua aplicação; Tmpclasses: diretório usado pela aplicação durante o runtime; Tmpsrc: diretório usado pela aplicação durante o runtime.
facilitar o desenvolvimento e para que consigamos emular de forma mais real o comportamento da aplicação em seu celular, trazendo várias opções que devem ser usadas de acordo com a aplicação a ser desenvolvida. A saber: Clean Database: limpa toda a base de RecordStores da aplicação carregada. Memory Monitor: diz respeito à monitoração de memória, traz gráficos de utilização em tempo real, permitindo que você encontre “gargalos” e problemas em sua aplicação. Network Monitor: nos traz muitas informações sobre o trafego de dados que estamos tendo com nossa aplicação, podendo ainda filtrar tipos de mensagens trafegadas, como uma espécie de sniffer. Profiler: faz um rastreamento de quais são os métodos
3. Tela de Settings do projeto.
Ferramentas do WTK Como dito anteriormente, o KToolbar nos dá acesso a todas as ferramentas disponibilizadas pela WTK. Outra importante ferramenta e muito usual pode ser acessada através do menu Iniciar Programas J2ME Wireless Toolkit 2.2 Utilities ou no menu Files Utilities da tela principal do programa J2ME Wireless Toolkit (Ktoolbar). Esta ferramenta ( 6) tem como principal objetivo nos proporcionar configurações extras para
4. Configurações requeridas da aplicação.
16 2º Edição
wm02.indb 16
6/4/2005 22:19:47
Java
Bluetooth/OBEX: configurações relativas à transmissão de dados via Bluetooth ou IrDA (Infrared).
Compilando e executando projetos
5. Estrutura de diretórios de uma aplicação.
Para que possamos executar um projeto no WTK, precisamos primeiramente abrir um projeto. Vá então até o botão Open Project na tela principal do WTK ( 8) e abra um projeto já existente nele, que em nosso caso foi o UIDemo. Depois de carregado o projeto, devemos compilá-lo, bastando para isso clicarmos no botão Build da tela principal do WTK. Feito isto, o WTK deverá nos retornar uma saída igual a esta:
usados durante a aplicação, quanto tempo é gasto para executar cada um e quantas vezes foram chamados, dentre muitas outras informações sobre a execução de sua aplicação. WMA: serve para que possamos testar nossas aplicações que usam o Wireless Messaging API, podendo simular mensagens SMS, assim como MMS. Security: as duas opções dentro desse subgrupo são usadas para que possamos assegurar permissões, assinaturas de midlets e ainda os certificados digitais. Stub Tools: usado para que se possam gerar códigos para acesso a Web Services a partir de aplicações J2ME. A maioria desses utilitários vistos deve ser habilitada. Para isso, basta acessar o menu Iniciar Programas J2ME Wireless Toolkit 2.2 Preferences ou no menu Edit Preferences da tela principal do aplicativo J2ME Wireless Toolkit (Ktoolbar). A partir deste menu, temos uma nova tela com vários outros acessórios, que podemos ver na 7. Habilitamos na aba Monitor o que queremos usar nas aplicações. A tela da 7 nos traz outras ferramentas, nas diversas abas, que valem a pena conhecermos e utilizarmos durante o desenvolvimento de nossas aplicações. Vamos conhecer o que podemos obter de cada aba desta tela: Network Configuration: nesta tela podemos setar algumas configurações com relação à conectividade, como qual versão do protocolo HTTP utilizar; Performance: nesta aba temos configurações de velocidade de processamento, latência para renderização de imagens, velocidade de conexão, dentre outras; Monitor: pode-se definir quais as opções a serem monitoradas e rastreadas; Storage: podemos definir o local onde todos os RecordStores serão gravados, assim como o tamanho máximo de memória e tamanho do Heap; WMA: configurações para o uso da Messaging API; Security: é possível setar o nível de segurança de nossa aplicação, que é informado para a VM do aparelho antes da instalação;
6. Menu de utilidades.
7. Tela de Preferences na aba Monitor.
WebMobile 17
wm02.indb 17
6/4/2005 22:19:50
Project “UIDemo” loaded Project settings saved Building “UIDemo” Build complete
Agora basta apenas selecionar o tipo de emulador que ele irá utilizar na combo Device, que em nosso caso foi o Default Color Phone, e clicarmos em Run. Pronto, temos nossa aplicação rodando em um emulador, conforme 9.
3. Na próxima tela clique em New Remote Site. Então coloque o caminho conforme a 10. Feito isto, selecione o site que acabou de criar e clique em Next. 4. Na próxima tela ( 11) você receberá uma lista de itens a instalar. Selecione os itens que você deseja instalar (no nosso caso apenas EclipseME). 5. Agora apenas continue seguindo as instruções de instalação e finalize-a;
Distribuindo aplicações O Wireless Toolkit ainda nos traz uma ferramenta muito útil para geração dos pacotes para a distribuição de nossa aplicação. Para que possamos gerar o pacote de nossa aplicação, precisamos abrir nosso projeto, e ir ao menu Edit Create Package. O WTK compilará nossas classes novamente e criará os arquivos .jad e .jar no output default da aplicação ($wtkhome/apps/SuaAplicacao/bin). Ele ainda verificará o diretório res e o diretório lib e empacotará tudo o que for necessário para a aplicação. Ainda possuímos a opção de gerarmos nossos pacotes obfuscados, dificultando assim a decompilação de nossa aplicação. Podemos associar qualquer obfuscador para utilizarmos em conjunto com o Wireless Toolkit. Para isso, precisamos baixar um obfuscador. O default do WTK é o Proguard. Para instalarmos ele siga os seguintes passos: 1. Faça o download da última versão do Proguard em http://proguard.sourceforge.net; 2. Extraia o arquivo /lib/proguard.jar para o diretório $wtkhome/bin. Como o Proguard é o obfuscador padrão do WTK, este já vem pré-configurado para funcionar corretamente. Contudo, caso deseje utilizar outros, verifique a documentação do WTK e da ferramenta para saber como configurar corretamente. Em alguns casos pode ser preciso gerar um arquivo de script para poder controlar a forma que seu obfuscador irá funcionar. Nestes casos procure na documentação da própria ferramenta para saber como a utilizar melhor.
8. Abrindo um projeto no Wireless Toolkit.
Integração do WTK com Eclipse (plug-in EclipseME) EclipseME é um plug-in OpenSource desenvolvido para facilitar o desenvolvimento de aplicativos em J2ME dentro da IDE Eclipse. A última versão deste plug-in (0.75) é compatível com o Eclipse 3.0. Ainda não existe uma versão dele para o Eclipse 3.1 que ainda está em desenvolvimento. Este artigo parte do princípio que o leitor já possui o Eclipse instalado e configurado tanto no Linux como no Windows. Para a instalação deste plug-in, siga os seguintes procedimentos: 1. Abra o Eclipse e vá até o menu Help Software Updates Find and Install; 2. Será mostrada uma tela com duas opções. Selecione a opção Search for New Features to install;
9. Aplicação UIDemo sendo executada no Emulador.
10. URL para instalação do EclipseME.
18 2º Edição
wm02.indb 18
6/4/2005 22:19:52
Java
6. Depois de finalizada a instalação e de ter reiniciado o Eclipse, vá até o menu Window Preferences e verifique se existe uma entrada na árvore para J2ME, conforme a 12. 7. Agora precisamos configurar onde encontrar o nosso WTK. Para isso, clique em Plataform Components na árvore onde está localizado o J2ME e depois na opção Wireless Toolkits. Caso o próprio Eclipse já não tenha reconhecido seu WTK, clique então com o botão direito em Wireless Toolkits e em Add Wireless Toolkit. Procure então pela instalação de seu WTK e clique em Finish. 8. Feita essa configuração, estamos prontos para criar um novo projeto de J2ME. Para isso, vá até o menu File New Project, do Eclipse, e então escolha a opção J2ME J2ME Midlet Suíte, conforme 13. 9. Defina um nome para o novo projeto. 10. Na próxima tela, podemos escolher qual será a plataforma de desenvolvimento. Para o exemplo, optaremos pela MIDP 1.0 que é a mais comum hoje. Feito isso, clique em Finish. 11. O último painel ( 14) nos dá a oportunidade de ajustar as configurações do projeto, outros projetos e bibliotecas, dentre outras. São configurações padrão do Eclipse. Se o seu projeto precisar de bibliotecas externas, adicione o arquivo .JAR correspondente na guia “Libraries”. O plug-in EclipseME irá manusear automaticamente seus arquivos extras com seus arquivos de classe compilados. 12. Concluído os passos acima, a aparência do projeto no eclipse deve parecer como o da 15. 13. Depois de criar um novo projeto MIDlet Suite Project, você pode querer alterar algumas propriedades do projeto. As propriedades do MIDlet Suite são controlados pelo Java Application Descriptor (JAD). Para acessar o editor
11. Lista de itens contidos no site EclipseME.
12. Preferências básicas de J2ME.
13. Criando um novo projeto J2ME no Eclipse.
14. Painel utilizado para manusear o projeto.
WebMobile 19
wm02.indb 19
6/4/2005 22:19:54
JAD, clique duas vezes sobre o arquivo WebMobile.jad, conforme a 16.
Conclusão Conforme pudemos ver, criar uma aplicação para dispositivos móveis não é nenhum bicho de sete cabeças, existem detalhes que podem passar despercebidos, mas uma vez descoberto o caminho das pedras não existe mais segredo. Essas ferramentas apresentadas no artigo trazem um leque enorme de potencialidade no desenvolvimento, facilitando e agilizando a vida do
15. Aparência do projeto após conclusão dos passos para criação do projeto.
desenvolvedor de aplicações deste ramo. Porém, nunca confie cegamente no que emuladores lhes dizem, prime sempre por testes mais exaustivos em aparelhos reais, estes sim lhe dirão se sua aplicação irá realmente funcionar.
Juliano D. Carniel (juliano@portaljava.com) Trabalha como Consultor da plataforma Java, já passou por vários projetos de J2ME e SuperWaba, para soluções coorporativas, de mobilidade e integração de sistemas com J2EE. Atualmente presta Consultoria em J2EE na Renault do Brasil. Autor de diversos artigos e tutoriais publicados em diversos meios, como no PortalJava , do qual é um dos Administradores, e também palestrante em eventos de Java.
Daniel Kühl (daniel@fag.edu.br) é administrador de redes com Solaris, Linux, NetBSD, OpenBSD e Windows 2000 com experiência de mais de 5 anos. Desenvolvedor de sistemas em Delphi a 4 anos. Trabalha atualmente na Faculdade Assis Gurgacz em Cascavel/PR onde está implementando projetos em Java para vestibular e controle de RH.
Home do J2ME http://java.sun.com/j2me Maiores informações para instalação do plug-in EclipseME. http://eclipseme.org/docs/installation.html Contém vários materiais para J2ME e afins na seção de artigos e tutoriais. www.portaljava.com.br
Faça o download no site: 16. Editor JAD com suas opções. Observe as guias na parte de baixo, são as propriedades do projeto JAD.
www.portalwebmobile.com.br/revista/ed2
20 2º Edição
wm02.indb 20
6/4/2005 22:20:00
PDA’s
Acesso a dados no Pocket? por Renato Haddad
Leitura Obrigatória Web Mobile 1 Construindo sua primeira aplicação para POCKET PC com .NET.
C
omo em um dispositivo tão pequeno pode ter uma quantidade de dados expressa na forma de banco de dados relacional? Afinal, existem diversas maneiras de armazenamento de dados, seja em arquivos textos, XML, banco de dados etc. Neste tutorial mostrarei como acessar dados através de um Pocket PC, abordando o uso do banco de dados diretamente no Pocket.
Cenário O cenário de um ambiente conectado é muito importante para definir o escopo de uma aplicação móvel. O acesso à rede, dados, tipos de usuários, velocidade, tipos de conexões etc. são peças fundamentais aqui. As vantagens e desvantagens dependem da arquitetura da solução. Veja alguns pontos a serem considerados em uma arquitetura móvel: O banco de dados deverá estar sempre atualizado no Pocket? Se o usuário precisar ter todas as informações atualizadas em tempo real, por exemplo, a quantidade de estoque ou o preço de um produto, então, no momento adequado é preciso solicitar ao servidor da empresa o devido dado. Para isso, é preciso que haja um meio de comunicação via http, seja Wi-Fi ou cabo. Não importa o meio, de qualquer forma a sua aplicação instalada no Pocket terá que requisitar o dado no banco de dados da empresa naquele instante. Por outro lado, se não houver necessidade da informação atualizada, é indicado armazenar os dados no Pocket PC através de arquivos XML ou SQL Server CE, permitindo que a aplicação trabalhe off-line. Assim, em determinado momento, o usuário deverá sincronizar as alterações com o servidor, através de Replication ou Synchronization; Existe um meio de comunicação? Esse fator é primordial para que a aplicação funcione. Se você precisar atualizar os dados imediatamente e não houver um meio de comunicação (leia-se rede), então, ficará na mão literalmente. Portanto, antes de montar a aplicação, certifique-se em qual ambiente a aplicação irá rodar. Saiba que as redes sem fio (Wi-Fi – Wireless Fidelity) estão crescendo muito em todo o mundo a um custo muito baixo. Isso significa dizer que teremos em breve acesso à rede a qualquer hora e lugar, permitindo construir aplicações constantemente conectadas. Outra alternativa é usar o telefone WebMobile 21
wm02.indb 21
6/4/2005 22:20:08
celular (qualquer um) como modem, provendo sinal de acesso, seja através de cabo celular/pocket ou via Bluetooth. Outra solução seria o uso de um PhoneEdition, que é um dispositivo com funcionalidades do Pocket PC e celular ao mesmo tempo. Cabe ressaltar que as redes Wi-Fi estão associadas a um Access Point (AP), que emite um sinal com distância de até 150 metros, dependendo do fabricante. Veja no link www.microsoft. com/brasil/msdn/tecnologias/movel/mobilidade_wifi.aspx mais informações sobre Wi-Fi. O mais esperado neste ano de 2005 é que as redes Wi-Max cheguem ao mercado em breve, pois acredite, o sinal chegará a uma distância de 75 km; Recursos de hardware: um aspecto a ser analisado é o custo dos equipamentos e recursos de cada dispositivo. A cada dia os dispositivos têm novos acessórios, seja cartão de memória, Wi-Fi, Bluetooth, leitor ótico, comunicação com impressoras, enfim, isso implica diretamente no investimento da empresa; Acesso a Web Services: se a aplicação precisar consumir Web Services, sempre deverá estar conectada à rede. Existem situações em que isso se torna imprescindível, pois certos dados só podem ser acessados através de Web Services. Por exemplo, checar o crédito de uma empresa/consumidor no Serasa, consultar dados externos à empresa, montar um fluxo de informações com diversas empresas para integrar soluções, enfim, tem que ter acesso à rede; Outro aspecto a ser considerado em relação ao acesso à rede da empresa é que através do Pocket PC você pode acessar o banco de dados SQL Server diretamente no servidor. No final do tutorial, existem mais comentários a respeito disso. Faremos a partir de agora uma aplicação que criará e manipulará um banco de dados no Pocket. Na parte I deste tutorial (edição 1 da Web Mobile) foi criada uma solução chamada tutorialPocket e é exatamente essa que usaremos neste projeto, portanto, abra-a.
Banco de dados Como criaremos um banco de dados no Pocket, o namespace responsável é o System.Data.SqlServerCE, ou seja, é preciso referenciar essa biblioteca. O SQL Server CE é um banco de dados similar ao SQL Server, resguardadas as devidas limitações de um dispositivo móvel. Por exemplo, não existem Stored Procedure e Triggers, mas em compensação temos sintaxes T-SQL que você já conhece (select, insert, delete e update), chaves primárias, consultas, agregação (sum, count, max, avg e min), além da DLL ser de apenas 2 MB. Acesse o menu Project|Add Reference e inclua as referências no projeto conforme mostrado na 4. O System.Data.SqlServerCE contém os métodos necessários para criar o banco de dados e a tabela. O System.Data.Common é fundamental para usar um DataAdapter, que utilizaremos para exibir os dados no ListBox.
1. Criando um novo formulário Windows Form
Formulário Adicione um novo formulário (Add|Add Windows Form) chamado BancoDados ( 1). Selecione o menu View|Toolbox para exibir a caixa de ferramentas (ou pressione Ctrl + Alt + X). Como esse formulário conterá diversos controles, a melhor forma de organizá-los é através de um TabControl. Portanto, arraste esse controle para o formulário e redimensione sua altura. Pressione F4 para exibir a janela de propriedades e em TabPages (Collection) clique no botão construtor [...]. Será exibida uma janela para que você adicione as TabPages. Nela inclua três Pages: Banco, Incluir e Excluir ( 2). Digite cada texto na propriedade Text e para adicionar um novo item, clique no botão Add. Na tabPage Banco, inclua os controles com as respectivas propriedades, conforme 1e 3.
2. Adicionando Pages no TabControl
22 2º Edição
wm02.indb 22
6/4/2005 22:20:15
PDA’s
1 Button 1 Button 1 Listbox
Name: btnBanco Text: Cria banco dados/tabela Name: btnPreenche Text: Preenche tabela Name: lstDados
1. Componentes do formulário BancoDados
3. Formulário para criação do banco de dados no Pocket
incluída no System.Text.StringBuilder, pois o uso dessa classe para manipular strings (principalmente concatenar) ocorre de forma muito eficaz, mais rápida que qualquer outro meio de concatenar variáveis. O ExecuteNonQuery é que efetiva a criação da tabela no banco de dados. Se ocorrer algum erro, será tratado no Catch. O botão Preenche Tabela incluirá alguns registros na tabela criada anteriormente. Dê um duplo clique no btnPreenche e digite o código da 2. Para incluir dados na tabela, criei uma rotina chamada AddDados ( 3), que recebe três parâmetros para montar a instrução SQL e a respectiva conexão. Em seguida, ela efetiva os dados na tabela e retorna à rotina que a chamou. Isso permite otimizar o código para usá-lo em outras situações em que houver a necessidade de incluir dados na tabela. Note novamente o uso do StringBuilder. Uma vez incluídos os dados na tabela, é preciso listá-los em algum controle. Como temos o ListBox lstDados, iremos utilizá-lo para mostrar todos os assinantes existentes na tabela. É importante ressaltar que todos esses dados estão no banco de dados do Pocket PC, o SQL Server CE, completamente desconectados de outra fonte de dados, permitindo assim trabalhar off-line. Como iremos montar um DataSet, é preciso incluir o seguinte namespace na lista de using: using System.Data;
4. Adicionando uma referência
Dê um duplo clique no botão btnBanco e digite o código da 1 para criar o banco de dados e a tabela. Como usaremos o SQL Server CE, é preciso referenciar o respectivo namespace na lista de using no início do projeto. Inclua também System.IO, pois manipularemos um arquivo no Pocket PC. Note que nesse código é definida a variável conexao contendo todo o Data Source do banco de dados a ser criado. Em seguida, é verificado se o arquivo webmobile.sdf existe na pasta My Documents, por isso o uso do namespace System.IO. Caso não exista, ele cria automaticamente. Já o é usado para invocar a classe SqlCeEngine e o método CreateDatabase para criar apenas o banco de dados. O uso do Dispose se faz necessário para liberar o objeto da memória. Em seguida é feita a conexão com o banco de dados definido na variável conexão e é declarada uma instrução SQL para criar a tabela Assinantes contendo dois campos (IDAssinante e Assinante). Note que a instrução SQL está
Em seguida, digite o código da rotina ListaDados, conforme 4. Basicamente, é feito um Select na tabela Assinantes do SQL Server CE, montado um DataAdapter e um DataSet e, ao final, todos os assinantes serão exibidos no ListBox. Note que no .NET Compact Framework, o uso de DataSet (System.Data) e DataAdapter (System.Data.Common) é permitido, desde que você referencie as devidas bibliotecas. Isso é muito importante, pois como um DataSet pode conter diversas tabelas na memória, o programador poderá trabalhar com várias tabelas desconectadas e vinculadas a diversos controles, por exemplo, DataGrid, ListBox etc. Gostaria de pedir sua atenção para o nome dos campos declarados nas propriedades DisplayMember e ValueMember, eles são case sensitive. Salve o projeto (Ctrl + S). Na parte I deste tutorial foi desenvolvido um formulário de menu contendo um login com as opções. Portanto, inclua o formulário de banco de dados no menu ( 5), digite o código abaixo para chamar o respectivo formulário e teste a aplicação.
private void menuItem5_Click(object sender, System.EventArgs e) { BancoDados frm = new BancoDados(); frm.ShowDialog(); }
WebMobile 23
wm02.indb 23
6/4/2005 22:20:24
1. Código para criação do banco de dados e tabela. using System.Data.SqlServerCe; using System.IO;
private string conexao = @”Data Source=\My Documents\webmobile.sdf”;
private void btnBanco_Click(object sender, System.EventArgs e) { try { //verifica se o arquivo existe if (! File.Exists(@”\My Documents\webmobile.sdf”)) { // cria o database SqlCeEngine eng = new SqlCeEngine(conexao); eng.CreateDatabase(); // libera o objeto da memória eng.Dispose();
// cria a conexão SqlCeConnection conn = new SqlCeConnection(conexao); // abre a conexão conn.Open();
// cria a tabela System.Text.StringBuilder sql = new System.Text. StringBuilder(); sql.Append(“CREATE TABLE Assinantes(“); sql.Append(“IDAssinante int Primary Key NOT NULL, “); sql.Append(“assinante nvarchar(40))”);
5. Chamando o formulário a partir do menu principal
No formulário Banco Dados, configure a propriedade MinimizeBox = False.
Execute a aplicação, faça o login correto, selecione a opção Banco Dados no menu e clique no botão Cria banco dados/tabela ( 6). Clique no botão Preenche Dados para incluir alguns registros na tabela e mostrá-los no ListBox ( 7). Com isso, já temos tudo o que é necessário: o banco de dados, a tabela e os dados.
// define o command SqlCeCommand cmd = new SqlCeCommand(sql.ToString(), conn); // efetiva a execução cmd.ExecuteNonQuery(); // fecha a conexão conn.Close(); // avisa o usuário MessageBox.Show(“Banco de dados criado”,”WebMobile”); } } // trata o erro, se houver catch (SqlCeException ex) { MessageBox.Show(ex.Message); } catch (Exception ex) { MessageBox.Show(ex.Message); } }
Cadastro Vamos construir o código para cadastrar assinantes no banco de dados. Na Page Incluir adicione os controles com as respectivas propriedades, conforme a 2e 8. Digite o código do btnCadastar conforme mostrado na 5, que adicionará na tabela do banco de dados o nome do assinante digitado no TextBox. Neste código foi utilizada a função Max do SQL para identificar qual é o maior código (IDAssinante) cadastrado, pois como o campo é chave primária, é preciso identificar o maior e adicionar mais um. Com isso, o usuário jamais digitará qualquer ID. A interface com o usuário é muito importante e a única forma que ele tem de escrever o nome do assinante é através do teclado (InputPanel). Portanto, para exibir ou ocultar o teclado quando o TextBox estiver com
24 2º Edição
wm02.indb 24
6/4/2005 22:20:28
PDA’s
AddDados(5, “Pato Donald”,conn);
2. Código para incluir dados na tabela.
// fecha a conexão private void btnPreenche_Click(object sender, System.EventArgs e)
conn.Close();
{
// invoca a rotina para mostrar os dados ListaDados();
try }
{
// trata o erro, se houver
// define a conexão SqlCeConnection conn = new SqlCeConnection(conexao);
catch (SqlCeException ex)
// abre a conexão
{ MessageBox.Show(ex.Message);
conn.Open(); }
// invoca a rotina AddDados passando os 3
catch (Exception ex)
parâmetros
{
AddDados(1, “Mickey”, conn);
MessageBox.Show(ex.Message);
AddDados(2, “Pluto”, conn); }
AddDados(3, “Pateta”, conn); AddDados(4, “Minie”, conn);
}
sql.Append(“,’”);
3. Inclusão de dados.
sql.Append(assinante); private void AddDados(int cod, string assinante,
sql.Append(“’)”);
SqlCeConnection conn)
// monta o Command SqlCeCommand cmd = new SqlCeCommand(
{
sql.ToString(), conn);
try
// efetiva o Command, ou seja, inclui o
{
registro na tabela
// define a instrução SQL oriunda dos
cmd.ExecuteNonQuery();
parâmetros recebidos }
System.Text.StringBuilder sql = new
catch (Exception)
System.Text.StringBuilder();
{
sql.Append(“INSERT INTO Assinantes
throw;
(IDAssinante, assinante) “); }
sql.Append(“VALUES (“); sql.Append(cod);
}
// preenche o Adapter no Dataset com a
4. Listando os dados no ListBox.
// tabela assinantes private void ListaDados()
da.Fill(ds, “assinantes”);
{
// define o campo que será exibido try
lstDados.DisplayMember = “assinante”;
{
// define o campo que será armazenado // define a conexão
lstDados.ValueMember = “IDAssinante”;
SqlCeConnection conn =
// define a fonte de dados lstDados.DataSource =
new SqlCeConnection(conexao);
ds.Tables[“assinantes”].DefaultView;
// abre a conexão
// fecha a conexão
conn.Open();
conn.Close();
// seleciona todos os dados da tabela }
string sql = “Select * FROM Assinantes
catch (Exception)
ORDER BY Assinante”;
{
// define o DataAdapter
throw;
SqlCeDataAdapter da = }
new SqlCeDataAdapter(sql,conn); // define o DataSet
}
DataSet ds = new DataSet();
WebMobile 25
wm02.indb 25
6/4/2005 22:20:30
6. Criando o banco de dados no Pocket
o foco, adicione os seguintes eventos ao controle txtAssinante (para maiores detalhes sobre o evento, consulte a primeira parte deste tutorial).
negrito, conforme a 6. Basicamente, usará o mesmo DataTable criado no DataSet (chamado Assinante) que preenche os dois ListBoxes. Para deixar o projeto funcional, inclua o nome da rotina ListaDados como mostrado no código a seguir. Tudo o que você inserir nessa sessão será executado apenas na primeira vez em que o formulário for montado, portanto, assim que você abrir o formulário BancoDados, os dois ListBoxes serão preenchidos. public BancoDados() { // // Required for Windows Form Designer support //
private void txtAssinante_GotFocus(
InitializeComponent();
object sender, System.EventArgs e)
ListaDados();
{ inputPanel1.Enabled = true;
}
}
private void txtAssinante_LostFocus( object sender, System.EventArgs e) { inputPanel1.Enabled = false; }
Salve o projeto e execute-o no Pocket para testar. Digite o nome do assinante e verifique na lista se ele foi cadastrado ( 9).
Exclusão Já que temos todos os assinantes cadastrados no banco de dados, vamos criar uma forma de excluir dados. Na Page Excluir, adicione os controles com as respectivas propriedades, conforme 3e 10. O funcionamento será da seguinte forma: quando o formulário for carregado pela primeira vez, irá carregar todos os ListBoxes existentes (lstDados e lstExcluirAssinantes) com os dados dos assinantes. Tanto na inclusão quanto na exclusão de qualquer registro, esses dois ListBoxes deverão ser carregados, a fim de exibir os dados atualizados. No momento em que o usuário selecionar um assinante na lstExcluirAssinantes e pressionar o botão de Excluir, ele será excluído da tabela. O primeiro passo é incluir o código para listar os assinantes na lstExcluirAssinantes. Como a rotina ListaDados já existe, então, adicione o seguinte bloco de código em 7. Dados da tabela exibidos no ListBox
Uma vez listados todos os assinantes na lstExcluirAssinantes, para excluir um registro é preciso selecioná-lo na lista e clicar no botão Excluir. Portanto, dê um duplo clique no botão btnExcluir e digite o código da 7. É importante ressaltar que, apesar do nome do assinante ser exibido no ListBox, quando você seleciona um item, é capturado o IDAssinante, que é a propriedade ValueMember definida quando o ListBox foi preenchido. Portanto, é justamente esse ID que será usado na cláusula where da instrução SQL. Salve o projeto e execute no Pocket. Selecione um nome na lista e clique no botão Excluir para efetivar a exclusão na tabela e atualizar os ListBoxes. Veja a seqüência na 11.
SQL Server CE O SQL Server CE provê uma série de recursos que o torna um excelente meio de armazenamento de dados. Sua maior vantagem é oferecer uma forma de armazenar uma grande quantidade de dados em um pequeno dispositivo, além é claro, de suportar sincronização e replicação de dados com o SQL Server no servidor. Veja alguns pontos que se destacam: Roda o banco de dados direto no device: qualquer dispositivo que tenha o .NET Compact Framework com as devidas bibliotecas para o SQL Server CE pode armazenar as informações 1 Label
Text: Incluir Assinante (Formatado conforme a figura)
1 Label
Text: Assinante
1 TextBox 1 Button
Name: txtAssinante Text: em branco Name: btnCadastrar Text: Cadastrar
1 MainMenu 1 InputPanel 2. Criando uma tela de cadastro
26 2º Edição
wm02.indb 26
6/4/2005 22:20:33
PDA’s
1 Label
Text: Excluir Assinante (Formatado conforme a figura)
1 ListBox
Name: lstExcluirAssinantes
1 Button
Name: btnExcluir Text: Excluir Assinante
3. Componentes do formulário para exclusão de registros
8. Incluindo um assinante
direto no dispositivo. Cabe ressaltar que é preciso considerar a quantidade de memória existente no dispositivo, mas nada o impede de armazenar o banco de dados em cartões de memória, por exemplo, se você usar um cartão de 1GB terá uma enorme quantidade de informações; Não requer conexão com servidor: o SQL Server CE roda completamente independente de qualquer conexão com servidor, oferecendo ao usuário uma forma de trabalhar em um ambiente desconectado. Com isso, o usuário poderá coletar diversas informações no campo, armazená-las no banco de dados e, dependendo da aplicação, sincronizar com o SQL Server no servidor, se preciso; Suporta transação e índices; Fácil sincronização com servidor: existem classes para prover esse tipo de serviço; Encriptação de dados 128-bit; Menor que 2MB; Insert/Update/Delete/Select: suporta instruções SQL já conhecidas entre os desenvolvedores; Inner e outer joins: recurso suportado no SQL Server CE;
10. Formulário para exclusão de registros
9. Registro incluído no banco de dados
// invoca a rotina
5. Cadastrando um assinante.
//AddDados passando os 3 //parâmetros
private void btnCadastrar_Click(object sender, System.EventArgs e)
AddDados(cod + 1, txtAssinante.
{
Text.Trim(), conn);
// valida dados
// fecha a conexão
if (txtAssinante.Text == string.Empty)
conn.Close();
{
// avisa o usuário
MessageBox.Show(“Por favor, digite o nome
MessageBox.Show(“Assinante
do assinante”,”WebMobile”);
cadastrado com sucesso”, “WebMobile”);
txtAssinante.Focus(); }
// limpa o textbox
else
txtAssinante.Text = string.Empty;
{ try
// invoca a rotina para mostrar os dados
{
ListaDados();
// define a conexão }
SqlCeConnection conn =
// trata o erro, se houver
new SqlCeConnection(conexao); // abre a conexão
catch (SqlCeException ex)
conn.Open();
{ MessageBox.Show(ex.Message);
// acha o maior código cadastrado }
string sql = “Select
catch (Exception ex)
Max(IDAssinante) FROM Assinantes”;
{
SqlCeCommand cmd = new
MessageBox.Show(ex.Message);
SqlCeCommand(sql, conn); }
int cod = }
Convert.ToInt32( cmd.ExecuteScalar()); }
WebMobile 27
wm02.indb 27
6/4/2005 22:20:37
6. Exibindo assinantes no ListBox.
// define o campo que será armazenado lstDados.ValueMember = “IDAssinante”;
private void ListaDados()
// define a fonte de dados
{
lstDados.DataSource = try
ds.Tables[“assinantes”].DefaultView;
{ // define a conexão
// atualiza o listbox de exclusão de assinantes
SqlCeConnection conn = new SqlCeConnection(conexao);
lstExcluirAssinantes.DisplayMember =
// abre a conexão
“assinante”;
conn.Open();
lstExcluirAssinantes.ValueMember =
// seleciona todos os dados da tabela
“IDAssinante”;
string sql =
lstExcluirAssinantes.DataSource =
“Select * FROM Assinantes ORDER BY Assinante”;
ds.Tables[“assinantes”].DefaultView;
// define o DataAdapter
// fecha a conexão
SqlCeDataAdapter da = new SqlCeDataAdapter(sql,conn);
conn.Close();
// define o DataSet
}
DataSet ds = new DataSet();
catch (Exception)
// preenche o Adapter no Dataset com
{
// a tabela assinantes
throw;
da.Fill(ds, “assinantes”); // define o campo que será exibido
} }
lstDados.DisplayMember = “assinante”;
// define e executa o command
7. Código para excluir dados.
SqlCeCommand cmd = new SqlCeCommand(sql, conn);
private void btnExcluir_Click(object sender, System.EventArgs e)
cmd.ExecuteNonQuery();
{ // verifica se existe um item selecionado
// fecha a conexão
if (lstExcluirAssinantes.SelectedIndex >= 0)
conn.Close(); // avisa o usuário
{
MessageBox.Show(“Assinante
try
excluído com sucesso”,”WebMobile”);
{
// atualiza os listboxes
// captura o IDAssinante
ListaDados();
//selecionado no listbox string codExclusao =
}
lstExcluirAssinantes.
// trata o erro, se houver
SelectedValue.ToString();
catch (SqlCeException ex)
// monta a instrução SQL
{ MessageBox.Show(ex.Message);
string sql = “DELETE FROM }
Assinantes Where
catch (Exception ex)
IDAssinante=” + codExclusao;
{
// define e abre a conexão
MessageBox.Show(ex.Message);
SqlCeConnection conn = new }
SqlCeConnection(conexao); }
conn.Open(); }
28 2º Edição
wm02.indb 28
6/4/2005 22:20:38
PDA’s
11. Teste de exclusão de assinante
5. Caso queira visualizar as tabelas de objetos do sistema, selecione o item Tables e clique no primeiro ícone ( 14). 6. Caso queira adicionar uma nova tabela e definir a estrutura das colunas, selecione o item Tables e clique no segundo ícone ( 15). 7. O Query Analyzer permite executar qualquer instrução SQL. Para isso, clique no ícone SQL, onde será exibida uma janela contendo números de 1 a 10 e um grande TextBox para você digitar a instrução. Os números são maneiras de você armazenar até 10 instruções SQL na memória, a fim de economizar digitação. Como o banco de dados Assinantes está aberto, digite uma instrução Select para exibir todos os registros da tabela assinantes ( 16). Para executar, clique no primeiro ícone
12. Executando o Query Analizer
Funções aggregates: suporta funções do tipo Sum, Max, Min, Avg e Count, muito utilizadas em diversos tipos de aplicações; Provider SQL Server CE ADO.NET: similar ADO.NET providers, contendo as classes de DataSet, DataReader, DataTable entre outras; Classes: SqlCeEngine / SqlCeConnection / SqlCeCommand / SqlCeDataReader / Commands / ExecuteScalar / ExecuteReader / ExecuteNonQuery.
13. Query Analizer exibindo informações do banco de dados
O SQL Server CE não vem instalado no emulador e nos Pocket, no entanto, quando você instalar o projeto pela primeira vez, o SQL Server CE é instalado automaticamente. O SQL Server CE é gratuito e pode ser instalado quantas vezes quiser em diversos dispositivos.
Query analyzer Criamos o arquivo WebMobile.sdf contendo a tabela Assinantes. Veremos agora, através do Query Analyzer do Pocket PC, como visualizar os dados. Siga os seguintes passos para abrir o banco de dados ( 12): 1. Selecione o menu Start / Programs; 2. Abra o File Explorer; 3. Selecione a pasta My Device / My Documents; 4. Note que o arquivo webmobile.sdf consta na lista. Clique neste arquivo para abrir a janela do Query Analyzer ( 13). Expanda as ramificações para visualizar as tabelas (Assinantes), as colunas com os respectivos nomes, tipos e tamanhos, e os índices, constando a chave primária. Qualquer semelhança com o Query Analyzer do SQL Server é verdadeira;
14. Visualizando tabelas e colunas no Query Analizer
15. Criando uma tabela no Query Analizer
WebMobile 29
wm02.indb 29
6/4/2005 22:20:45
16. Gravando instruções SQL
(seta verde) e note que o retorno é exibido na tela. Para visualizar os dados retornados, clique no ícone Grid. 8. Caso queira armazenar algumas instruções SQL, clique no ícone SQL, em seguida no último ícone (número 1|2+) e, para cada número digite a respectiva instrução SQL ( 17). Para executar uma determinada instrução, basta clicar no respectivo número para aparecer o comando a ser processado.
17. Armazenando múltiplas instruções.
Página sobre Celulares da Microsoft www.microsoft.com/windowsmobile
Conclusão Neste tutorial você aprendeu a acessar um banco de dados no Pocket PC, desde a criação até a manipulação dos dados diretamente no SQL Server CE, permitindo trabalhar com uma aplicação desconectada. Caso necessite sincronizar com o SQL Server no servidor, pesquise sobre sincronização de dados no SQL Server CE diretamente no site msdn.microsoft.com/library, pois existem vários artigos tratando do assunto. Outra dica importante: o Pocket PC permite que se faça acesso direto ao banco de dados SQL Server dentro de uma rede. Com isto, você pode enxergar e manipular os dados diretamente no servidor, tornando a aplicação o mais on-line possível, dispensando o uso do SQL Server CE. Cabe ressaltar que isso é possível desde que haja uma conexão à rede e ao SQL Server e que esse acesso seja permitido. Veja mais detalhes em www.microsoft.com/ brasil/msdn/Tecnologias/movel/WinMobileSQLServer.mspx Bons estudos e lembre-se: No Stress, think .NET!!!
Renato Haddad (rehaddad@msn.com) é Microsoft Most Valuable Professional .NET Mobile Devices, editor da revista MSDN Magazine Brasil, ministra treinamentos e palestras sobre .NETe autor de diversos livros e treinamentos em CD multimídia de ASP.NET, Visual Studio .NET 2003 e Aplicações Móveis para celulares e Pocket PC, tanto no Brasil como em outros países da América Latina.
Faça o download no site: www.portalwebmobile.com.br/revista/ed2
30 2º Edição
wm02.indb 30
6/4/2005 22:20:54
Tutorial
ASP.NET
Primeiros passos Crie um cadastro de usuários usando ADO.NET
por Guinther Pauli
N
este artigo veremos como criar, passo a passo, um cadastro de usuários bastante simples, onde destacaremos várias técnicas de desenvolvimento com ASP.NET. Ao final você estará apto a criar suas próprias aplicações de banco de dados para Web, robustas, escaláveis e com produtividade máxima. Veremos como criar uma conexão com o SQL Server usando ADO.NET, como construir formulários para entrada de dados usando Web Controls e, finalmente, como validar informações usando os componentes de validação do ASP.NET. Acredito que o ASP.NET seja o maior motivo para empresas e desenvolvedores entrarem de cabeça na nova plataforma da Microsoft. E para começar, que tal fazermos uma aplicação básica, encontrada na maioria dos sites da Web?
Criando o banco de dados Para este exemplo utilizaremos o banco de dados SQL Server, que será acessado a partir do provider SQL para ADO.NET que é distribuído juntamente com o .NET Framework. Nada impede que você utilize um banco de dados diferente como MySQL, Oracle e Firebird dentre outros. Você pode inclusive utilizar o provider ADO.NET de sua preferência (OleDB, por exemplo), pois os recursos do ADO.NET utilizados neste exemplo são comuns a todos os providers para ADO.NET. WebMobile 31
wm02.indb 31
6/4/2005 22:21:09
A 1 mostra o script de criação da tabela USUARIOS. Você pode criar essa tabela em um novo banco de dados no SQL Server ou usar um banco existente para facilitar. O objetivo não é criar um exemplo complexo, mas focar nos conceitos básicos da utilização do ASP.NET. Vamos partir para a criação da aplicação Web.
1. Script para criação da tabela de usuários create table USUARIOS (LOGIN char(10) not null, NOME varchar(40), SENHA varchar(10),
Criando a aplicação ASP.NET e configurando o Web Form No Visual Studio .NET, clique em File|New>Project e escolha ASP.NET Web Application no item Visual C# Projects. Dê o nome de “USUARIOS” para a aplicação e clique em Ok. No Solution Explorer, selecione o arquivo aspx, pressione F2 e altere seu nome para Cadastro.aspx. Usando a Toolbox, coloque no formulário os seguintes controles da categoria Web Forms: seis Labels, um Button, cinco TextBoxes (configure a propriedade ID para “tbLOGIN”, “tbNOME”, “tbSENHA”, “tbCONFIRMA” e “tbEMAIL”, respectivamente). Da categoria HTML coloque um Reset Button. Os campos tbSENHA e tbCONFIRMA devem ter a propriedade TextMode configuradas para Password. Observe que todo o código de interface vai sendo gerado no arquivo aspx. O código responsável pela funcionalidade da aplicação é programado em um arquivo separado, chamado nesse caso de cadastro.aspx.cs. Esse arquivo é compilado na forma de um assembly .NET (DLL) e roda no servidor, garantindo a performance da aplicação. Esse recurso é conhecido como code-behind. Isso significa que você pode alterar o arquivo aspx (adicionando novos controles ou formatando os já existentes) sem que para isso seja necessário recompilar a aplicação (assembly). Você pode usar tanto Web Controls quanto controles HTML para construir seu Web Form. Esse último tipo de controle gera código mais próximo da sintaxe HTML padrão e foram construídos para facilitar a migração de formulários HTML para páginas aspx. Use Web Controls quando precisar manipular eventos e propriedades do componente no servidor ou precisar de controles que renderizem código mais sofisticado, como grids e calendários. Optei por utilizar Web Controls para labels, button e textboxes, e HTML para o reset. O uso de HTML ao invés de Web Controls pode adicionar um pouco de performance à aplicação. Caso tenha utilizado um controle HTML e queira mesmo assim manipular algumas de suas propriedades no servidor (em um evento, por exemplo), basta dar um clique com o botão direito sobre ele e ativar a opção “Run As Server Control”. Isso basicamente adiciona o atributo runat = “server” ao controle no arquivo aspx e declara o objeto com o modificador protected na classe do formulário. O Designer coloca ainda uma pequena indicação no canto superior esquerdo do controle (uma seta), mostrando que o mesmo está com o atributo runat = “server”. Em nosso exemplo, o uso do Reset Button é uma excelente alternativa: ele limpará o formulário sem que para isso seja enviar
EMAIL varchar(40)); alter table USUARIOS add constraint USUARIOS_PK primary key (LOGIN);
uma requisição ao servidor Web. Observe que neste exemplo estamos utilizando coordenadas absolutas para posicionamento dos controles em tela. Você pode comprovar isso examinando a tag gerada para os componentes no arquivo aspx, como no exemplo a seguir: <asp:Label id=”Label1” style=”Z-INDEX: 1; LEFT: 30px; POSITION: absolute; TOP: 38px”...> </asp:Label>
Com isso, cada controle será representado no browser com base nas coordenadas definidas em tempo de design. Uma outra opção seria usar o modelo GridLayout e posicionar os controles um abaixo do outro, ou usando tabelas para organizar seus posicionamentos. Caso queira usar essa opção, configure a propriedade PageLayout do objeto Document.
Acessando o banco com ADO.NET Coloque um SqlConnection no formulário (categoria Data) e abra o editor da sua propriedade ConnectionString para configurar uma conexão com o SQL Server. Na janela que aparece ( 1) escolha o nome do servidor, o tipo de autenticação e o banco de dados que será acessado. Use o botão Testar Conexão para ver se está tudo Ok. Agora coloque dois SqlCommands da categoria Data, apontando a propriedade Connection de cada um para o SqlConnection1. Esses componentes são responsáveis pela execução de comandos SQL no servidor, como Insert, Update, Delete, Select. Altere a propriedade CommandText do SqlCommand1 conforme mostrado a seguir: INSERT INTO USUARIOS (LOGIN, NOME, SENHA, EMAIL) VALUES (@LOGIN, @NOME, @SENHA, @EMAIL)
Observe que serão adicionados os parâmetros na propriedade Parameters (confirme quando questionado). Se você já criou uma aplicação com ADO.NET anteriormente, pode estar se
32 2º Edição
wm02.indb 32
6/4/2005 22:21:14
Tutorial
1. Criando uma conexão com o SQL Server
perguntando: por que não usamos um SqlDataAdapter e um DataSet neste exemplo? Como vamos apenas inserir (Insert) os dados em um primeiro momento, não estamos nos preocupando com as operações Select, Delete e Update, logo não há necessidade de usar um SqlDataAdapter. Um SqlDataAdapter nada mais é que um componente que encapsula internamente quatro SqlCommands, um para cada operação. Não há problema algum em usar um SqlCommand separadamente. Outra vantagem é que, com isso, não precisamos armazenar nenhum objeto na memória do servidor para fazer a inserção (como DataSets), o que aumenta ainda mais a escalabilidade da solução. No segundo SqlCommand, defina o seguinte CommandText: select 1 from USUARIOS where LOGIN = @LOGIN
Essa consulta tem por objeto verificar se um usuário já está cadastrado no banco. Para aumentar a performance da consulta, retornamos apenas o número “1” caso algum registro seja encontrado. Esse segundo SqlCommand será utilizado quando criarmos as validações no formulário. Certifique-se que o parâmetro foi adicionado na propriedade Parameters do componente.
Validando o formulário O ASP.NET reduz drasticamente o trabalho de validação de formulários através de controles especializados descendentes de BaseValidator (que descende de Label).
Por exemplo, coloque um RequiredFieldValidator e aponte sua propriedade ControlToValidate para o tbNOME. Pronto! Com isso será incluída validação para garantir que um valor seja digitado no controle quando os dados do formulário forem enviados ao servidor. Fácil não? Para personalizar a mensagem de erro, use a propriedade ErrorMessage. Temos alguns controles de validação mais sofisticados. Em nossa aplicação, precisamos garantir que a senha digitada em tbSENHA tenha o mesmo valor de confirmação digitado em tbCONFIRMA. Para garantir isso, coloque um CompareValidator, aponte sua propriedade ControlToValidate para tbCONFIRMA e ControlToCompare para tbSENHA. Em Operator selecione a opção Equal, indicando que queremos fazer um teste de igualdade (existem outras opções, como testar se um valor é maior que outro, é diferente ou se é de um determinado tipo). Digite “Senha não confirma” em ErrorMessage. Pronto, não foi necessária nenhuma linha de código! A validação do e-mail é um pouco mais “complicada”. Precisamos garantir que o e-mail está no formato esperado, contendo somente caracteres válidos, tenha um @ e tenha o domínio do servidor no estilo “servidor.com”. O .NET Framework facilita muito esse processo através do conceito de expressões regulares. Para ver como isso funciona na prática, coloque um RegularExpressionValidator e aponte seu ControlToValidate para tbEMAIL. Abra o editor da propriedade ValidationExpression e escolha a opção Internet E-mail Address. Observe que a expressão regular “\w+([-+.]\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*” será adicionada à propriedade. Essa expressão contém todas as regras para validação do campo e-mail. Agora basta digitar a mensagem de erro na sua propriedade ErrorMessage. Já imaginou quantos ifs você teria que codificar caso precisasse fazer esse teste “no braço”? Produtividade é um dos pontos fortes do .NET, como podemos comprovar. Observe que todas essas validações serão feitas no browser. O ASP.NET é capaz de gerar código Java Script (se o browser utilizado suportar) para validar tudo no cliente, poupando requisições ao servidor e aumentando a performance da aplicação. No entanto, nem todas as validações podem ser feitas no browser, pois podem envolver um processamento que só pode ser feito no servidor Web, ou que não seja suportado pelos componentes de validação fornecidos pelo framework. Como faríamos a validação do campo Login (para ver se já não está cadastrado) sem fazer uma consulta ao servidor? Para essas situações mais específicas podemos utilizar o CustomValidator, que também herda da classe BaseValidator. Você deve então incluir um manipulador para o evento ServerValidate e fornecer sua validação customizada. O código da 2 mostra o código que deve ser inserido nesse evento. O que basicamente fazemos no código é atribuir o parâmetro da consulta e chamar o método ExecuteScalar do SqlCommand para verificar se há um valor de retorno (indicando que usuário já existe). WebMobile 33
wm02.indb 33
6/4/2005 22:21:16
ExecuteScalar é ideal para esse tipo de situação, quando apenas o primeiro campo do primeiro registro precisa ser acessado, o que aumenta a performance da consulta. Os outros dois métodos disponíveis são ExecuteNonQuery (visto a seguir) e ExecuteReader, normalmente utilizado em consultas Select que retornam um conjunto de dados a ser manipulado através de um DataReader. O parâmetro args.IsValid indica se a validação falhou ou teve sucesso. A 2 mostra como ficou nossa aplicação ainda em tempo design.
1. Desativando validação Caso queira desativar uma validação momentaneamente (durante a fase de testes da aplicação, por exemplo), basta configurar a propriedade Enabled do controle de validação para False.
2. Validação personalizada com CustomValidator private void CustomValidator1_ServerValidate(object source, System.Web.UI.WebControls.ServerValidateEventArgs args) { sqlConnection1.Open(); try { sqlCommand2.Parameters[“@LOGIN”].Value = tbLOGIN. Text; args.IsValid = sqlCommand2.ExecuteScalar() == null; } finally { sqlConnection1.Close(); } }
Inserindo os dados no banco E finalmente, vamos colocar o código que permitirá a inclusão dos dados do formulário na tabela USUARIOS. Tudo o que precisamos fazer é passar os valores para os parâmetros do primeiro SqlCommand, que contém a instrução Insert. Esses valores são obtidos com base nos valores digitados nos TextBoxes. A 3 mostra o código do evento Click do botão Cadastrar. Se tudo ocorreu bem, atribuímos os parâmetros do SqlCommand e chamamos seu método ExecuteNonQuery (pois é um comando de inserção que não retorna um conjunto de dados) e redirecionamos o usuário para uma segunda página, chamada Confirma.aspx. Você deve criar essa página dando um clique com o botão direito sobre o projeto no Solution Explorer e acessando a opção Add>Add Web Form. Para o redirecionamento, usamos o método Redirect do objeto Response, passando como parâmetro da URL o login do usuário. No evento Load (método Page_Load) da página Confirma.aspx recuperamos esse valor e mostramos ao usuário uma mensagem de confirmação ( 4). Para isso, usei o QueryString do objeto Request, que permite obter várias informações enviadas pelo browser para o servidor, entre elas os campos passados para a página. Essa é uma das várias formas existentes para trocar informações entre páginas. Outras opções seriam o uso de Cookies e variáveis de sessão (Session) dentre outras. Rode a aplicação e teste as validações e a inserção de usuários no banco de dados. Veja a aplicação final em execução na 3.
2. Formulário em tempo de design: controles de validação, Web Controls e componentes ADO.NET
34 2º Edição
wm02.indb 34
6/4/2005 22:21:22
Tutorial
3. Inserindo os dados no Banco de Dados private void Button1_Click(object sender, System. EventArgs e) { sqlCommand1.Parameters[“@LOGIN”].Value = tbLOGIN.Text; sqlCommand1.Parameters[“@NOME”].Value = tbNOME.Text; sqlCommand1.Parameters[“@SENHA”].Value = tbSENHA.Text; sqlCommand1.Parameters[“@EMAIL”].Value = tbEMAIL.Text; sqlConnection1.Open(); try { sqlCommand1.ExecuteNonQuery(); Response.Redirect(“Confirma.aspx?Login=” + tbLOGIN.Text); } finally { sqlConnection1.Close(); } }
4. Página confirmando o cadastro private void Page_Load( object sender, System.EventArgs e) { Response.Write(Request.QueryString[“LOGIN”] + “, cadastro efetuado com sucesso, obrigado”); }
Conclusões O ASP.NET é sem dúvida uma poderosa tecnologia para a criação de aplicações Web. Espero com este artigo ter incentivado o uso do ASP.NET. Um abraço a todos!
Guinther Pauli É Bacharel em Sistemas de Informação pelo Centro Universitário Franciscano (Unifra – RS), tem 10 anos de experiência como desenvolvedor e é autor de mais de 100 artigos publicados na área. É certificado oficial Borland, Editor Geral da revista ClubeDelphi e Co-Editor . da Revista Web Mobile Magazine. Pode ser contatado pelo endereço guinther_pauli@hotmail.com ou guinther@portalwebmobile.com.br
Faça o download no site: www.portalwebmobile.com.br/revista/ed2 3. Cadastro de usuários usando ASP.NET e ADO.NET
WebMobile 35
wm02.indb 35
6/4/2005 22:21:26
Smartphone com .NET por Renato Haddad
V
ocês se lembram do tempo em que não havia telefone celular? Todos se comunicavam de alguma forma, seja através da internet, de carta, de telefone fixo, enfim, o conceito de comunicação era outro. Com a chegada dos telefones celulares, a vida e os costumes foram alterados de forma que você consegue ficar conectado 24 horas por dia. A facilidade oferecida por esta nova tecnologia impulsionou um mercado fabuloso em relação a movimentação de dinheiro, seja através de receitas para as operadoras, seja através de negócios fechados no mundo móvel ou até, é claro, para os fabricantes de aparelhos (devices). Que esta tecnologia veio para mudar os conceitos ninguém tem dúvida. Atualmente o número de telefones celulares já ultrapassou a quantidade de linhas fixas. O uso destes aparelhos reduziu o custo de instalação a praticamente zero, pois não há cabeamento nenhum, apenas as torres de transmissão e replicação dos sinais. É fato que este investimento das operadoras tem sido na casa dos milhões, mas mesmo assim, estudos comprovam que o custo benefício proporcionou uma recuperação do investimento muito rápido. Mudando um pouco do cenário celular para um computador, você já utilizou o Microsoft Outlook® ou o Outlook Express®, cadastrando contatos, agendas, usando e-mails, etc? É provável que sim, para não dizer “com certeza”. O uso da interface do Windows já é totalmente familiar para a maioria dos usuários de computador. Que tal se você transferir esta interface conhecida para um telefone celular? Acredite, isto não é só possível como é uma realidade. Para isto, alguns fabricantes criaram os aparelhos unindo todos os recursos de um telefone celular com a facilidade que o Windows oferece. Estes aparelhos são os Smartphones ou telefones inteligentes. O sistema operacional dos Smartphones é o Windows Mobile (antigo Pocket PC 2003), o qual contém uma interface totalmente conhecida por muitos usuários de computador (ver 1).
36 2º Edição
wm02.indb 36
6/4/2005 22:21:34
Smartphone
Surge então a seguinte pergunta: Qual seria o objetivo de ter uma aplicação Windows no Smartphone? Temos também uma resposta: unir as funcionalidades de um telefone com o mundo .NET, seja através de uma simples aplicação até o consumo de Web Services para consultas a bancos de dados. Os Smartphones poderão agregar valor às aplicações desenvolvidas em .NET, por exemplo, parte de uma solução pode estar no Smartphone, como envio de mensagens (SMS – Sort Message Service), aprovação de pedidos de compras, consultas de estoque, saldo bancário, pagamento de contas, etc.
Como um Smartphone funciona?
1. Interface do SmartPhone.
Indo mais adiante nesta interface, que tal unir as funcionalidades do Microsoft Outlook (agenda, contatos, Inbox) com o Smartphone? A proposta da Microsoft em relação a estes dispositivos é proporcionar uma forma de trazer os usuários do Windows para agregar valor a mais um novo dispositivo, o telefone celular. Resumindo, se operar um telefone celular e o Windows já é comum a todos, então, operar um Smartphone também será. A idéia é justamente esta. Além destes recursos, você ainda dispõe: Internet Explorer para navegar na internet, MSN Messenger para ficar conectado ao messenger, ActiveSync para sincronizar dados com o desktop, servidor ou o Exchange (ler e-mails), Windows Media Player para tocar sons, vídeos, etc, calculadoras, jogos, entre outras funcionalidades (ver 2). Neste tutorial, você aprenderá a desenvolver um projeto para este tipo de dispositivo através do Visual Studio .NET 2003.
O Smartphone possui os mesmos recursos que um telefone celular comum. Usa o GSM para se comunicar e o GPRS para trafegar dados (internet, e-mail). Portanto, basta você comprar um cartão com chip GSM, acoplar ao dispositivo e pronto. Existem casos de configuração específica para navegar na internet, pois isto depende da operadora do seu chip GSM. Um aviso importante para quem for usar o Smartphone em qualquer lugar do mundo, é preciso verificar e configurar a freqüência do país, por exemplo, no Brasil trabalhamos com uma freqüência de 900/1800 MHZ. Para isto, acesse o menu Start / Settings / Phone / Change Band. Cabe ressaltar que na 3 não consta o Change Band pelo fato de ser um emulador.
Como é a cobrança para estes dispositivos? Na tecnologia GPRS, quando você trafega informações pela rede, existe um tamanho de Kbytes transmitidos. Você pagará pelos Kbytes enviados e vale dizer que você já está 24 horas ligado na rede/internet. Se o fluxo de dados promete ser grande na sua empresa, é possível fazer uma parceria com a operadora e montar um modelo de negócios para um tamanho determinado de dados trafegados. Esta prática tem-se demonstrado a melhor forma de reduzir os custos. Entretanto, já que em um Smartphone você consegue trafegar dados (textos e imagens), é comum o uso de uma interface rica em imagens, cores, fontes, etc e, isto pode sair um pouco mais caro que o previsto. Por outro lado, a sua aplicação será mais rica em recursos.
O que um Smartphone tem a ver com o mundo de desenvolvimento? A resposta é simples, acompanhe o raciocínio: se o sistema operacional é o Windows Mobile e a interface já é conhecida, então, porque não desenvolver aplicações para este dispositivo? É justamente isto que vou mostrar neste tutorial, o desenvolvimento de aplicações Windows para serem executados no Smartphone. O desenvolvimento será todo baseado em .NET usando a linguagem VB.NET como referência, mas se você preferir, use o Visual C#.
2. Algumas funcionalidades do SmartPhone.
WebMobile 37
wm02.indb 37
6/4/2005 22:21:41
3. Configurações da banda.
Interfaces com usuários (UI) Responda rápido: você acha fácil e prático cadastrar alguém na agenda do celular ou ainda, enviar uma mensagem SMS? Se a resposta for sim, é porque você deve ter muita paciência, parabéns! A única interface que um telefone oferece é o teclado, independente do tipo e do fabricante. Salvo casos em que é possível adicionar o reconhecimento de voz. De qualquer forma, o teclado numérico/alfanumérico será o seu meio de interação com o Smartphone. Especialmente em aplicações para celulares, a interface deve ser extremamente bem planejada, pois pode levar ao sucesso ou fracasso de uma aplicação. Veremos neste tutorial a criação de interfaces com usuários (UI) com os possíveis controles existentes para Smartphone.
o suficiente para se criar uma UI inteligível. Vamos dar início à criação de nossa aplicação. Adicione um formulário chamado Controles (ver 6). Feito isto, selecione o menu View / Toolbox para exibir a caixa de ferramentas (Ctrl + Alt + X) e arraste para o formulário os controles apresentados na 1. Pressione F4 para exibir a janela de propriedades e para cada controle configure as propriedades definidas na 1 (ver 6). Como a UI será baseada no menu, inclua o controle MainMenu e digite as seguintes opções visualizadas na 7. Por uma questão de funcionalidade, cabe ressaltar que o controle menu de um Smartphone deve ter no máximo duas opções horizontais e dez verticais, pois o acesso será feito via teclado numérico. O próprio sistema operacional se encarrega de numerar as opções, dispensando assim ter que ficar controlando cada número. A questão mais importante do controle MainMenu é que a primeira opção (Sair, neste exemplo) jamais poderá ter um submenu. Isso se dá devido à funcionalidade da interface programada para estes dispositivos.
Novo projeto Inicialmente vamos criar um projeto de interface com o usuário, assim como o uso de alguns controles utilizados no Smartphone. Abra o Visual Studio .NET 2003, selecione File / New / Project (Ctrl + Shift + N) e digite os dados (ver 4): • Project Types: Visual Basic Projects • Templates: Smart Device Application • Name: tutorialSphone • Location: C:\Projetos\WebMobile Clique no botão OK e será exibida uma nova janela contendo opções para Pocket PC, Windows CE ou Smartphone. Selecione Smartphone e em projetos do tipo, Windows Application. Note ainda que a quantidade de emuladores disponíveis nesta janela depende da quantidade instalada na sua máquina. Clique no botão OK para criar o projeto. Note que a Solution chama-se tutorialSphone e que é criado o Form1.cs automaticamente (ver 5). Clique com o botão direito sobre o Form1.cs e exclua-o. Para criar qualquer formulário durante todo o treinamento, abra o Solution Explorer, clique com o botão direito sobre tutorialSphone e selecione Add / Add Windows Form, informe o nome e clique no botão Open.
4. Novo projeto.
Controles e propriedades Em função das limitações da interface de usuário, a quantidade de controles existentes para Smartphone é pequena, porém,
5. Formulário.
38 2º Edição
wm02.indb 38
6/4/2005 22:21:48
Smartphone
2 Labels 1 TextBox
ID: Label1
Text: Nome
Forecolor: red
ID: lblNome Text: branco Forecolor: 0, 0, 192 (azul) Name: txtNome
1. Controles do formulário.
Text: branco
Códigos Pressione a tecla F7 para exibir a janela de códigos e note que todos os controles herdam da classe System.Windows.Forms.Form (ver 1). Além disso, cada tipo de controle possui uma classe específica (Label, TextBox, MainMenu). Isto serve para qualquer tipo de controle inserido no formulário. Expanda a região abaixo para exibir como que os controles são criados e adicionados ao formulário. #Region “ Windows Form Designer generated code “
Note que existe o construtor da classe (Public Class Controles), que é o próprio formulário, o qual invoca o procedimento InitializeComponent() (ver 2). É justamente nesta rotina que você deve inicializar variáveis públicas ou chamar rotinas que serão executadas quando o formulário for criado. Veja na 3 o código que define os controles e os incluem no formulário. Cada propriedade alterada na janela Properties é refletida aqui no código. Note que é criada uma nova instância do respectivo controle, são definidas as propriedades dos mesmos e ao final são adicionados (Controls.Add) ao objeto formulário. Pressione Shift + F7 para retornar ao design do formulário. Dê um duplo clique na opção de menu Sair e digite o código que fechará a aplicação. Private Sub MenuItem1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MenuItem1.Click Me.Close() End Sub
Faça o mesmo procedimento para o menu Label e digite o código da 4. Faça o mesmo para o menu MessageBox, o qual exibirá o conteúdo no corpo da mensagem ao usuário (ver 5).
6. Propriedades dos Controles.
1. Public Class Controles Inherits System.Windows.Forms.Form Friend WithEvents Label1 As System.Windows.Forms.Label Friend WithEvents txtNome As System.Windows.Forms.TextBox Friend WithEvents lblNome As System.Windows.Forms.Label Friend WithEvents MainMenu1 As System.Windows.Forms.MainMenu Friend WithEvents MenuItem1 As System.Windows.Forms.MenuItem Friend WithEvents MenuItem2 As System.Windows.Forms.MenuItem Friend WithEvents MenuItem3 As System.Windows.Forms.MenuItem Friend WithEvents MenuItem4 As System.Windows.Forms.MenuItem
7. Menu de opições.
WebMobile 39
wm02.indb 39
6/4/2005 22:21:55
Execução Para executar um formulário no Smartphone, abra o Solution Explorer, clique com o botão direito no tutorialSphone e selecione propriedades. Na opção Startup object, selecione o nome do projeto Controles e clique em OK (ver 8). A partir deste momento,
4. Private Sub MenuItem3_Click(ByVal sender As System. Object, ByVal e As System.EventArgs) Handles MenuItem3. Click ‘Verifica se o conteúdo é vazio If Me.txtNome.Text.Trim = String.Empty Then
2.
‘exibe uma mensagem MessageBox.Show(“Digite o nome”, “Tutorial SPhone”)
Public Sub New()
‘seta o foco no controle
MyBase.New() ‘This call is required by the Windows Form Designer. InitializeComponent()
‘Add any initialization after the InitializeComponent() call End Sub
txtNome.Focus() Else ‘exibe no label o conteúdo digitado lblNome.Text = txtNome.Text.Trim End If End Sub
‘
3.
‘MainMenu1 <System.Diagnostics.DebuggerStepThrough()> Private Sub
‘
InitializeComponent()
Me.MainMenu1.MenuItems.Add(Me.MenuItem1)
Me.Label1 = New System.Windows.Forms.Label
Me.MainMenu1.MenuItems.Add(Me.MenuItem2)
Me.txtNome = New System.Windows.Forms.TextBox
‘
Me.lblNome = New System.Windows.Forms.Label
‘MenuItem1
Me.MainMenu1 = New System.Windows.Forms.MainMenu
‘
Me.MenuItem1 = New System.Windows.Forms.MenuItem
Me.MenuItem1.Text = “Sair”
Me.MenuItem2 = New System.Windows.Forms.MenuItem
‘
Me.MenuItem3 = New System.Windows.Forms.MenuItem
‘MenuItem2
Me.MenuItem4 = New System.Windows.Forms.MenuItem
‘
‘
Me.MenuItem2.MenuItems.Add(Me.MenuItem3)
‘Label1
Me.MenuItem2.MenuItems.Add(Me.MenuItem4)
‘
Me.MenuItem2.Text = “Ler Dado”
Me.Label1.ForeColor = System.Drawing.Color.Red
‘
Me.Label1.Size = New System.Drawing.Size(152, 22)
‘MenuItem3
Me.Label1.Text = “Nome:”
‘
‘
Me.MenuItem3.Text = “Label”
‘txtNome
‘
‘
‘MenuItem4
Me.txtNome.Location = New System.Drawing.Point(0, 24)
‘
Me.txtNome.Size = New System.Drawing.Size(152, 25)
Me.MenuItem4.Text = “MessageBox”
Me.txtNome.Text = “”
‘
‘
‘Controles
‘lblNome
‘
‘
Me.Controls.Add(Me.lblNome)
Me.lblNome.ForeColor = System.Drawing.Color.
Me.Controls.Add(Me.txtNome)
FromArgb(CType(0, Byte), CType(0, Byte),
Me.Controls.Add(Me.Label1)
CType(192, Byte))
Me.Menu = Me.MainMenu1
Me.lblNome.Location = New System.Drawing.Point(0, 56)
Me.Text = “Controles”
Me.lblNome.Size = New System.Drawing.Size(152, 22)
40 2º Edição
wm02.indb 40
6/4/2005 22:21:59
Smartphone
5. Private Sub MenuItem4_Click(ByVal sender As System. Object, ByVal e As System.EventArgs) Handles MenuItem4.Click ‘Verifica se o conteúdo é vazio If Me.txtNome.Text.Trim = String.Empty Then ‘exibe uma mensagem MessageBox.Show(“Digite o nome”, “Tutorial SPhone”, _ MessageBoxButtons.OK, MessageBoxIcon.Exclamation, _ MessageBoxDefaultButton.Button1) ‘seta o foco no controle txtNome.Focus() Else ‘exibe uma mensagem com o conteúdo digitado MessageBox.Show(“Bem vindo: “ & txtNome.Text.Trim, _ “Tutorial SPhone”, MessageBoxButtons.OK, _ MessageBoxIcon.Exclamation, _ MessageBoxDefaultButton.Button1) End If End Sub
Note a diferença entre as configurações do comando MessageBox.Show, em relação à quantidade de parâmetros declarados (ver 11).
Propriedades do TextBox O TextBox é um dos controles mais utilizados em Smartphone, portanto, quero destacar algumas propriedades importantes: • Enabled / Visible (True/False): habilita /desabilita ou oculta/ exibe o controle; • MaxLength: define o número máximo de caracteres digitados; • Multiline (True/False): permite digitar ou exibir dados em várias linhas; • PasswordChar: usado para definir o caractere a ser exibido quando digitada uma senha; • ScrollBars (none, horizontal, vertical, both): exibe ou não barras de rolagem quando o multiline for True; • TextAlign: indica como que o texto será alinhado para edição no controle.
9. Deploy da aplicação.
8. Startup do projeto.
quando você executar o projeto, é o formulário definido nesta opção que será executado. Portanto, preste atenção nisto, pois todos os demais formulários desenvolvidos a seguir, precisarão desta configuração para execução. Selecione o menu Build / Build Solution para compilar toda a aplicação. Se tudo ocorreu corretamente, você deverá receber uma mensagem na janela de Output informando que o projeto foi compilado com sucesso. A seguir, selecione o menu Debug / Start ou pressione F5 para executar. Será exibida uma janela para que você escolha o local / emulador. Caso o Smartphone esteja conectado ao computador com o Active Sync rodando, selecione Smartphone Device. Caso contrário, use o emulador para testar a aplicação. Clique em Deploy e teste (ver 9). Neste ponto, poderemos utilizar nossa aplicação que pode ser visualizada na 10.
10. Execução da aplicação.
11. Execução da aplicação.
WebMobile 41
wm02.indb 41
6/4/2005 22:22:04
Explorando outros recursos Nesta parte, iremos desenvolver um outro formulário a fim de explorar outros controles (combobox e checkbox) e métodos da linguagem, criando uma interface amigável com o usuário. Adicione um novo formulário (Add / Add Windows Form) chamado Futebol, contendo os controles e suas propriedades apresentadas na 2. Depois de inseridos os controles, teremos a interface como a apresentada na 12. Agora adicione um MainMenu com as seguintes opções: Sair / Opção (Novo Time / Enviar) (ver 13). Pressione F7 para exibir a janela de código. Localize o InitializeComponent() e digite o código da 6 para montar os itens de preenchimento da cboTimes. Note que para cada elemento é usado o método Add seguido do respectivo texto. Ao final, todos estes itens farão parte da lista de elementos da cboTimes. Outra possibilidade de você montar uma lista sem ter que programar é através da propriedade Items (Collection) da cboTimes. Clique no botão construtor (...) e digite a respectiva lista. A desvantagem é que os itens não serão classificados, ou seja, você tem que digitar na ordem. Para a opção de menu Sair, digite o código abaixo:
6. #Region “ Windows Form Designer generated code “
Public Sub New() MyBase.New()
‘This call is required by the Windows Form Designer. InitializeComponent()
‘preenche a cboTimes com os items With cboTimes.Items .Add(“Palmeiras”) .Add(“Corinthians”) .Add(“Flamengo”) .Add(“Avaí”) .Add(“Fluminense”) .Add(“São Paulo”) .Add(“Santos”) End With ‘seleciona o primeiro item da lista cboTimes.SelectedIndex = 0 End Sub
Private Sub MenuItem1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MenuItem1.Click Close()
7.
End Sub
Digite o código apresentado na 7 para o menu Enviar, o qual verifica o conteúdo dos controles da tela e envia uma mensagem. A opção de menu Novo Time irá inserir o nome do novo time digitado por você na cboTimes. Portanto, adicione os controles descritos na 3 na interface (ver 14).
Private Sub MenuItem3_Click(ByVal sender As System. Object, ByVal e As System.EventArgs) Handles MenuItem3.Click ‘verifica se a cboTimes contém um item selecionado If cboTimes.SelectedIndex < 0 Then MessageBox.Show(“Selecione um time”, “Tutorial”, _ MessageBoxButtons.OK, MessageBoxIcon.Hand, _ MessageBoxDefaultButton.Button1)
1 Label
Text: Times
1 ComboBox
Name: cboTimes
2 CheckBox
Name: ckAssociado Name: ckCarteira
‘abandona a rotina Exit Sub
Text: associado? Text: tem carteirinha?
End If ‘Define um stringBuilder para manipular strings Dim msg As New System.Text.StringBuilder ‘Adiciona uma string
2. Novos controles.
msg.Append(“Time: “ & cboTimes.Text) ‘Verifica se o ckAssociado está selecionado If ckAssociado.Checked Then msg.Append(vbNewLine & “Associado do clube”) End If ‘Verifica se o ckCarteira está selecionado If ckCarteira.Checked Then msg.Append(vbNewLine & “possui carteirinha”) End If MessageBox.Show(msg.ToString(), “tutorial”, _ MessageBoxButtons.OK, MessageBoxIcon.Asterisk, _ MessageBoxDefaultButton.Button1) End Sub
12. UI do formulário.
13. Opções do menu.
42 2º Edição
wm02.indb 42
6/4/2005 22:22:10
Smartphone
1 Label
Name: lblTime
Text: novo time:
Visible: False
1 TextBox
Name: txtTime
Text: branco
Visible: False
3. Controles da UI.
Note que ambos controles estarão invisíveis quando o formulário for carregado pela primeira vez. Quando o usuário selecionar a opção Novo Time, estes dois controles serão exibidos para que o nome do time seja digitado. E, para capturar o nome digitado e adicionar à cboTimes, é preciso criar uma opção no menu Opção chamada Adicionar. Note que a propriedade Enabled desta opção deve estar definida para False, ou seja, está desabilitada (ver 15). Agora digite o código da 8 para a opção Novo Time, o qual exibe os lblTime e o txtTime, coloca o cursor (foco) no txtTime e ativa a opção MenuItem5 (Adicionar). Feito isto, digite o código para a opção Adicionar, o qual verifica se o usuário digitou o nome do novo time e inclui na cboTimes. Como a interface é pequena, você precisa controlar a exibição dos controles e desabilitar a opção do menu Adicionar (MenuItem5) (ver 9). Agora defina este formulário como o Startup Object e execute no emulador. Note que assim que carregado, são exibidas todas as opções da cboTimes (ver 16). Para navegar entre os itens, você pode selecionar as setas de direção ou ainda pressionar o botão central de seleção (azul) para exibir todas as opções na forma de lista. Em seguida, desloque o foco até a opção desejada e clique na opção Done (ver 17). Para selecionar as outras duas opções de checkBox, é preciso sempre focar na opção e em seguida pressionar o botão de seleção azul. Selecione o menu Opção e note que estão disponíveis apenas as duas primeiras, pois o Adicionar está desativado. Selecione a opção 1 Enviar, o qual irá capturar os dados selecionados e exibi-los na tela. Para cadastrar um novo time na lista de times, selecione o menu Opção / 2 Novo Time. Veja que 14. UI do formulário.
15. Propriedades do menu.
8. Private Sub MenuItem4_Click(ByVal sender As System. Object, ByVal e As System.EventArgs) Handles MenuItem4.Click ‘exibe os controles lblTime.Visible = True txtTime.Visible = True ‘coloca o foco no txtTime txtTime.Focus() ‘ativa a opção Adicionar do menu MenuItem5.Enabled = True End Sub
.9 Private Sub MenuItem5_Click(ByVal sender As System. Object, ByVal e As System.EventArgs) Handles MenuItem5.Click ‘verifica se o novo time foi digitado If txtTime.Text.Trim <> String.Empty Then ‘adiciona o item a cboTimes cboTimes.Items.Add(txtTime.Text.Trim) ‘apaga o conteúdo do txtTime txtTime.Text = String.Empty End If ‘oculta os controles txtTime.Visible = False lblTime.Visible = False ‘desativa a opção Adicionar MenuItem5.Enabled = False End Sub
o Label (lblTime) e o txtTime são exibidos e o foco já é colocado no txtTime. Então, digite o nome do novo time, selecione o menu Opção / 3 Adicionar (ver 18). Consulte a lista de times novamente e note que o novo time já está adicionado!
TreeView Agora adicione um novo formulário (Add / Add Windows Form) chamado TreeviewControl, contendo um TreeView, um MainMenu e uma ImageList. Selecione o ImageList1, exiba as propriedades (F4), selecione a propriedade Images (Collection) e adicione duas imagens que serão exibidas no treeView (ver 19).
16. Execução do emulador.
WebMobile 43
wm02.indb 43
6/4/2005 22:22:19
17. Execução no emulador.
O próximo passo é associar este ImageList1 ao TreeView. Para isso, selecione a propriedade ImageList do TreeView1 e escolha o ImageList1 na lista de opções. Para definir os elementos do TreeView1, selecione a propriedade Nodes (Collection) e inclua os itens conforme a 20. Para adicionar um novo elemento no raiz, clique no botão Add Root e, em Label digite o texto. Para incluir um filho, selecione o raiz e clique em Add Child e digite o respectivo texto. No caso dos filhos, associe uma imagem diferente da default na combo Image e Selected image. Caso queira excluir alguma opção, selecione-a e clique em Delete. Por fim, clique em OK para finalizar os nós e veja o resultado (ver 21). Digite o código para o botão Sair.
18. Execução no emulador.
Private Sub MenuItem1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MenuItem1.Click Close()
19. Controle treeView.
End Sub
Por fim, salve o formulário, defina-o no Startup Object e execute-o (ver 21).
ListView Adicione um novo formulário (Add / Add Windows Form) chamado ListviewControl, contendo um ListView, um MainMenu e duas ImageList. O menu deverá ficar com a aparência da 22. Selecione o ImageList1 e adicione uma figura de forma que o tamanho da imagem fique 16, 16 (ver 23). Repita os mesmos passos para o ImageList2, no entanto, altere o tamanho das figuras para 38, 38. Em seguida, configure as propriedades do ListView1 de forma que a propriedade LargeImageList fique vinculado ao ImageList2 e a SmallImageList fique vinculado ao ImageList1. No MainMenu, digite o código apresentado na 10 para a opção Preencher, o qual irá criar uma lista de itens para preencher o ListView. Nada o impede de criar esta lista diretamente na propriedade Items.
20. Controle treeView.
44 2º Edição
wm02.indb 44
6/4/2005 22:22:25
Smartphone
Veja o código da opção Large: Private Sub MenuItem4_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MenuItem4.Click ListView1.View = View.LargeIcon End Sub
Veja o código da opção Details: Private Sub MenuItem5_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MenuItem5.Click ListView1.View = View.Details End Sub
21. Execução do controle treeView.
Veja o código da opção Small: Private Sub MenuItem6_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MenuItem6.Click ListView1.View = View.SmallIcon End Sub
Por fim, veja o código da opção Sair: Private Sub MenuItem1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MenuItem1.Click
22. UI do formulário
23. Propriedades.
Close() End Sub
Agora salve o formulário, defina-o no Startup Objects e execute-o no emulador. As telas da aplicação exemplo podem ser visualizadas na 24.
. 10 Private Sub MenuItem3_Click(ByVal sender As System. Object, ByVal e As System.EventArgs) Handles MenuItem3. Click ‘Adiciona uma nova coluna ao ListView1
Splash Para finalizar nosso artigo, veremos como criar uma tela de splash para nossa aplicação. Adicione um novo formulário
ListView1.Columns.Add(“My colunm”, ListView1.Size.Width, HorizontalAlignment.Left) ‘monta um looping para preencher os itens For i As Integer = 1 To 6 ‘define o item Dim item As New ListViewItem(“Item “ + i.ToString()) ‘associa a imagem item.ImageIndex = 0 ‘adiciona o item a lista ListView1.Items.Add(item) Next ‘configura o modo de exibição dos itens ListView1.View = View.LargeIcon End Sub
24. Execução no emulador.
WebMobile 45
wm02.indb 45
6/4/2005 22:22:29
(Add / Add Windows Form) chamado Splash contendo dois Labels e um PictureBox (ver 25). O funcionamento deste formulário se dará da seguinte forma: quando aberto, será exibido ao usuário por três segundos e depois será fechado automaticamente. Agora configure as seguintes propriedades do formulário: • BackColor: Black; • Text: Splash; • WindowsState: Maximized.
Salve o formulário, defina-o no Startup Objects e execute-o no emulador (ver 26).
Conclusão
25. UI.
Para os Labels, digite um texto qualquer que pode ser o nome da sua empresa e o nome da equipe de desenvolvimento, enfim, é um texto de apresentação. Já para o PictureBox1, selecione a propriedade Image e associe uma imagem. Para efeito de layout, se necessário altere a propriedade SizeMode para acomodar a figura adequadamente. Neste caso, selecionei CenterImage para centralizar a figura dentro do tamanho do controle definido. Adicione o controle Timer e configure a propriedade Interval para 3000. Cada intervalo de 1000 corresponde a 1 segundo, portanto, a cada 3 segundos o programa deverá disparar algum código, caso exista. Dê um duplo clique no Timer1 e veja que é criado o evento Timer1.Tick que irá disparar o seguinte código quando os 3 segundos definidos na propriedade Interval forem atingidos. Este código irá fechar o formulário, mas nada o impede de programar qualquer outro código, por exemplo abrir um novo formulário, etc.
Neste tutorial de Smartphone você aprendeu a criar formulários e manipular alguns dos controles utilizados na interface com o usuário. Futuramente, veremos como acessar um banco de dados e 26. Execução. publicar o resultado diretamente no Smartphone. Bons estudos e lembre-se: No Stress, think .NET!!!
Colocar UM TITULO AQUI!!!! www.microsoft.com/windowsmobile
Renato Haddad (rehaddad@msn.com) É Microsoft Most Valuable Professional .NET Mobile Devices, editor da revista MSDN Magazine Brasil, ministra treinamentos e palestras sobre .NET e autor de diversos livros e treinamentos em CD multimídia de ASP.NET, Visual Studio .NET 2003 e Aplicações Móveis para celulares e Pocket PC, tanto no Brasil como em outros países da América Latina.
Private Sub Timer1_Tick(ByVal sender As Object, ByVal e As System.EventArgs) Handles Timer1.Tick Close()
Faça o download no site: www.portalwebmobile.com.br/revista/ed2
End Sub
46 2º Edição
wm02.indb 46
6/4/2005 22:22:36
wm02.indb 47
6/4/2005 22:22:39
Introdução às tecnologias Web Services: SOA, SOAP, WSDL e UDDI Parte 2 por Thomas Erl
Leitura Obrigatória Web Mobile 1 Introdução às tecnologias Web Services: SOA, SOAP, WSDL e UDDI – Parte 1.
C
omo foi visto no primeiro artigo dessa série, web services são serviços que podem ser disponibilizados na internet e usados como componentes distribuídos por aplicações baseadas na web. Para alcançar esse objetivo, essa abordagem é fundamentada em uma coleção de protocolos e padrões que permitem que os serviços sejam acessados em sistemas remotos utilizando tecnologias de domínio público como o http e SOAP. Finalizando a série de artigos iniciada na edição passada, descreveremos nesta matéria os componentes do protocolo SOAP, assim como a sua utilização e também os conceitos da tecnologia UDDI.
Simple Object Access Protocol - SOAP Apesar de ter sido inicialmente concebido como a tecnologia para transpor a brecha entre plataformas baseadas em comunicação RPC, SOAP se tornou em um dos mais conhecidos formatos de mensagens e protocolo utilizado por web services baseados em XML. Por este motivo, o acrônimo SOAP é referido freqüentemente como Service-Oriented Architecture (or Application) Protocol (protocolo de arquitetura orientada a serviços) ao invés de Simple Object Access Protocol. 48 2º Edição
wm02.indb 48
6/4/2005 22:23:06
Tutorial
A especificação SOAP estabelece um formato padrão de mensagem que consiste em um documento XML capaz de hospedar dados RPC e centrados em documentos (document-centric) (ver 1). Isto facilita o intercâmbio de dados de modelos síncronos (pedido e resposta) e assíncronos (orientado a processo). Com o WSDL estabelecendo um formato de descrição padrão para aplicações, o uso do formato de mensagem document-centric é muito mais comum. A arquitetura que exploraremos ao longo deste artigo faz referência a ambos os tipos de formatos de mensagem, utilizando os símbolos padrão de diagramação fornecidos na 2. Adicionalmente, discutiremos o uso de anexos em mensagens SOAP. Estes são descritos em diferentes especificações de web services de segunda geração: os padrões WS-Attachmentes e SOAP Messages with Attachments – SwA. Mensagens SOAP contendo anexos são representados com o símbolo mostrado na 3.
1. SOAP estabelece dois formatos de mensagem padrão primários.
Arquitetura de mensagens SOAP SOAP estabelece um método de comunicação baseado em um modelo de processamento que está relativamente alinhado com a arquitetura de web services descrita na primeira parte deste artigo. Esse protocolo introduz termos e conceitos relacionados ao modo pelo qual mensagens devem ser manipuladas.
Nós SOAP
2. Símbolos utilizados para representar mensagens SOAP: (a) document-centric e (b) RPC.
Um nó SOAP representa o processamento lógico responsável pela transmissão, recebimento e realização de uma série de tarefas sobre mensagens SOAP. Uma implementação de um nó SOAP é tipicamente específica à plataforma e é normalmente rotulada como um SOAP server (servidor) ou SOAP listener (ouvinte). Existem também variações especializadas, tais como SOAP routers (roteadores). A 4 estabelece o nó SOAP como o mecanismo de transporte subjacente a um web service.
Tipos de nós SOAP Nós SOAP podem existir como emissores iniciais, intermediários e receptores finais. Nós SOAP realizando tarefas de envio e recebimento são chamados de SOAP senders e SOAP receivers (ver 5). A especificação SOAP, no entanto, não classifica isto como papeis. Para os propósitos deste artigo, nos referiremos a eles como “tipos” de nós SOAP. A 6 mostra um nó SOAP agindo como um intermediário. Ele transaciona através de ambos os tipos SOAP, receptor e emissor, durante o processamento de uma mensagem SOAP. Assim como nos papeis atribuídos aos web services, o mesmo nó SOAP pode assumir comportamentos diferentes dependendo da sua posição dentro da rota da mensagem e do estado da atividade de negócio atual. Por exemplo, um nó SOAP como um emissor inicial ao transmitir uma mensagem pode, em outro momento, assumir o papel de receptor final e também receber uma resposta enviada por um outro nó.
3. O símbolo usado para representar mensagens SOAP entregando seus dados como um anexo.
4. Um nó SOAP.
5. Tipos fundamentais de nós SOAP ao longo de uma rota de mensagem.
WebMobile 49
wm02.indb 49
6/4/2005 22:23:30
de resposta criadas especificamente para comunicar condições de erro. O construtor Fault consiste em uma série de elementos de sistema utilizados para identificar características de exceção (ver 3).
Papeis de nós SOAP
6. Nó SOAP intermediário.
Estrutura das mensagens SOAP O recipiente da informação de uma mensagem SOAP é chamado de envelope SOAP. Descreveremos na 1 a estrutura de uma típica mensagem SOAP. O elemento raiz Envelope, que delimita o documento da mensagem, é composto por uma seção Body e uma área Header que é opcional. O cabeçalho SOAP é representado através do uso de um construtor Header, o qual pode conter um ou mais blocos ou seções. O uso mais comum de blocos Header ocorre em: Implementação de extensões SOAP; Identificação de alvos SOAP intermediários; Fornecimento de meta-informação adicional sobre a mensagem SOAP. Enquanto uma mensagem SOAP trafega até o seu destino, intermediários podem acrescentar, remover ou processar as informações contidas no Header. Mesmo sendo parte opcional de uma mensagem SOAP, o uso da seção Header para carregar informações é muito comum quando se trabalha com especificações web services de segunda geração. A única parte de uma mensagem SOAP que é obrigatória é o corpo (Body). Esta seção age como um recipiente para os dados que são entregues pela mensagem. Esses dados são freqüentemente chamados de carga útil ou dados de carga útil (ver 2). O construtor Body pode ser usado também para hospedar informações de exceção dentro de elementos de falha (Fault). Seções do tipo Fault podem residir junto com informações úteis dentro de uma mensagem, contudo, este tipo de informação é freqüentemente enviado em separado, dentro de mensagens
Agora que demos uma olhada na estrutura interna e na sintaxe de uma mensagem SOAP, encerraremos este assunto com uma breve introdução aos possíveis papeis que um nó SOAP pode assumir. Nós SOAP só podem assumir um determinado papel se eles executarem uma função de recepção, ou seja, se forem receptores intermediários ou finais (ver 7). Para indicar que um nó SOAP possui em papel, o atributo env:role deve ser usado. Esse atributo permite que uma mensagem SOAP identifique blocos de cabeçalho destinados a tipos específicos de receptores SOAP. Os dois valores de atributos env:role mais comuns são next (próximo) e ultimateReceiver (receptor final). Um nó intermediário processará somente blocos com cabeçalhos identificados com o papel next, enquanto que um nó agindo como o receptor final, processará os dois. Para saber mais sobre blocos Header e como se relacionam aos web services de segunda geração, visite www.specifications.ws.
Universal Description, Discovery, and Integration - UDDI Um componente fundamental da arquitetura orientada a serviço é o mecanismo pelo qual descrições web services podem ser descobertas por requisitantes potenciais. Para estabelecer esta parte de um framework baseado em web service, é necessário um diretório centralizado para hospedar as descrições dos serviços utilizados. Tal diretório pode se tornar uma parte integrada de uma organização ou de uma comunidade disponibilizada na internet. Esta é a razão pela qual a UDDI tem crescido em importância. Um aspecto chave da UDDI é a padronização da descrição que é armazenada em tais diretórios, também conhecidas como
1. Esqueleto do envelope de um SOAP. <env:Envelope xmlns:env=”http://www.w3.org/2003/05/soapenvelope”> <env:Header> ... </env:Header> <env:Body> ... </env:Body> </env:Envelope>
50 2º Edição
wm02.indb 50
6/4/2005 22:23:37
Tutorial
registro. Um registro público de negócio é um diretório global de descrições de serviços internacionais de negócios. Instâncias deste registro são hospedadas em um grupo de servidores UDDI dedicados. Esses registros UDDI são replicados automaticamente entre instâncias de repositórios. Algumas empresas também agem como registradoras de UDDI, permitindo que outros adicionem e editem seus perfis de descrições web service. Registros privados são repositórios de descrições de serviços hospedados dentro de uma organização (ver 8). Aqueles autorizados a acessar este diretório geralmente são parceiros de
2. Exemplo de informações de um Body. <env:Envelope xmlns:env=”http://www.w3.org/2003/05/ soap-envelope”> <env:Header> ... </env:Header> <env:Body>
negócios externos. Um registro restrito a usuários internos só pode ser referenciado como registro interno. O processo de descobrimento pode ocorrer em várias situações dependendo da necessidade da informação de serviço. Por exemplo: uma organização desejando estabelecer novas relações de negócio para transações on-line pode procurar por (e comparar) parceiros apropriados utilizando um registro público de negócio; um arquiteto que esteja projetando uma nova aplicação e-Bussiness pode antes querer pesquisar a disponibilidade de lógica de programação genérica dentro da organização. Pela leitura de descrições de serviço existentes, podem ser descobertas oportunidades de reuso; o mesmo arquiteto pode também querer vender web services para terceiros, fornecendo lógica de aplicação pré-construída que pode ser incorporada (localmente ou remotamente) dentro de outra aplicação; um desenvolvedor que está construindo novos serviços precisará acessar as definições de interface para serviços
<x:Book xmlns:x=”http://www.examples.ws/”> <x:Title> Service-Oriented Architecture A Field Guide to Integrating XML and Web services </x:Title> </x:Book> </env:Body> </env:Envelope>
3. Um exemplo de construtor Fault que fornece informação de erro. <env:Envelope xmlns:env=”http://www.w3.org/2003/05/ soap-envelope”> <env:Body> <env:Fault>
7. Papeis que podem ser assumidos recepcionando nós SOAP.
<env:Code> <env:Value> env:VersionMismatch </env:Value> </env:Code> <env:Reason> <env:Text xml:lang=”en”> versions do not match </env:Text> </env:Reason> </env:Fault> </env:Body> </env:Envelope></env:Envelope>
8. Descrições de serviço centralizados em um registro UDDI privado.
WebMobile 51
wm02.indb 51
6/4/2005 22:23:50
existentes. O registro interno poupa ao desenvolvedor a preocupação quanto a saber se a interface que está sendo incorporada é ou não a mais atual. Registros UDDI organizam as entradas de registro utilizando seis tipos de dados primários: business entities (entidades de negócio); business services (serviços de negócio); specification pointers (ponteiros de especificação); service types (tipos de serviço); business relationships (relacionamentos de negócio); subscriptions (subscrições). As entidades de negócios, tal como representados pelo elemento businessEntity, fornecem informação de perfil acerca do negócio registrado, incluindo seu nome, descrição e identificador unívoco. A 4 apresenta um documento XML exemplo contendo o construtor businessEntity. Examinaremos a partir de agora este documento para analisar os construtores individuais. Começaremos pela 5. Quando XMLTC Consulting Inc. foi registrado, teve atribuído um
identificador unívoco e9355d51-32ca-49cf-8eb4-1ce59afbf4a7, o qual foi então designado para o atributo businessKey do elemento pai businessEntity. Desde que a Microsoft agiu como o nó operador, fornecendo uma instância do registro UDDI, seu nome é exibido no atributo operador do elemento businessEntity. O elemento discoveryURL (ver 6) identifica o endereço utilizado para localizar este documento XML. O elemento name simplesmente contém o nome oficial de negócio (ver 7). Registros businessService representando o serviço atual oferecido pelo negócio registrado são aninhados dentro do construtor businessEntity como pode ser observado na 8. Um serviço de negócio é identificado por um valor único conferido ao atributo serviceKey. Seu pai, o elemento businessEntity, é referenciado pelo atributo businessKey (ver 9). O único businessService associado com esta entidade de negócio é a home page do negócio, como identificada pelo elemento name (ver 10). Cada businessService fornece ponteiros de especificação. Também conhecidos como binding templates, estes registros consistem de endereços ligando o business service à informação de
4. Um documento businessEntity real, recuperado de um serviço público de registro.
businessKey=”e9355d51-32ca-49cf-8eb4-1ce59afbf4a7”>
<businessEntity xmlns:xsd=”http://www.w3.org/2001/XMLSchema”
</name>
<name xml:lang=”en-us”> Corporate Home Page
xmlns:xsi=”http://www.w3.org/2001/XMLSchema-instance” businessKey=”e9355d51-32ca-49cf-8eb4-1ce59afbf4a7”
<bindingTemplates> <bindingTemplate
operator=”Microsoft Corporation”
bindingKey=”48b02d40-0312-4293-a7f5-4449ca190984”
authorizedName=”Thomas Erl”
serviceKey=”1eeecfa1-6f99-460e-a392-8328d38b763a”>
xmlns=”urn:uddi-org:api_v2”>
<description xml:lang=”en”>
<discoveryURLs> <discoveryURL useType= “businessEntity”>http://test.uddi.microsoft.com/ discovery ?businesskey=e9355d51-32ca-49cf-8eb4-1ce59afbf4a7 </discoveryURL> </discoveryURLs> <name xml:lang=”en”> XMLTC Consulting Inc
Entry point into the XMLTC Web site through which a number of resource sites can be accessed </description> <accessPoint URLType=”http”> http://www.xmltc.com/ </accessPoint> <tModelInstanceDetails /> </bindingTemplate>
</name>
</bindingTemplates>
<description xml:lang=”en”>
<categoryBag>
XMLTC has been building end-to-end enterprise eBusiness solutions for corporations and government agencies since 1996. We offer a wide range of design, development and integration services </description> <businessServices> <businessService
<keyedReference tModelKey= ”uuid:c1acf26d-9672-4404-9d70-39b756e62ab4” keyName=”Namespace” keyValue=”namespace” /> </categoryBag> </businessService> </businessServices> </businessEntity>
serviceKey=”1eeecfa1-6f99-460e-a392-8328d38b763a”
52 2º Edição
wm02.indb 52
6/4/2005 22:23:52
Tutorial
Tutorial
WebMobile 53
WebMobile 53
implementação. Utilizando service pointers (ponteiros de serviço), um desenvolvedor pode saber como e onde se ligar fisicamente a um web service (ver 11). O construtor bindingTemplate exibido no exemplo anterior estabelece a localização e descrição do serviço, utilizando os elementos accessPoint e description. Várias categorias podem ser atribuídas a serviços de negócio. No nosso exemplo, a URL que identificamos foi classificada como um namespace utilizando o elemento filho keyedReference do construtor categoryBag (ver 12). Finalmente, dados de relações de negócio e de subscrição são representados por elementos publisherAssertions e subscription, respectivamente. Construtores publisherAssertions fornecem meios de estabelecer a relação da businessEntity atual com uma outra. Subscription permite que os assinantes sejam notificados quando a informação do perfil da entidade de negócio foi atualizada. Vale ressaltar que não existe uma relação de formato entre UDDI e WSDL. Um registro UDDI fornece meios para apontar para as definições da interface de serviços.
5. O elemento pai businessEntity com alguns atributos <businessEntity xmlns:xsd=”http://www.w3.org/2001/ XMLSchema” xmlns:xsi=”http://www.w3.org/2001/XMLSchema-instance” businessKey=”e9355d51-32ca-49cf-8eb4-1ce59afbf4a7” operator=”Microsoft Corporation” authorizedName=”Thomas Erl” xmlns=”urn:uddi-org:api_v2”>
6. O construtor discoveryURL contendo a URL original <discoveryURLs> <discoveryURL useType=”businessEntity”> http://test.uddi.microsoft.com/discovery ?businesskey=e9355d51-32ca-49cf8eb4-1ce59afbf4a7 </discoveryURL> </discoveryURLs>
7. O elemento name fornecendo o nome de negócio. <name xml:lang=”en”> XMLTC Consulting Inc </name>
wm02.indb 53
6/4/2005 22:23:58
Conclusão 8. O construtor businessService. <businessServices> <businessService serviceKey=”1eeecfa1-6f99-460e-a392-8328d38b763a” businessKey=”e9355d51-32ca-49cf-8eb4-1ce59afbf4a7”>
Essa série de artigos teve com principal objetivo apresentar uma tecnologia que está se popularizando cada vez mais: os web services. O principal motivo relacionado a essa popularização é o grande desacoplamento entre os diferentes serviços, que possibilita uma fácil e rápida construção das aplicações.
<name xml:lang=”en-us”> Corporate Home Page </name> <bindingTemplates> <bindingTemplate bindingKey=”48b02d40-0312-4293-a7f5-4449ca190984” serviceKey=”1eeecfa1-6f99-460e-a392-8328d38b763a”> <description xml:lang=”en”> Entry point into the XMLTC Web site through which a number of resource sites can be accessed </description> <accessPoint URLType=”http”> http://www.xmltc.com/ </accessPoint> <tModelInstanceDetails /> </bindingTemplate> </bindingTemplates> <categoryBag> <keyedReference
11. O construtor bindingTemplate alojando informação de localização concreta. <bindingTemplates> <bindingTemplate bindingKey=”48b02d40-0312-4293-a7f5-4449ca190984” serviceKey=”1eeecfa1-6f99-460e-a392-8328d38b763a”> <description xml:lang=”en”> Entry point into the XMLTC Web site through which a number of resource sites can be accessed. </description> <accessPoint URLType=”http”> http://www.xmltc.com/ </accessPoint> <tModelInstanceDetails /> </bindingTemplate> </bindingTemplates>
tModelKey=”uuid:c1acf26d-9672-4404-9d7039b756e62ab4” keyName=”Namespace” keyValue=”namespace” /> </categoryBag> </businessService>
12. O elemento categoryBag fornecendo a categorização mediante a utilização do elemento aninhado keyedReference
</businessServices>
<categoryBag> <keyedReference tModelKey=”uuid:c1acf26d-9672-4404-9d70-39b756e62ab4” keyName=”Namespace” keyValue=”namespace” />
9. Os atributos dos elementos serviceKey e businessKey do businessService.
</categoryBag>
<businessService serviceKey=”1eeecfa1-6f99-460e-a392-8328d38b763a” businessKey=”e9355d51-32ca-49cf-8eb4-1ce59afbf4a7”> ... </businessService>
Thomas Erl É consultor independente e arquiteto chefe da XMLTC Consulting em Vancouver, no Canadá. Ele é conhecido por seus trabalhos no modelo de escopo em camadas para XML e Web Services e, no framework de integração de Web Services (XWIF).
10. O elemento name com o serviceName. <name xml:lang=”en-us”> Corporate Home Page </name>
Faça o download no site: www.portalwebmobile.com.br/revista/ed1
54 2º Edição
wm02.indb 54
6/4/2005 22:24:02
Jogos
Incrementando um jogo J2ME/MIDP usando RMS Uma introdução ao Record Management System (RMS) por Fábio Mesquita Póvoa
WebMobile 55
wm02.indb 55
6/4/2005 22:24:09
Leitura Obrigatória Web Mobile 1 Desenvolvimento de jogos J2ME/MIDP para celular.
U
m dos fatores mais importantes para se produzir um jogo de sucesso é o seu grau de interatividade. A interatividade, em certos casos, chega a fazer com que algum defeito de um jogo passe despercebido, como uma péssima jogabilidade, fazendo-o alcançar algum sucesso. Há jogos baseados em SMS com interface gráfica bastante pobres que estão entre os mais vendidos pelas operadoras de telefonia celular (apesar do fato de que cada SMS custasse 14 centavos na época). Para mostrar alguns conceitos de interatividade que podem dar outra cara para seu aplicativo, usaremos o jogo Mobile Invaders, desenvolvido pelos nossos colegas Renato Iida e Eduardo Peixoto publicado na primeira edição da WebMobile. Foram introduzidas algumas modificações no jogo original a fim de demonstrar o funcionamento das tecnologias Record Management System e Generic Connection Framework em jogos para celulares, além de tornar o jogo mais atrativo aos seus usuários. As modificações são as seguintes: foram introduzidas fases com nível de dificuldade crescente, pontuação, armazenamento local de pontos e o mais interessante, armazenamento de pontos em um servidor. Tudo isto utilizando a tecnologia Java (J2ME/MIDP e J2EE). Nesse artigo, você irá aprender a usar as tecnologias Java necessárias para colocar em prática parte dessas idéias. Será utilizado o Record Management System (RMS) para persistência de dados. As classes para comunicação via Internet e os Servlets para a implementação do servidor serão apresentados no próximo artigo da série.
O que mudou no Mobile Invaders? Da forma como foi concebido, o Mobile Invaders teve como objetivo a introdução de várias técnicas e arquiteturas indispensáveis para o desenvolvimento de jogos. Para adequá-lo às tecnologias que queremos apresentar neste artigo, tornou-se necessária à criação de novas funcionalidades. Para tanto, modificamos algumas partes do código, criamos algumas classes e acrescentamos algumas telas de menu. É hora de entender como o jogo ficou estruturado, quais foram as principais modificações e as novas regras.
As regras As regras do jogo se mantiveram as mesmas. Há uma nave controlada pelo jogador que tem como objetivo destruir todos os inimigos da tela. A quantidade de inimigos, sua velocidade e quantidade de tiros simultâneos aumentam à medida que o jogador passa para uma nova fase. Para que o jogo não fique muito
injusto, a quantidade de tiros da nave também aumenta, mas não sua velocidade (pois tornaria o jogo fácil demais). Os parâmetros que definem a dificuldade do jogo são facilmente editáveis e você pode alterá-los para tornar uma partida mais difícil caso ache que precise de um pouco mais de emoção. Altere-os e peça para que seus amigos joguem até que você perceba que o jogo atingiu um nível de dificuldade razoável. Para a alegria de uns e tristeza de outros, esse jogo não tem uma quantidade limite de fases. Isso mesmo, ele se enquadra na categoria dos jogos do bom e velho Atari. É claro que com um pouco mais de interatividade. Esse recurso é interessante, pois tende a aumentar o ciclo de vida do jogo, fazendo com que os jogadores continuem jogando para manter seu recorde, visto que não há limite para o número de pontos. De fato, o número máximo de pontos é dado por uma variável do tipo int, de 32 bits (cujo limite superior é 2.147.483.647), mas esse recorde nós garantimos que ninguém conseguirá alcançar! Ao terminar uma partida, o jogador somente registra seus pontos no Hall da Fama caso a sua pontuação seja alta o suficiente. Para simplificar, só são guardadas as cinco maiores pontuações, ou seja, você só armazena a sua pontuação caso ela seja maior que o menor dos recordes armazenados até então. O fluxograma da 1 ilustra todo o processo que envolve uma partida. Se ao fim da partida você bateu um recorde, é exibida uma tela em que é possível entrar com seu nome, como mostra a 2a. Nessa tela, escreve-se movimentando o botão direcional. Primeiro posiciona-se o cursor sobre uma das cinco posições possíveis, depois se escolhe o caractere movimentando o direcional para cima e para baixo. A posição selecionada tem a cor branca. Ao entrar com o seu nome, é exibida uma lista com os recordes locais ( 2b). Nesse ponto surge a pergunta: mas por que só é possível entrar com cinco caracteres para o nome? A resposta é simples, e quem já se aventurou a utilizar a classe Canvas para esse fim sabe disso. É muito complicado simular uma caixa de texto em Canvas, pois se devem capturar os eventos de tecla1. Fluxograma de todo o processo que do, pintar a letra digitada envolve uma partida.
56 2º Edição
wm02.indb 56
6/4/2005 22:24:12
Jogos
2. (a) Tela de inserção do nome e (b) tela de recordes locais.
na tela e movimentar o cursor. Lembre-se que é possível digitar várias letras com a mesma tecla de um celular, imagine a complicação de escrever na tela um simples “abc”. Bem, é um trabalho possível, mas desnecessário para a nossa finalidade. Fica a cargo do leitor tentar implementar uma caixa de texto em Canvas (ler 1).
1. Interface gráfica de alto nível Para a criação de telas de entradas de dados no MIDP, existem componentes de interface gráfica chamados de componentes de alto nível. Com eles, é possível criar itens de formulário, como caixas de texto, o que simplificaria e muito o trabalho acima. Contudo o estudo de interface de alto nível está fora do escopo desse artigo. Para aqueles que se interessarem, busquem informações sobre o pacote javax.microedition.lcdui.*, que contém todas as classes que representam os componentes de alto nível, além da classe Canvas (de baixo nível) que estamos utilizando.
Recordes Locais: exibe os cinco recordes armazenados localmente. Como já foi dito, esse armazenamento é feito utilizando-se o RMS (assunto deste artigo); Recordes On-line: exibe somente os cinco maiores recordes armazenados no servidor; Enviar Recorde Atual: envia somente o maior recorde local. Portanto, antes de submeter o seu recorde, verifique se ele realmente é alto o suficiente, caso contrário, ele nem será exibido ao selecionar a opção Recordes On-line; Local = On-line: torna os recordes locais iguais aos cinco maiores recordes on-line. As três últimas opções (Recordes On-line, Enviar Recordes atual e Local) somente serão vistas no próximo artigo da série no qual será explicada com detalhes a comunicação entre celular e servidor. Outra funcionalidade interessante foi a criação de várias fases. Quando todos os inimigos da tela são desativados, o método nextLevel() (não existente na primeira versão do artigo e que foi criado para atender a essa nova funcionalidade) da classe Engine é chamado. Esse método faz com que a thread de jogo entre no estado wait e altera os parâmetros que definem a dificuldade. O código da 1 mostra o método nextLevel(). A cada duas fases, incrementam-se as variáveis linesOfEnemies, enemyMaxBullets e playerMaxBullets, que correspondem a quantidade de linhas de inimigos, número máximo de tiros simultâneos dos inimigos e número máximo de tiros simultâneos do jogador,
1. Método nextLevel() da classe Engine. public void nextLevel(){ gameCanvas.novaFase = true;
As novas funcionalidades
fase++;
As principais características que deram interatividade ao jogo foram a contagem de pontos e o banco on-line de recordes. Para dar acesso a essas novas funcionalidades, foi criada uma opção no menu inicial chamada de Hall da Fama. No Hall da Fama, você encontra as seguintes opções, conforme apresentado na 3.
if(fase % 2 == 0){ linesOfEnemies++; maxEnemies = linesOfEnemies * ENEMIES_PER_LINE; enemyMaxBullets++; playerMaxBullets++; maxBullets = playerMaxBullets + enemyMaxBullets; } if(fase % 3 == 0){ enemySpeed++; } numeroDeInimigos = maxEnemies; enemyNumeroDeBullets = 0; createSprites(); System.gc(); }
3. Hall da Fama
WebMobile 57
wm02.indb 57
6/4/2005 22:24:15
respectivamente. A cada três fases, incrementa-se a variável enemySpeed que representa a velocidade vertical dos inimigos. As variáveis maxEnemies e maxBullets representam a quantidade máxima de inimigos e de tiros na tela a cada fase. numeroDeInimigos e enemyNumeroDeBullets são usadas para controlar a quantidade de inimigos e de tiros inimigos ativos. É nesse método que devem ser feitas as alterações para configurar o nível de dificuldade do jogo. Veja na 4 a evolução desses parâmetros da fase 1 para a fase 6. Após a execução desse método, a thread de jogo exibe o número da fase e espera até que o usuário dê continuidade ao jogo, como mostra a 5.
5. Início de uma nova fase.
Uma nota sobre jogabilidade Ao dar mais funcionalidades para o game, devemos nos preocupar com sua jogabilidade. Jogabilidade aqui não se refere somente ao que acontece durante uma partida, mas também ao modo como a aplicação interage com o usuário. Todas as modificações no estado do jogo devem ser comunicadas adequadamente e seguindo um padrão. Ao mudar de fase, o jogador é avisado e o jogo somente é reiniciado quando ele aperta no soft button “Continuar” ou quando ele começar a disparar contra os inimigos. Ao fim de uma partida, é exibida a mensagem de game over e o jogador deve optar por continuar. Não queremos que ele passe de fase ou que o jogo acabe sem que ele tenha conhecimento disso. Para implementar essa funcionalidade, a thread do jogo sofreu algumas mudanças, como mostra a 2. Antes de completar um loop, é verificado se o jogador apertou pause ou se passou de fase. Caso isso tenha acontecido, a thread entra no bloco sincronizado e conseqüentemente no estado wait. A thread de jogo sai desse estado quando é notificada pela thread que escuta os eventos do teclado, reiniciando o jogo (ler 2). O mesmo acontece quando o jogo acaba, e o segundo bloco de código sincronizado é executado dependendo de como a partida foi terminada. Somente é exibida a tela de Game Over caso o jogador tenha perdido. Se ele tiver desistido, a tela não será exibida.
4. Fase 1 x Fase 6
2. Dica de performance Queremos aqui pedir licença ao leitor para fazer um esclarecimento. Evite utilizar blocos sincronizados de código em aplicativos que necessitam de performance, muito menos dentro do método run da thread de um jogo. Resolvemos abrir uma exceção nesse caso pois os blocos sincronizados somente são executados nos momentos de mudança de fase, quando o usuário seleciona pause ou quando o jogo acaba. A verdade é que esse jogo não exige muito dos processadores dos smartphones e ficamos de certa forma livres para cometer alguns pecados de performance como esse. Ou seja, não leve essas dicas de performance ao pé da letra. Basta não abusar. Estabeleça padrões de desempenho para o seu jogo e faça o necessário para que ele fique dentro desses padrões.
Record Management System (RMS) Um ponto muito importante que se deve entender para desenvolver aplicativos J2ME/MIDP é o mecanismo chamado de RMS. Como diz a especificação, “O Mobile Information Device Profile provê um mecanismo para os MIDlets persistirem dados e recuperá-los depois. Esse mecanismo de armazenamento persistente é modelado sobre uma simples base de dados orientada a records e é chamada de Record Management System”. Records são os itens individuais de armazenamento. Eles representam a entidade básica do mecanismo de persistência. A API os trata como um array de bytes, portanto tudo que pode ser representado como uma seqüência de bytes pode ser armazenado, como todos os tipo primitivos, strings e imagens. Um record não tem um tamanho fixo ou limitado, o RMS aceita um array de bytes de qualquer tamanho (respeitando é claro o limite de memória não volátil disponível para a aplicação). Um conjunto de records forma um record store. A implementação do record store deve garantir que os records sejam recuperados ou armazenados atômica e sincronamente, sem a possibilidade de que eles sejam corrompidos por múltiplo acesso. Até certo ponto, podemos fazer uma analogia entre record stores e tabelas de um banco de dados relacional. A cada record
58 2º Edição
wm02.indb 58
6/4/2005 22:24:17
Jogos
criado, é associado um identificador único ou recordId. Esse identificador é usado como se fosse uma chave-primária para os records. Ao primeiro record criado é atribuído o recordId 1, ao segundo 2, e assim por diante. As analogias param por aí. Não é possível pré-definir campos e tipos para um record store como se faz para uma tabela de banco de dados. Pode-se até associá-lo a uma tabela com dois campos: um campo inteiro com o recordId (que é a chave-primária) e outro campo cujo tipo é um array de bytes. Também não é possível fazer relacionamentos entre os record stores. O escopo de um record store é limitado ao seu MIDlet suite (ver 3 para mais informações sobre MIDlet suite). Somente MIDlets de um mesmo suite podem compartilhar os dados de um record store. O MIDP 2.0 já permite que um record store seja compartilhado entre MIDlets situados em suites diferentes por meio de alguns parâmetros passados no momento da criação do record store.
3. MIDlet suite MIDlet suite nada mais é que uma coleção de MIDlets relacionados que podem ser tratados pelo dispositivo como uma entidade única. MIDlets de um mesmo suite podem compartilhar vários tipos de recursos como objetos em memória (uma vez que todos eles rodam na mesma máquina virtual) e record stores.
A quantidade de memória disponível para o RMS varia de plataforma para plataforma. Procure se informar sobre isso antes de desenvolver seu aplicativo. Vamos agora estudar o pacote javax.microedition.rms, verificar quais são as funcionalidades que ele nos oferece e como tudo isso foi utilizado no Mobile Invaders.
O pacote javax.microedition.rms O pacote javax.microedition.rms é composto de uma classe, quatro interfaces e cinco exceções, que compreendem toda a
tempo = System.currentTimeMillis()
2. Método run da thread de jogo. - inicio; /*
if (tempo > TICK) {
*Método run da thread do jogo. Chama o método engine.
continue;
atualizar() para atualizar
} else {
*os sprites. Repinta a tela. Espera o tick para manter o
try {
fps constante.
Thread.sleep(TICK - tempo);
*/
} catch (InterruptedException ie) {
public void run() {
}
while(!engine.gameOver) { } inicio = System.currentTimeMillis();
}
keyLocked = false;
/* *Exibe a tela de Game Over somente se o jogador não desistiu do jogo.
/*
*Caso ele não tenha desistido, exibe a tela de Game
*Verifica se o jogador apertou pause ou passou de
Over e espera que ele
fase e espera
*pressione continuar.
*até que ele pressione despausar ou continuar.
*/
*/
if(!quit){
if(paused || novaFase){
synchronized(this){
synchronized(this){
try{
try{
this.wait();
this.wait();
}catch(InterruptedException ex){}
}catch(InterruptedException ex){} }
} }
quit = false; }
engine.atualizar(); repaint();
mobileInvadersMidlet.displayMenu(engine.score);
serviceRepaints(); }
WebMobile 59
wm02.indb 59
6/4/2005 22:24:18
funcionalidade de gerenciamento do RMS. A classe RecordStore é o membro mais importante desse pacote. Com ela é possível criar, abrir, fechar e destruir record stores, além de realizar as operações de escrita, leitura e atualização de records. A interface RecordEnumeration mantém uma seqüência de records obtidos a partir de uma consulta. O tamanho dessa seqüência e a sua ordem podem ser alterados com o uso das interfaces RecordFilter e RecordComparator, que fornecem métodos para filtrar e ordenar os records de acordo com algum critério. RecordListener é uma interface utilizada para “ouvir” eventos associados a um Record Store. Toda a lógica de acesso e tratamento do RMS está na nova classe MobileInvadersScore e é baseado nela que iremos criar os exemplos para mostrar o funcionamento desse pacote.
A classe MobileInvadersScore A classe MobileInvadersScore usa o artifício de guardar em memória todos os recordes guardados no record store. Esses recordes são armazenados em arrays no momento em que é criado um objeto da classe. Uma vez inicializados, toda consulta é feita diretamente a eles. O objetivo é minimizar o impacto de performance que poderia ser causado pelo acesso contínuo ao record store. A base de dados somente é atualizada quando algum novo recorde é alcançado, como mostra o método addHighScore( ) na 3. Esse método se encarrega de verificar se a pontuação a ser guardada é maior que o mínimo necessário para entrar no Hall da Fama. Caso seja, ele chama o método saveRecord( ), que se encarrega de atualizar a base de dados com os novos valores dos arrays. O método saveRecord( ) será explicado em uma listagem mais adiante.
openRecordStore( ) na classe RecordStore. Existem mais dois métodos com este nome como podemos ver na 5. O primeiro método é usado para criar um record store que possa vir a ser acessado a partir de outro MIDlet suite. O parâmetro authmode diz se o record store tem acesso restrito ao suite ou não, e o parâmetro writable diz se os MIDlets de outro suite têm permissão para escrita. O segundo método abre um record store (que pode estar em outro suite) associado aos parâmetros vendorName e suiteName. O acesso é dado baseando-se no parâmetro authmode passado no momento da criação do record store. Ambos os métodos fazem parte do MIDP 2.0. Para fechar um record store, devemos usar o método closeRecordStore( ), como mostra a 6. 3. Adicionando um novo recorde. /** *
Armazena um novo score. Verifica se esse score é
*
antes de armazená-lo.
maior que lowestScore
* @param score recorde * @param name dono do recorde */ public void addHighScore(int score, String name){
int lowestScore = scores[0]; int index = 0;
for(int i = 1; i < NUM_RECORDS; i++){
Abrindo e fechando um RecordStore
if(scores[i] < lowestScore){
lowestScore = scores[i]; A classe RecordStore não possui construtores públicos. Deveindex = i; mos abrir ou criar um recorde store utilizando o método estático } RecordStore.openRecordStore( ), que retorna uma instância dessa } classe. A 4 mostra como esse método foi utilizado na classe MobileInvadersScore. Não se confundam, também foi criado um méif(score > lowestScore){ todo com nome openRecordStore( ) na classe MobileInvadersScore. scores[index] = score; Como pode ser visto, o último chama o primeiro. O método recebe names[index] = name; como argumento uma String, que representa o nome do record saveRecords(); store a ser aberto (ou criado) e um booleano createIfNecessary. } Caso esse último parâmetro seja passado como true, o record store } é criado se ainda não existir. Se já existir, ele apenas é aberto. Caso o parâmetro seja false, o record store somente é aberto, 4. Método openRecordStore( ) da classe MobileInvadersScore. e mesmo que ainda não exista, não é criado. Deve-se ter cui/** dado ao utilizar essa última * Abre o RecordStore ou o cria caso ainda não exista. opção, uma vez que o objeto */ retornado pode ser nulo caso private void openRecordStore() throwsRecordStoreException{ o record store ainda não tenha rs = RecordStore.openRecordStore(“MobileInvadersRS”, true); //rs é do sido criado. } Há uma sobrecarga do método
tipo RecordStore
60 2º Edição
wm02.indb 60
6/4/2005 22:24:20
Jogos
Escrevendo em um Record Store Dois métodos são utilizados para se escrever em um record store: addRecord e setRecord (ver 7). O método addRecord( ) é utilizado para inserir um novo record. A cada chamada desse método, um inteiro representando o identificador do record é retornado. Já o setRecord( ) é utilizado para sobrescrever um record, identificado pelo parâmetro recordId, com o conteúdo do array data. Não podemos nos esquecer que o RMS é uma base de dados orientada a records e que records são bytes. É de se esperar então que todos os dados a serem armazenados devam ser convertidos
em uma seqüência de bytes. No nosso caso, em cada record serão armazenados uma String com o nome do jogador e um inteiro com sua pontuação. Esse processo de escrita pode ser um tanto exaustivo e difícil, caso você tente serializar esses parâmetros sem nenhum auxílio (ler 4).
4. Recorde X Record Não confunda recorde com record. A palavra “recorde” está no português e significa a maior pontuação do jogo. Já “record”, no inglês, significa a entidade básica do mecanismo de persistência.
5. Variantes do método openRecordStore na classe RecordStore. public static RecordStore openRecordStore(String name, boolean createIfNecessary, int authmode, boolean writable) throws
RecordStoreException, RecordStoreFullException,RecordStoreNotFoundException
public static RecordStore openRecordStore(String name, String vendorName, String suiteName) throws
RecordStoreException,RecordStoreNotFoundException
6. Fechando um record store na classe MobileInvadersScore. /** *
Fecha o RecordStore.
*/ private void closeRecordStore() throws RecordStoreException{ if(rs != null){ rs.closeRecordStore(); //rs é do tipo RecordStore } }
7. Métodos para escrever em um Record store. public int addRecord(byte[] data, int offset, int numBytes) throws RecordStoreNotOpenException, RecordStoreException, RecordStoreFullException
public void setRecord(int recordId, byte[] data, int offset, int numBytes) throws RecordStoreNotOpenException, InvalidRecordStoreIDException, RecordStoreException, RecordStoreFullException
O pacote java.io do Connection Limited Device Configuration (CLDC) contém duas classes para este fim, ByteArrayOutputStream e DataOutputStream. De fato, o princípio utilizado para escrever em um record store é o mesmo usado para enviar pacotes pela rede, por exemplo. Se você já tem familiaridade com aplicações Java desse tipo, não deve sentir nenhuma dificuldade. A classe ByteArrayOutputStream é uma extensão da classe OutputStream, a qual escreve os dados diretamente para um array de bytes. O array é realocado sempre que necessário, de maneira a acomodar qualquer quantidade de bytes. A classe DataOutputStream provê mecanismos para escrever tipos primitivos diretamente para o output stream subjacente, passado no momento da construção. A 6 mostra como essas duas classes se relacionam. A 6 demonstra, por exemplo, qual seria o efeito da chamada do método writeUTF(“oi”) da classe DataOutputStream sobre o array. A idéia é usar um objeto DataOutputStream para preencher o array de bytes encapsulado por um objeto ByteArrayOutputStream de maneira adequada. Ao chamar writeUTF(“oi”) sobre alguma instância de DataOutputStream, não precisamos nos preocupar em como a string “oi” será convertida em uma seqüência de bytes. Perceba que, apesar da string ter apenas dois caracteres, o algoritmo de serialização utilizado pela classe DataOutputStream gerou 4 bytes ( 6): os dois primeiros dizem o tamanho da string e os dois últimos representam o seu conteúdo. A 8 descreve como aplicar esses conceitos. O método saveRecords( ) só é chamado no momento em que alguma alteração foi feita
WebMobile 61
wm02.indb 61
6/4/2005 22:24:22
para lê-la. A 10 mostra como os records da base de dados são lidos e armazenados nos arrays. A leitura deve obedecer à mesma ordem da escrita. No nosso caso, o inteiro deve ser lido antes da String.
8. Método saveRecords( ) da classe MobileInvadersScore. /** *
Salva os valores dos arrays no RecordStore.
*/ private void saveRecords(){
6. Estrutura do DataOutputStream e ByteArrayOutputStream. A figura mostra a seqüência de bytes que representam a string “oi”.
ByteArrayOutputStream baos = null; DataOutputStream dos = null; byte[] b = null;
nos arrays e o record store deve ser atualizado. Os valores contidos nos arrays são serializados nas linhas 3 e 4 ( 8), onde se escreve um inteiro com o método writeInt, e uma String com o método writeUTF, diretamente para o objeto baos criado na linha 1. Pode se recuperar a seqüência de bytes resultante desse processo (linha 5) e escrevê-la no record store (linha 6), sobrescrevendo o record cujo id é (i +1). Perceba que a contagem dos records se inicia no 1 e não no zero, como é caso dos arrays. Como somente cinco recordes podem ser armazenados, apenas os records com id’s de 1 a 5 são utilizados. Nunca se utiliza mais que cinco records nesse record store, por isso o usamos o método setRecord( ) para aproveitar as posições previamente criadas. Mas para aproveitar as posições já criadas, os records devem ter sido adicionados usando-se o método addRecord( ). Onde isso é feito? Ao criar um objeto da classe MobileInvadersScore, o trecho de código da 9 é executado. Na linha 1 ( 9) é verificado se o record store está vazio. Se estiver, cinco recordes default são adicionados. Esse bloco de código somente é executado se o record store acabou de ser criado. Assim, o método addRecord( ) (linha 2) é usado somente no momento em que o record store é criado, ou seja, quando se precisa preencher as cinco posições necessárias para guardar todos os recordes. A partir das próximas execuções, rs.getNumRecords( ) == 0 (linha 1) retorna false, e as cinco posições criadas no record store serão reutilizadas sempre que necessário usando-se o método setRecord( ).
try{
openRecordStore();
for(int i = 0; i < NUM_RECORDS; i++){ try{ baos = new ByteArrayOutputStream(); //linha 1 dos = new DataOutputStream(baos); //linha 2 dos.writeInt(scores[i]); //linha 3 dos.writeUTF(names[i]); //linha 4
b = baos.toByteArray(); //linha 5 }catch(IOException ex){
}finally{ try{ dos.close(); }catch(IOException ex){} }
rs.setRecord(i+1, b, 0, b.length); //linha 6 }
}catch(RecordStoreException ex){
}finally{
Lendo de um Record Store A leitura de um record store é um processo análogo à escrita. Há duas classes de apoio no pacote java.io chamadas ByteArrayInputStream e DataInputStream. Por exemplo, se você escreveu Strings utilizando writeUTF( ) da classe DataOutputStream, você deve utilizar o método readUTF( ) da classe DataInputStream
try{ closeRecordStore(); }catch(RecordStoreException ex){} } }
62 2º Edição
wm02.indb 62
6/4/2005 22:24:24
Jogos
A interface RecordFilter Ao executar uma consulta a um record store, devemos ser capazes de determinar quais serão os records retornados dessa consulta. No nosso jogo, poderíamos realizar um filtro, de maneira que na tela de recordes locais somente fossem exibidos os recordes do jogador FABIO ou os recordes que forem superiores a 10000, por exemplo. É exatamente esse o papel da interface RecordFilter. Para fazer um filtro, um dos parâmetros da consulta deve ser um objeto que implementa essa interface. Esse objeto deve implementar o método matches( ) abaixo, de modo que ele retorne true somente para os records que satisfizerem um determinado critério e false caso contrário.
9.Código da classe MobileInvadersScore. Primeiro trecho do método updateRecords( ), chamado pelo construtor. /** *
Atualiza os arrays.
*
Caso o RecordStore não tenha nenhum registro, insere 5 registros
*
default. Caso o RecordStore já tenha algum registro, atualiza os valores
*
dos arrays scores e names com os valores contidos nele.
*/ private void updateRecords(){
try{ openRecordStore(); if(rs.getNumRecords() == 0){ //linha 1 ByteArrayOutputStream baos = new ByteArrayOutputStream(); DataOutputStream dos = new DataOutputStream(baos); byte[] record = null;
public boolean matches(byte[] rec); //rec especifica um record do record store
try{ dos.writeInt(0);
A implementação do record store chama esse método para cada record armazenado, para verificar se ele fará ou não parte do retorno da consulta. Ele é o único método da interface RecordFilter. Retomando a analogia do banco de dados relacional, essa interface faz o mesmo papel do “WHERE” de uma query SQL. Apesar de bastante útil, não foi necessário filtrarmos nenhuma consulta no Mobile Invaders, uma vez que sempre são exibidos todos os cinco recordes armazenados.
dos.writeUTF(“AAAAA”); record = baos.toByteArray(); }catch(IOException ex){
}finally{ try{ if(dos != null){ dos.close(); } }catch(IOException ex){} }
for(int i = 0; i < NUM_RECORDS; i++){ rs.addRecord(record, 0, record.length); //linha 2
A interface RecordComparator Quando selecionamos a opção de Recordes Locais no Mobile Invaders, vemos que os recordes são exibidos em ordem decrescente ( 2). Será que temos que implementar
names[i] = “AAAAA”; }
}//fim do if
WebMobile 63
wm02.indb 63
6/4/2005 22:24:26
algoritmos de ordenação sempre que quisermos realizar uma consulta ordenada? A resposta é não. E é para isso que se utiliza a interface RecordComparator. Para ordenar os records, um dos parâmetros da consulta deve ser um objeto que implementa essa interface. Esse objeto deve implementar o método compare(), que recebe como parâmetro dois records, rec1 e rec2, a serem comparados. public int compare(byte[] rec1, byte[] rec2);
De acordo com o resultado da comparação, esse método deve retornar uma das três constantes seguintes: RecordComparator.EQUIVALENT, caso rec1 e rec2 sejam considerados iguais; RecordComparator.PRECEDES, se rec1 for comparativamente maior que rec2; RecordComparator.FOLLOWS, se rec1 for comparativamente menor que rec2.
10.Segundo trecho do método updateRecords( ) da classe MobileInvadersScore. else{
DataInputStream dis = null;
for(int i = 0; i < NUM_RECORDS; i++){ try{ dis = new DataInputStream(new
A implementação do record store chama esse método sempre que deseja comparar dois records armazenados, a fim de ordenálos no resultado da consulta. Ele é o único método da interface RecordComparator. Essa interface faz o papel do “ORDER BY” de uma query SQL. Utilizamos essa interface, como já foi dito, para que a consulta ao record store retornasse os records ordenados em ordem decrescente de pontuação. A 11 mostra como essa interface foi implementada pela classe MobileInvadersScore para cumprir com esse objetivo. Essa interface foi implementada de uma maneira um tanto interessante. A pontuação (que é um valor inteiro) guardada nos records passados, rec1 e rec2, são obtidas por meio de operações de deslocamento de bits. As operações das linhas 1 a 4 constroem as variáveis score1 e score2 a partir dos quatro primeiros bytes contidos nos arrays passados como parâmetro. Basta então compararmos esses dois valores para decidirmos se rec1 deve ser retornado antes ou depois de rec2. Mas por que utilizar essa abordagem de deslocamento de bits se os input streams podem facilmente retornar o valor inteiro contido nesses arrays de bytes? A resposta é simples, eficiência. Imagine que tenhamos 100 records que devem ser comparados e para cada comparação, um objeto ByteArrayInputStream e um objeto DataInputStream forem construídos. Com certeza, o código da 11 traz uma melhor opção de performance, pois evita a criação de objetos sempre que se deseja comparar dois records. Não se esqueça que nos encontramos num ambiente restrito de memória Heap. Deixamos para o leitor o exercício de implementar esse método usando os input streams.
ByteArrayInputStream( rs.getRecord(i+1))); scores[i] = dis.readInt(); names[i] = dis.readUTF(); }catch(IOException ex){
}finally{ try{ dis.close(); }catch(IOException ex){} } } } }catch(RecordStoreException ex){
}finally{ try{ closeRecordStore(); }catch(RecordStoreException ex){} } }
A interface RecordEnumeration Falamos até agora sobre como filtrar e ordenar uma consulta, mas de fato não falamos sobre como realizá-la ou sobre como utilizar os seus resultados. A interface RecordEnumeration representa uma coleção dos records retornados a partir de uma consulta a um record store. Além disso, ela provê métodos que tornam possível iterar sobre esses records: hasNextElement( ), hasPreviousElement( ), nextRecord( ) e previousRecord( ). Ela funciona de modo muito parecido com a interface Enumeration do J2SE, com a diferença de ser bidirecional. A 12 mostra como trabalhar com essa interface. O método nextRecord( ) retorna o record da posição x da enumeração e coloca o marcador na posição seguinte (x + 1). Na linha 2, hasNextElement( ) verifica se há um novo record na posição (x + 1) a ser lido. O método enumerateRecords( ) da classe RecordStore retorna uma enumeração que será construída de acordo com os três parâmetros passados, como mostra a linha 1. O primeiro parâmetro deve ser um objeto do tipo RecordFilter e o segundo, um objeto do tipo RecordComparator. Caso esses parâmetros sejam nulos, os records retornados não serão filtrados nem
64 2º Edição
wm02.indb 64
6/4/2005 22:24:27
Jogos
ordenados. O terceiro argumento diz se o RecordEnumeration deve ou não ser mantido atualizado com relação a quaisquer mudanças no record store. Se for true, toda mudança no record store será refletida na enumeração. Caso, por exemplo, a ordem dos records da enumeração seja importante para você, cuidado, pois quando novos records forem adicionados, eles ficarão desordenados dentro da enumeração, uma vez que essa já havia sido criada. Se for false, pode-se correr o risco de ter uma enumeração desatualizada, que já não reflete a verdade sobre a base de dados.
13. Iterando sobre os records. Método getHighestScores() da classe MobileInvadersScore. /** *
Retorna os recordes em ordem decrescente de
pontos. Usa-se as interfaces *
RecordEnumeration (para iterar sobre os registros)
e RecordComparator *
(para ordenar os registros).
* @return Retorna os recordes em ordem decrescente de pontos em um array de Record */
11. Método compare da interface RecordComparator implementado pela classe MobileInvadersScore.
public Record[] getHighestScores(){ RecordEnumeration re = null; DataInputStream dis = null;
/** *
Record[] recordes = new Record[NUM_RECORDS];
Método da interface RecordComparator usado para
int
ordenação dos records *
i = 0;
da interface RecordEnumeration. try{
*/
openRecordStore();
public int compare(byte[] rec1, byte[] rec2){
re = rs.enumerateRecords(null, this, false);
int score1 = 0, score2 = 0;
//linha 1 for(int i = 0; i < 4; i++){ while(re.hasNextElement()){ //linha 2
score1 = (score1 << 8); //linha 1
try{
score1 |= (rec1[i] & 0x000000ff); //linha 2
dis = new DataInputStream(new ByteArrayInputStream(re.nextRecord()));
score2 = (score2 << 8); //linha 3
//linha 3
score2 |= (rec2[i] & 0x000000ff); //linha 4
recordes[i] = new Record();
}
recordesi].score = dis.readInt(); recordes[i].name = dis.readUTF();
if(score1 == score2){
}catch(IOException ex){
return RecordComparator.EQUIVALENT; }else if(score1 > score2){
}finally{
return RecordComparator.PRECEDES;
try{
}else{
dis.close();
return RecordComparator.FOLLOWS;
}catch(IOException ex){}
}
}
} i++; } }catch(RecordStoreException ex){
12. Método compare da interface RecordComparator implementado pela classe MobileInvadersScore.
}finally{ re.destroy(); //linha 4
//re representa um RecordEnumeration re = rs.enumerateRecords(null, null, false);
try{
//linha 1
closeRecordStore(); }catch(RecordStoreException ex){}
while(re.hasNextElement()){ //linha 2
}
byte[] b = re.nextRecord(); }
return recordes; }
WebMobile 65
wm02.indb 65
6/4/2005 22:24:29
Nesse caso, podemos utilizar o método RecordEnumeration.rebuild( ) para atualizar uma enumeração já criada. A 13 mostra como a interface RecordEnumeration foi utilizada no Mobile Invaders. O método getHighestScores( ) retorna um array com cinco objetos da classe Record. Essa classe tem um atributo inteiro e uma string para encapsular a pontuação e o nome do pontuador. Esse array é preenchido com os valores retornados da consulta feita na linha 1 ( 13). Por meio dos parâmetros do método enumerateRecords( ), podemos ver que essa consulta retornará todos os elementos do record store ordenados pelo critério estabelecido pelo método RecordComparator.compare( ) da 11. Além disso, o RecordEnumeration retornado não deverá refletir todas as modificações do record store corrente, de acordo com o booleano false passado. Dentro do bloco while, verificamos se a enumeração ainda contém elementos (linha 2 – 13), obtemos um record e construímos um DataInputStream (linha 3 – 13) e preenchemos todos os elementos do array records. Quando o RecordEnumeration não for mais necessário, devemos destruí-lo, como mostra a linha 4 ( 13). Esse método é chamado pela classe MenuCanvas para exibir os recordes locais na tela.
Considerações finais sobre RMS Ainda existem dois pontos que merecem ser tratados. A interface RecordListener e a estrutura de exceções do pacote. O RecordListener, como o próprio nome diz, é um listener que escuta eventos associados ao record store. Seus métodos são: public void recordAdded(RecordStore rs, int recordId);
apesar de ser um mecanismo de persistência um tanto primitivo, é bastante simples e suficiente para atender ás necessidades de persistência de dados no MIDP. É necessário para tanto, ter conhecimento de algumas classes do pacote java.io. Ainda há várias outras funcionalidades que podem ser dadas ao jogo, como sons, vidas, bônus, etc. Encorajamos o leitor a tentar implementá-las. E não se esqueça. No próximo artigo da série, será explicada a parte de armazenamento on-line de recordes utilizando o Generic Connection Framework (J2ME/MIDP) e Servlets (J2EE). Não percam!
Agradecimentos Gostaria de agradecer e de parabenizar os professores Paulo Henrique Portela de Carvalho e Jorge Henrique Cabral Fernandes pelo grande trabalho desenvolvido dentro da Universidade de Brasília (UnB) e pelo sucesso do projeto Inova Mobile.
Databases and MIDP, Part 1: Understanding the Record Management System http://developers.sun.com/techtopics/ mobility/midp/articles/databaserms/ Databases and MIDP, Part 2: Data Mapping http://developers.sun.com/techtopics/mobility/ midp/articles/databasemap/ JSR-000118 Mobile Information Device Profile 2.0 (Final Release) www.jcp.org/aboutJava/communityprocess/ final/jsr118/
public void recordChanged(RecordStore rs, int recordId); public void recordDeleted(RecordStore rs, int recordId);
Esses métodos são chamados quando um record é adicionado, alterado ou removido de um record store. Assim como a interface RecordFilter, essa interface não foi necessária nos nossos exemplos. Quanto às exceções, o que vale a pena saber é que todas herdam de RecordStoreException. Portanto, se você um dia estiver com pressa ou um pouco cansado, pode dar um único catch para capturar as exceções desse pacote. As outras exceções são: InvalidRecordIdException, RecordStoreFullException, RecordStoreNotFoundException e RecordStoreNotOpenException. O próprio nome já é capaz de dizer o significado de cada uma. Bom, de RMS é só!
Fábio Mesquita Póvoa (fabio.povoa@gmail.com) Faz parte do Grupo Inova Mobile e é desenvolvedor Java especializado em aplicações J2ME/MIDP que usam tecnologia Bluetooth. Fábio desenvolve em Java há mais de dois anos e estuda engenharia nas horas vagas.O grupo Inova Mobile é formado por professores e alunos da Universidade de Brasília e é voltado para o desenvolvimento de aplicativos para o ambiente móvel, entre jogos, aplicações cliente-servidor e ferramentas (API`s) para auxílio no desenvolvimento.
Conclusões Vimos aqui como utilizar as principais classes e métodos do pacote javax.microedition.rms e como isso é capaz de dar um outro ânimo para os jogadores do Mobile Invaders. Vimos também que o RMS,
Faça o download no site: www.portalwebmobile.com.br/revista/ed2
66 2º Edição
wm02.indb 66
6/4/2005 22:24:35
Java
Conexão
HTTP com J2ME
Comunicando aplicações J2ME com servidores remotos por Robison Cris Brito
O
desenvolvimento de aplicações para celular utilizando o J2ME não é uma tarefa tão complicada. Porém, ainda esbarramos em um grande problema: na capacidade limitada de processamento e de armazenamento de informações. Uma alternativa viável é a utilização de servidores remotos para processar informações e armazenar dados em um repositório central, facilitando o acesso a informações que poderão ser feitos por outros mecanismos. Celulares e outros dispositivos móveis costumam fazer acesso a dados remotamente utilizando conexões OTA (Over the Air). Esta tecnologia é bastante deficiente, principalmente no que diz respeito à velocidade. Usuários que estão acostumados com conexões rápidas podem ficar entediados pela demora no tráfego de alguns KB. Além do mais, estas conexões podem ser pouco confiáveis e intermitentes. WebMobile 67
wm02.indb 67
6/4/2005 22:24:38
Entretanto, as empresas operadoras de telefonia móvel no Brasil estão em constante evolução, e já disponibilizam serviços em que é possível trafegar cada vez mais informações em conexões ininterruptas, pagando cada vez menos por este serviço, e ainda oferecendo uma maior abrangência territorial no país. O MIDP (profile Java utilizado no desenvolvimento de programas para celular) possui mecanismos genéricos para acesso à rede. Na MIDP 1.0, a conexão pode ser feita apenas por HTTP, através da classe HttpConnection (package javax.microedition.io) - outros protocolos poderiam ser utilizados de acordo com cada fabricante de celular. Já no MIDP 2.0, existem outras maneiras de estabelecer conexão, incluindo o HttpsConnection (HTTP sobre SSL), CommConnection (conexão serial), SocketConnection (permite conexão a um servidor socket) e ServerSocketConnection (inicia um servidor de socket e espera conexões externas). O presente artigo apresenta a comunicação entre um programa desenvolvido em J2ME e um servlet utilizando o protocolo HTTP (ver 1).
1. Características do protocolo HTTP HTTP (Hyper Text Transfer Protocol) é o protocolo de transferência de dados utilizado na web e é a base de toda sua funcionalidade. Leve e veloz, foi construído sobre o protocolo TCP/IP, sendo também orientado a conexão. Na verdade, o protocolo HTTP permite que dispositivos e browser conversem com os servidores web, façam pedidos e recebam as respostas em forma de texto através de uma conexão internet. A possibilidade de utilizar o protocolo HTTP está disponível desde a primeira versão do MIDP. A partir do MIDP 2.0 foi disponibilizado o recurso de conexão segura, o HTTPS.
os clientes. O servidor web hoje mais utilizado para executar servlet é o Apache Tomcat. Antes de desenvolver o servlet, será necessário instalar o Apache Tomcat na máquina servidora. O download do Tomcat pode ser feito no site http://jakarta.apache.org/tomcat/. A versão escolhida foi a 5.0.28. Após o download do arquivo jakarta-tomcat-5.0.28.exe, será necessário instalar o servidor. O processo de instalação não requer configuração especial, basta avançar todas as telas (ver 2). A instalação padrão configura o Tomcat na porta 8080, com o usuário admin e a senha em branco.
2. Instalação do Tomcat O foco deste artigo não é a instalação do Tomcat. Assim, abordamos apenas o básico para demonstrar a construção da aplicação exemplo.
Após a instalação, é necessário iniciar o serviço. Clique com o botão direito no ícone do Tomcat localizado ao lado do relógio e escolha a opção Start Service (ver 2). Para certificar-se de que o serviço foi iniciado, abra o browser e digite a seguinte URL: http://127.0.0.1:808. Feito isto, deverá ser exibida a tela da 3. Agora iniciaremos o desenvolvimento do servlet. Para isso, acesse a pasta onde foi instalado o tomcat, dentro da pasta webapp crie uma pasta com o nome de duke (duke será o contexto da aplicação no servidor) e, dentro dela, crie uma estrutura conforme a 4.
Arquitetura da aplicação Como vimos, o celular possui recursos limitados e para lidar com isso, podemos acessar recursos disponibilizados remotamente. Nessa situação, o celular seria um cliente que acessa serviços de um servidor (servlet) via conexão http. O servidor pode ser qualquer PC, desde que este tenha instalado um servidor web e possua um IP real. A 1 exemplifica o processo de comunicação celular/servidor. Foram selecionadas as seguintes ferramentas para o desenvolvimento desta infra-estrutura: o container servlet, que também funcionará como servidor web, foi o Tomcat; a IDE de desenvolvimento Java foi o Gel, disponível para download no endereço www.gexperts.com.br; a ferramenta de desenvolvimento J2ME foi o Wireles ToolKit e o sistema operacional Windows XP. Todas as ferramentas para o desenvolvimento são gratuitas e, com exceção do Gel, todos os outros programas possuem versões para Windows e Linux.
1. Diagrama contendo o fluxo de informação entre o aplicativo celular e o servidor.
Desenvolvendo o servlet – a aplicação servidora Servlet é um programa Java que estende a funcionalidade de um servidor web gerando conteúdo dinâmico e interagindo com
2. Ícone do Tomcat localizado na barra de tarefas do Windows.
68 2º Edição
wm02.indb 68
6/4/2005 22:24:41
Java
3.Página de configuração do Apache Tomcat 5.0.28
Pasta onde deve ser criado o arquivo web.xml Pasta onde deve ser criado o arquivo DukeServlet.java
4.Estrutura de diretório para o contexto duke onde será desenvolvido o servlet
Após definir a estrutura do diretório, deveremos criar uma classe com o nome DukeServlet. Abra o Gel e selecione a opção File New... Java File. Salve o arquivo na pasta webapps\duke\EB-INF\classes. O código fonte da classe DukeServlet segue na 1. A classe DukeServlet é simples e didática, tem a função de receber todas informações vindas do celular. Quando solicitado dados do servlet, será enviando o texto estático “Resposta Enviada”. Caso contrário, a mensagem que o celular está enviando será guardada no arquivo de log tomcat\logs\stdout.log. Segue a explicação do código utilizado no servlet: Na linha 8 é feita a definição do servlet DukeServlet que herda as funcionalidades da classe HttpServlet. Na linha 10 foi declarado o método público init() que é executado apenas no momento que o servlet for iniciado. Este método é útil para definir conexões com banco de dados, inicializar contadores, etc. Na seqüência, define-se o método destroy(), que será executado quando o servlet for retirado de execução. Fechar a conexão com o banco de dados é um exemplo do que pode ser executado neste método. A linha 18 possui a declaração do método doGet, que recebe todas as requisições feitas pelo celular. Na linha 22 configura-se o formato de resposta para “application/octetc-stream”, deixando o fluxo de dados mais rápido, pois nesse modo é retirada grande parte dos caracteres de controle que costumam ser enviado
19.
1. DukeServlet.java - Servlet responsável por receber dados do celular via HTTP.
20.
try {
21. 01. import java.io.DataOutputStream;
22.
02. import java.io.IOException;
response.setContentType( “application/octetc-stream” );
03.
23.
04. import javax.servlet.http.HttpServlet;
24.
DataOutputStream out = new DataOutputStream(
05. import javax.servlet.http.HttpServletRequest;
response.getOutputStream());
06. import javax.servlet.http.HttpServletResponse;
25.
07.
26.
08. public class DukeServlet extends HttpServlet
getParameter( “msg” ); 27.
09. 10.
public void init() {
28.
11.
//código que será executado quando o
29.
//servlet for iniciado
30.
}
31.
public void destroy() {
32.
//código que será executado quando o
33.
12.
String dados = request.
{
if ( dados.equals( “PegarDados” ) ) { out.writeUTF(“Resposta Enviada” ); } else { System.out.println( “Mensagem Recebida: “ + dados);
13. 14. 15.
16.
//servlet for finalizado
34.
}
35. 36.
17. 18.
public void doGet(HttpServletRequest request, HttpServletResponse response){
37.
}
} catch( IOException ioe ) { System.out.println( “Erro de IO”); } } // fim do método doGet
38. } // fim da classe DukeDuck
WebMobile 69
wm02.indb 69
6/4/2005 22:24:45
com as mensagens, fazendo com que seja trafegado apenas informações úteis. Logo abaixo é associado um objeto da classe DataOutputStream ao fluxo de saída de dados do servlet. É definida, na linha 26, a String dados que receberá o valor do parâmetro “msg” enviado pelo celular. Este parâmetro funciona como um protocolo. Se a mensagem que chegar for “PegarDados”, então o servlet envia informação para o celular utilizando o método writeUTF (na linha 29 envia o texto estático “Resposta Enviada”). Caso o valor do parâmetro seja diferente de “PegarDados”, então é armazenado as informações no log do sistema através do comando System.out.println(). O arquivo de log se encontra na pasta logs dentro da pasta Tomcat. Por fim, na linha 34 são tratadas as exceções IOException que podem ser geradas pelo servlet. Após codificar a classe DukeServlet, o próximo passo é criar manualmente o arquivo web.xml (ver 2) e adicioná-lo à pasta WEB-INF (ver 4). O web.xml contém informações que detalham o funcionamento do nosso Servlet. Tratando-se de um arquivo XML, sua estrutura é divida em campos (tags). O campo servlet traz o nome que deverá ser utilizado para fazer referência a esse servlet (<servlet-name>) e o nome da classe que possui o servlet (<servlet-class>). Já o campo <servlet-mapping> possui o caminho onde o servlet foi gravado na pasta WEB-INF/classes (<url-pattern>). Com isso, o aplicativo servidor está pronto. É importante frisar a necessidade de reiniciar o contexto da aplicação toda vez que for modificado e compilado o servlet DukeServlet. Para isso, acesse o browser e digite http://127.0.0.1:8080/manager/html. Para reiniciar o contexto duke, localize-o na tela e clique no botão reload.
Desenvolvendo o aplicativo para celular – a aplicação cliente No desenvolvimento do aplicativo que roda no celular foi utilizado o Wireless Toolkit. A versão instalada foi a 1.0.4_02.
2. Descritor web.xml contendo o mapeamento gerado para servlet DukeServlet. 01. <web-app> 02.
<servlet>
03.
<servlet-name>DukeServlet</servlet-name>
04.
<servlet-class>DukeServlet</servlet-class>
05.
</servlet>
06.
<servlet-mapping>
07.
<servlet-name>DukeServlet</servlet-name>
08. 09.
<url-pattern>/DukeServlet</url-pattern> </servlet-mapping>
10. </web-app>
É possível baixar esta ferramenta no site http://java.sun.com/ products/j2mewtoolkit. A instalação não exige nenhuma configuração, é só avançar todos os passos. Após a instalação, acesse o programa Wireless ToolKit pelo atalho KToolBar que se encontra no menu de programas. Em seguida, clique no botão New Project... e preencha o campo com o nome do seu projeto e o nome da classe principal. Nesse exemplo, o projeto e a classe principal se chamarão MidletDuke. Feito isto, clique em Create Project. A tela que aparece em seguida disponibiliza informações detalhadas do projeto (por exemplo, versão do MIDP utilizado – ver 4). Essas informações ficarão disponíveis no arquivo .JAD (ver 3).
3. Arquivos .JAD e .JAR Um dos itens mais curiosos quando se fala de programação para celular é sobre como são gerados os programas e como são instalados no aparelho. Após o processo de criação do aplicativo, é necessário transformá-lo em um formato compatível com os aparelhos celulares: o formato é o JAR (Java Archive). Ele agrupa todas as classes utilizadas para o desenvolvimento e pode conter vários KB. Hoje existe uma grande variedade de aparelhos celulares no mercado e por este motivo, um aplicativo que funcione bem num modelo pode não ser apto a rodar em outro, por possuírem diferentes características físicas, como versão do MIDP, display, entrada de dados ou conexão com a rede. Para evitar a situação de levar vários minutos fazendo o download da aplicação e ela não ser compatível com o aparelho, é gerado um arquivo JAD (Java Application Descriptor), muito menor que o JAR, que possui as características da aplicação. Assim, quando se deseja baixar o aplicativo para o celular, é feito o download do arquivo JAD, se for verificado a compatibilidade com o modelo a ser instalado, inicia-se então o download do arquivo .JAR.
4. MIDP A maioria dos celulares suporta a versão 1.0 da MIDP, que é bem limitada. Entretanto, este cenário está se modificando e já existem alguns modelos que suportam a MIDP 2.0. Este possui diversos recursos de segurança como HTTPS e novos recursos multimídias, utilizados principalmente para desenvolver jogos. Neste artigo serão utilizados apenas recursos básicos do MIDP 1.0 para garantir a compatibilidade com a grande maioria dos celulares existentes no mercado brasileiro.
Após a confirmação no OK, o projeto será criado. Automaticamente é incluído um diretório com o nome do aplicativo dentro do Wireless ToolKit (c:\WTK104\apps\MidletDuke), conforme 5. Vale lembrar aqui que o programa que estamos desenvolvendo é didático e bastante simples. Trata-se de um formulário com um componente caixa de texto (TextField) e dois comandos (Command’s), com as funções de enviar e receber informações do servidor. As informações enviadas devem ser digitadas na caixa de texto; as informações recebidas também são exibidas na mesma caixa de texto. Será adicionada também uma String na tela que
70 2º Edição
wm02.indb 70
6/4/2005 22:24:47
Java
mostrará o status da conexão. A 6 apresenta a tela do aplicativo, exibida no emulador do WTK usando o layout “genérico” do WTK 1.0.4. Para a codificação do sistema, abra o editor de código Gel e escolha a opção Java New... Java File. Feito isto, grave o código fonte no diretório src do seu projeto e não esqueça que o nome da classe deve ser o mesmo utilizado na criação do projeto. A 3 apresenta o código do programa que será executado no celular. As classes HttpConnection e Connector são responsáveis pela conexão HTTP. Na linha 15 é declarada a classe MidletDuke, que herda as informações de MIDlet, que o transforma em um aplicativo para celular, e implementa o CommandListener, responsável pela manipulação do evento das teclas de comando do celular. Da linha 18 a linha 22 são declarados os componentes visuais do aplicativo. O método startApp() é chamado quando o
aplicativo for iniciado. Nele é criado o objeto display (tela do celular), é chamado o método montarTelaInicial() que formatará a tela de acordo com o layout da 6 e a adicionará no objeto display. O método pauseApp() é chamado quando, por exemplo, o aplicativo está sendo executado e chega uma ligação para o aparelho. O método destroyApp() faz com que o aplicativo libere a memória e passe o controle novamente para o software de controle do celular. O método commandAction() (linha 51) é executado toda vez que o usuário pressionar um botão de comando no celular. Neste método será verificado qual Command foi pressionado. Se for o Command cmdEnviar, será executado o método passarInformacaoServlet() (linha 60). Se for escolhido o Command cmdReceber, será executado então o método pegarInformacaoServlet () (linha 82). No método passarInformacaoServlet(), a conexão HTTP é criada nas linhas 63 e 64, onde é definido um objeto “com” do tipo HttpConnection. Este objeto é criado a partir do método Connector.open(). Para a conexão é passada a seguinte String: http://127.0.0.1:8080/duke/DukeServlet?msg=”+ tf.getString(). replace(‘ ‘, ‘+’ ) ) ;
Local onde deve ser criado o arquivo MidleDuke.java
5. Estrutura de diretório para a aplicação MidletDuke.
6. Aplicativo sendo executado no emulador do WTK 1.0.4.
onde: http será o protocolo utilizado. 127.0.0.1 é o IP no qual será efetuada a conexão (localhost). O IP 127.0.0.1 só é válido nos testes (emulador). Na prática, é necessário que o Tomcat e o servlet desenvolvido estejam instalados em um servidor que possua IP real; caso contrário, acontecerá um erro de conexão. 8080 é a porta padrão do Tomcat. Esse número pode alterar de acordo com a instalação do servidor ou definição de suas configurações. /duke é o contexto onde foi instalado/codificado o servlet. /DukeServlet é o nome do servlet que foi desenvolvido na 1. ?msg= envia um parâmetro com o nome de msg via URL. Este parâmetro será recebido pelo servlet ( 1 - linha 26). tf.getString().replace(' ', '+' ): esta função retornará o conteúdo digitado na caixa de texto do aplicativo efetuando a substituição de espaços em branco pelo sinal de mais (+). O servlet já faz o processo inverso automaticamente quando receber a mensagem. Após a conexão, é necessário testar seu status para verificar se ocorreu algum erro. Na linha 65 foi criada uma variável int status, que recebe o código de retorno da conexão através do método con.getResponseCode(). Se o código for igual à constante HttpConnection.HTTP_OK (código 200), significa que a mensagem foi recebida com sucesso pelo servlet e a String situação WebMobile 71
wm02.indb 71
6/4/2005 22:24:51
3. MidletDuke.java - Midlet que será instalado no celular.
50. 51. public void commandAction( Command c, Displayable d ) {
01. import javax.microedition.lcdui.Display; 02. import javax.microedition.lcdui.Form;
52.
03. import javax.microedition.lcdui.TextField;
53.
04. import javax.microedition.lcdui.Command;
54.
passarInformacaoServlet();
05. import javax.microedition.lcdui.CommandListener;
55.
} else if ( c == cmdReceber ) {
06. import javax.microedition.lcdui.Displayable;
56.
07.
57.
08. import javax.microedition.midlet.MIDlet;
58. }//fim do método commandAction()
09. import javax.microedition.io.HttpConnection;
59.
10. import javax.microedition.io.Connector;
60. private void passarInformacaoServlet() {
11.
61.
12. import java.io.InputStream;
62.
13. import java.io.IOException;
63.
if ( c == cmdEnviar ) {
pegarInformacaoServlet(); }
try { HttpConnection con = (HttpConnection)Connector.open(
14. 15. public class MidletDuke extends MIDlet 16.
64.
“http://127.0.0.1:8080/duke/ DukeServlet?msg=” +
implements CommandListener {
tf.get String().replace(‘ ‘, ‘+’ ) ) ;
17. 18. private Display display;
65.
int status = -1;
19. private Form tela;
66.
String situacao = “”;
20. private TextField tf;
67.
status = con.getResponseCode();
21. private Command cmdEnviar;
68.
22. private Command cmdReceber;
69.
situacao = (status != HttpConnection.HTTP_ OK?”Erro: Conexão”:”OK” );
23. 24. public void startApp() {
70.
25.
display = Display.getDisplay( this );
71.
26.
montarTelaInicial();
72.
montarTelaInicial();
27.
display.setCurrent( tela );
73.
tela.append( situacao );
28. }
74.
display.setCurrent( tela );
29.
75.
30. public void pauseApp() {
76.
31. //método chamado na pausa da aplicação
77.
32. }
78.
33.
79.
} catch (IOException e) {
}
34. public void destroyApp( boolean b ) {
80. } //fim do método passarInformacaoServlet()
35.
display.setCurrent( null );
81.
36.
this.notifyDestroyed();
82. private void pegarInformacaoServlet() {
37. }//fim do método destroyApp()
83.
StringBuffer mensagem = new StringBuffer();
38.
84.
String situacao = “”;
39. private void montarTelaInicial() {
85.
try {
40.
tela = new Form( “HTTP Sender” );
86.
41.
tf = new TextField( “Texto: “, null, 20,
42.
cmdEnviar = new Command( “Enviar”, Command.ITEM, 0 );
43.
cmdReceber = new Command( “Receber”,
TextField.ANY );
Command.ITEM, 0 );
87.
“http://127.0.0.1:8080/ duke/DukeServlet?msg =PegarDados”);
88.
int status = -1; status = con.getResponseCode();
44.
tela.append( tf );
89.
45.
tela.addCommand( cmdEnviar );
90.
46.
tela.addCommand( cmdReceber );
91.
47.
tela.setCommandListener( this );
92.
48.
HttpConnection con = (HttpConnection) Connector.open(
93.
if (status == HttpConnection.HTTP_OK) { InputStream is = con.openInputStream(); int lido = is.read();
49. }//fim do método montarTelaInicial()
72 2º Edição
wm02.indb 72
6/4/2005 22:24:53
Java
Continuação 94.
lido = is.read();
95.
lido = is.read();
96.
while (lido != -1) {
97.
byte b1 = (byte) lido;
98.
mensagem.append( (char ) b1 );
99.
lido = is.read();
101.
}
102.
situacao = “OK”;
103.
} else {
104.
situacao = “Erro:Conexão”;
105. 106.
} } catch (IOException ioe) {
107. 108.
situacao = “Erro:IO”; }
109.
montarTelaInicial();
110.
tf.setString( mensagem.toString() );
111.
tela.append( situacao );
112. 113.
display.setCurrent( tela ); } //fim do método pegarInformacaoServlet()
114. 115.} //fim da classe MidletDukeContinuação
receberá o texto “OK”. Se ocorrer algum erro na conexão (status diferente de HttpConnection.HTTP_OK), a variável situacao recebe “Erro: Conexão”. Depois de verificado o status da conexão, é chamada a rotina montarTelaInicial() e adicionada a String situacao na tela. Para receber informações do servlet, é chamado o método pegarInformacaoServlet(). A estrutura para fazer a conexão com o servidor é a mesma utilizada no método passarInformacaoServlet() (linha 86). Porém, estamos enviando o parâmetro msg com o conteúdo “PegarDados”. Este parâmetro será tratado na 1 - linha 28. Logo após executar o método Connector.open, é testado o status da conexão (linha 91) e, se ocorreu algum problema na conexão, a String situacao é valorizado com “Erro: Conexão”. Caso o status seja HttpConnection.HTTP_OK, é criado um fluxo de entrada de dados (InputStream) e declarada uma variável inteira “lido”. A variável lido foi definida como inteira pois o método read() do InputStream retorna int. Na seqüência, são ignorados os dois primeiros bytes (linhas 93 e 94) e na linha 95 é recebido o primeiro byte da informação. Feito isto, é executado um looping até que o fluxo de informações enviadas pelo servidor (lido igual a -1) seja finalizado. Cada informação recebida é transformada em byte e, em seguida, em caractere (char). Este é concatenado ao StringBuffer chamado mensagem. Se tudo ocorreu bem, a variável situacao recebe o status “OK”, é executado o método montarTelaInicial() (linha 109), e adicionada a mensagem recebida na Caixa de Texto e a situação da conexão na tela.
Pronto. Depois de codificado, é necessário compilar o programa e executar no emulador. O botão Build do KToolbar tem a função de compilar o aplicativo e o botão Run executa no emulador.
Erros comuns no desenvolvimento Como estamos trabalhando com um sistema cliente / servidor, é necessário que os dois aplicativos estejam trabalhando em sincronismo, e também que as ferramentas do cliente (WTK) e do servidor (Tomcat) estejam configuradas corretamente. Seguem alguns erros comuns: Esquecer de iniciar o servidor Tomcat; Instalar o Tomcat com a porta diferente de 8080, e deixar a porta padrão na String de conexão; Esquecer de compilar o servlet ou o midlet; Modificar o código do servlet, compilar a classe e esquecer de reiniciar o contexto da aplicação; A String de conexão é case-sensitive. Sugiro verificar como foi criado o contexto, a classe ou os argumentos da aplicação. Este é um dos erros mais comuns; Esquecer de criar o arquivo web.xml, criá-lo com letras maiúscula ou colocar o arquivo na pasta errada; Errar o IP da máquina onde o Tomcat está instalado; Ter um firewall ou ter instalado o ServicePack2 da Microsoft para Windows XP pode gerar problemas, pois estas ferramentas costumam bloquear portas, inclusive a do Tomcat (8080).
Dicas importantes Gostaria também de deixar aqui algumas dicas para quando estiver desenvolvendo suas aplicações: Sempre que utilizar acesso remoto, tenha uma thread no aplicativo cliente (celular) para isso, pois o acesso toma tempo e pode se estender por vários minutos; Mantenha algum tipo de indicação de progresso para o usuário (um componente Gauge por exemplo); Use Get ao invés de Post, pois é mais simples e não precisa se preocupar com os request header; Tenha certeza que as exceções estão sendo tratadas adequadamente, capture-as e mostre mensagens informativas para o usuário; Redes wireless não são muito confiáveis. Prepare o aplicativo para o pior (rede não disponível) exibindo mensagens explicativas ou repetindo tentativas de conexão. Libere memória e recursos assim que possível, em dispositivos portáteis os recursos são escassos. WebMobile 73
wm02.indb 73
6/4/2005 22:24:54
Conclusões A utilização do protocolo HTTP é uma alternativa fácil e eficaz para troca de informações entre o celular e um servidor remoto. No exemplo deste artigo foi transmitido apenas texto em ambas as direções. Contudo, é comum encontrar programas que enviam uma série de informações coletadas durante o dia para o armazenamento em um banco de dados remoto, ou manipulação on-line de dados que se encontram no servidor. O uso de XML para o envio e o recebimento de informações não é uma alternativa interessante. Utilize-a apenas quando for extremamente necessária, pois códigos XML possuem um grande número de caracteres para o controle da informação (tags) e eles devem ser transmitidos juntamente com as mensagens. Com isso, o número de bytes que trafegam na rede aumenta, e conseqüentemente, aumenta o tempo de transmissão dos dados e o custo da transmissão. No site www.dukeduck.com.br e www.devmedia.com.br/web mobile (neste último você também encontrará os arquivos da aplicação utilizada como exemplo nesta matéria) é possível fazer o download do código de um programa que utiliza HTTP e possuí vários recursos. Trata-se de um cadastro de clientes, onde o usuário manipula os dados localmente no celular, armazenando-os no RMS (Record Manager System) com as opções de importar/ exportar os dados do celular para um servidor remoto, onde está instalada uma base de dados.
Sobre o container web Tomcat jakarta.apache.org/tomcat Sobre o Gel - editor de código Java www.gexperts.com Sobre a Wireless ToolKit - ferramenta de desenvolvimento J2ME java.sun.com/products/j2mewtoolkit Tutoriais e códigos J2ME www.dukeduck.com.br Robison Cris Brito (robison@pb.cefetpr.br) É especialista em desenvolvimento web e professor do Centro Federal de Educação Tecnológica do Paraná - CEFET-PR, onde ministra aulas de Java e Sistemas Distribuídos, foi palestrante do JustJava 2004 e é um dos líderes do DukeDuck - Grupo de Usuários Java de Pato Branco/PR.
Faça o download no site: www.devmedia.com.br/webmobile/
74 2º Edição
wm02.indb 74
6/4/2005 22:24:58
PDA’s
Desenvolvimento
PalmOS utilizando
PocketStudio por Marcio Alexandroni
O
desenvolvimento para PalmOS tem se tornado cada vez mais popular e simples de ser realizado devido ao avanço tecnológico nesta área aliado ao surgimento de diversas ferramentas simples de serem utilizadas e que apóiam esse desenvolvimento. Nesta edição abordaremos assuntos relacionados à escolha de uma ferramenta de desenvolvimento para PalmOS. Serão apresentadas noções básicas sobre recursos do PalmOS e o artigo será finalizado com a construção de uma aplicação de exemplo que utiliza diversos conceitos relacionados ao PalmOS, tais como banco de dados, através da ferramenta PocketStudio.
Noções sobre desenvolvimento PalmOS Antes de iniciar o desenvolvimento no sistema operacional PalmOS, é bom que o desenvolvedor se acostume com algumas características e, principalmente, algumas limitações desta plataforma. Primeiramente, o desenvolvedor deve ter atenção especial com o desenho dos formulários. Quando houver necessidade de campos para entrada de dados, é interessante deixar uma opção na aplicação para apresentar o teclado virtual do Palm automaticamente, agilizando a entrada de dados. Nem todos os usuários se acostumam facilmente à entrada de dados Graffiti do Palm (reconhecimento de escrita). Outra característica importante no desenho dos formulários consiste em dispor os dados em formulários seqüencialmente permitindo navegação rápida, visto que o PalmOS não permite uso de barra de rolagem nos formulários para expandir sua área visual. Algumas aplicações que simulam este recurso na verdade utilizam um objeto visual chamado “Table” do PalmOS para entrada de dados. Como exemplo de utilização deste recurso, temos a aplicação de gerenciamento de contatos do Palm (Address Book). O uso de listas de itens, quando possível, é a melhor solução para seleção de dados pelos usuários. Um erro comum de todo desenvolvedor iniciante no mundo PalmOS é pensar em substituir uma aplicação desktop por uma aplicação Palm, ou de carregar o equipamento com dezenas de bancos de dados com milhares de registros. O sistema operacional PalmOS possui limite de registros por banco de dados; suporta apenas 65505 registros por banco de dados em memória. Vale ressaltar aqui que um “banco de dados” no Palm é equivalente a uma “Tabela” como é conhecida tradicionalmente no desenvolvimento para aplicações que executam no Windows. Assim, não adianta querer transferir para o Palm sua tabela de Clientes com 100.000 registros. As aplicações para o Palm devem ser desenvolvidas visando complementar sistemas corporativos, e não substituí-los. Apesar disto, o equipamento requer que os dados sejam transferidos de alguma forma entre o sistema da empresa e o Palm, o que é chamado de sincronismo de dados. Se o sincronismo de dados for local, onde o Palm é ligado diretamente ao desktop, a transferência WebMobile 75
wm02.indb 75
6/4/2005 22:25:13
de milhares de registros será demorada, mas viável. Se a única opção disponível para transferência de dados for a remota, via modem de linha convencional ou celular, devemos considerar também o custo envolvido na comunicação. Recomendamos que o desenvolvedor dimensione os dados que devem ser manipulados pela aplicação no Palm, utilize o menor número de informações possível e faça uso de informações sintéticas quando aplicável. Exemplo: ao consultar a posição financeira de um Cliente, é necessário que todos os registros de duplicatas vencidas e a vencer sejam transferidos para o Palm? Não seria possível trabalhar com um período menor para consulta? Melhor ainda, não seria possível trabalhar apenas informações sintetizadas e consolidadas para a análise? Uma outra limitação a que o desenvolvedor deve estar atento é que o PalmOS não possui índice, chave primária e relacionamento em seus bancos de dados. Isto implica em um trabalho a mais para o desenvolvedor, principalmente em consultas que envolvem critérios de busca variados. Existem bancos de dados comerciais como o Oracle Lite e IBM DB2 que amenizam um pouco estas limitações do sistema operacional, mas são pouco utilizados em virtude do custo, geralmente cobrado por usuário Palm. Por fim, um outro conceito que sempre confunde os iniciantes na plataforma é o suporte de “arquivos”. No PalmOS, tudo o que se transfere para a memória do equipamento são “bancos de dados”. Até mesmo as aplicações Palm, arquivos que no Windows têm extensão PRC, são armazenados em forma de um “banco de dados” na memória do Palm. O sistema operacional não suporta arquivos, TXT, JPEG e BMP dentre outros. O que tiver que ser transferido para a memória do equipamento deve ser feito embutindo o conteúdo em um banco de dados Palm (arquivos com extensão PDB no Windows) antes de enviá-lo ao equipamento. Arquivos podem ser gravados no cartão de expansão de memória, mas é necessário que a aplicação saiba como tratar estes arquivos e utilizar as funções do sistema operacional para abri-los e manipulá-los.
Escolha da ferramenta
pode ser lenta se a ferramenta de desenvolvimento gerar uma aplicação em código intermediário e se utilizar de um “runtime” (interpretador de comandos utilizado por algumas ferramentas) para executar a aplicação. Algumas ferramentas possuem conjuntos de executáveis “runtime” que ultrapassam 1 MB (um valor bastante alto). Suporte aos recursos do equipamento e sistema operacional. Como regra geral, as ferramentas que geram código nativo (sem uso de “runtimes”) suportam acesso a todas as funções do sistema operacional PalmOS. Isto as tornam “flexíveis” fazendo com que possam ser empregadas em qualquer tipo de aplicação suportada pelo equipamento Palm. Já as ferramentas que têm “runtime” podem estar limitadas aos recursos disponíveis no próprio runtime. Um exemplo de limitação é o acesso a bibliotecas de comunicação de dados como SyncAnywhere (compactação e comunicação FTP, www.cialogica.com.br) e ASTA (acesso remoto online a bancos de dados relacionais, www.astawireless.com), bibliotecas de impressão (PrintBoy – www.bachmannsoftware.com e PalmPrint – www.stevenscreek.com), suporte a equipamentos proprietários como GPS (www.garmin.com) e integração com máquinas industriais para coleta de dados. No pior caso, o “runtime” pode não ter suporte ao acesso às bibliotecas externas. Já nas ferramentas que suportam acesso às funções da API do PalmOS, mesmo que o suporte de uma biblioteca à ferramenta ainda não esteja disponível, as bibliotecas podem ser facilmente adaptadas para funcionar com a ferramenta. A 1 apresenta um quadro comparativo das ferramentas de desenvolvimento PalmOS mais utilizadas no Brasil.
Desenvolvendo com PocketStudio 2 O PocketStudio é a ferramenta de desenvolvimento mais utilizada atualmente no Brasil, escolhida principalmente por desenvolvedores que necessitam de flexibilidade para construir todo tipo de aplicação para o Palm, desde as tradicionais aplicações com bancos de dados até aplicações que se comunicam com equipamentos industriais ou GPS. Há muitas razões pela qual os desenvolvedores preferem o PocketStudio: IDE similar ao Delphi, com a mesma nomenclatura e disposição de janelas; Gera executáveis pequenos, rápidos e nativos da plataforma Palm, sem uso de "runtime";
Escolher a ferramenta ideal para desenvolvimento PalmOS requer um pouco de atenção do desenvolvedor. Assim como em outros sistemas operacionais, o PalmOS também dispõe de um número grande de ferramentas e cada uma delas possui suas características. Ao analisarmos ferramentas devemos ter em mente alguns aspectos como: Curva de Ferramenta Preço US$ Runtime Flexibilidade Performance da aplicação. No Windows não Aprendizado CodeWarrior 499 Não Grande Lenda precisamos nos preocupar com o tamanho do arGCC-sem IDE Grátis Não Grande Lenta quivo executável, pois temos memória facilmenPocket Studio 2 69 e 249 Não Grande M[edia te expansível, farto local para armazenamento e J2ME Grátis + 300k Média Média processadores cada vez mais velozes para execu+ 500k Média Média SuperWeba R$ 1350 p/ano tar a aplicação. No PalmOS é diferente, o equi1000 +600k Média Rápida Crossfire 150 +100k Média Rápida NSBasic pamento é um PDA (assistente pessoal digital) 995 +100k Média Rápida Satelite Forms e apesar de alguns modelos terem processado1. Quadro comparativo das ferramentas de desenvolvimento PalmOS mais utilizadas no Brasil. res relativamente velozes, uma aplicação ainda 76 2º Edição
wm02.indb 76
6/4/2005 22:25:17
PDA’s
Possui acesso a toda as funções do sistema operacional PalmOS, o que significa que não há limites nos tipos de aplicações que podem ser desenvolvidas. Tudo o que a plataforma Palm suporta pode ser desenvolvido com o PocketStudio; O formato do banco de dados é aberto. Isto significa que o desenvolvedor tem totais condições de utilizar os vários tipos de tecnologias disponíveis para sincronismo nos bancos de dados gerados pelo PocketStudio, como Conduits com o uso do HotSync, bibliotecas de FTP para compactar, transmitir e receber bancos de dados Palm como o SyncAnywhere (www.cialogica.com.br) e até mesmo comunicação online e em tempo real com bancos de dados relacionais (Oracle, SQL Server, Interbase, Firebird, entre outros) utilizando as bibliotecas de comunicação Smart Client Toolkit da ASTA (www.astawireless.com).
que é um modo de controlar as implementações e correções que você deve fazer na sua aplicação. Clicando com o botão direito do mouse sobre a janela você verá comandos para adicionar (Add), editar (Edit) e apagar (Delete) entradas na To-Do-List. No centro, o editor de código do PocketStudio (detalhe E da 1), onde cada unit é representada por uma aba a partir do canto superior esquerdo da janela. No canto direito está a janela Object Inspector (detalhe F da 1), acessível pela tecla F11. Nesta janela podem ser configuradas as propriedades dos objetos visuais como formulários, botões, campos de edição, etc. O Object Inspector possui duas abas, a Properties e a Events. Elas são dedicadas à configuração das propriedades (Properties) e para inserção de códigos de eventos no objeto (Events).
A curva de aprendizado da ferramenta é considerada de nível médio, pois a linguagem utilizada no PocketStudio é a Pascal procedural. A relação custo/benefício da ferramenta compensa o tempo de aprendizado. É comum desenvolvedores que optaram anteriormente por outras ferramentas necessitarem reescrever suas aplicações em ferramentas mais poderosas como o PocketStudio devido a problemas com o “runtime” de suas ferramentas ou a limitações encontrada durante o desenvolvimento ou aprimoramento da aplicação. Caso você não tenha baixado a versão Trial do PocketStudio, acesse www.winsoft.sk/Trial/PStudioTrial.aspx e preencha o formulário. A WinSoft, desenvolvedora do produto, lhe enviará um e-mail com informações de download da versão Trial do PocketStudio.
Para iniciar, é interessante criar um diretório na sua máquina para armazenar o novo projeto que será criado. Selecione o menu File New Application (ler 1). Um projeto padrão será criado contendo dois arquivos fonte (duas units). A unit Project contém os códigos de inicialização e gerenciamento de eventos globais da aplicação, e a unit1 contém a declaração do formulário criado automaticamente pelo projeto e seus códigos de tratamento de eventos do form e objetos associados a ele. Salve as units do projeto como descrito abaixo: Para a unit1.pas, salve com o nome uFrmPrincipal.pas. Não podemos salvar a unit somente com o nome FrmPrincipal. pas se quisermos que o objeto Form dentro da unit se chame FrmPrincipal. Este é o motivo da utilização do "u" antes do nome da unit. Para o Project.ppr, dê o nome Cadastro.ppr. O arquivo PPR é o arquivo de projeto da aplicação. Ele contém os códigos de
O ambiente do PocketStudio 2
Criando um novo projeto
Na 1 você pode notar a semelhança do ambiente do PocketStudio com outros ambientes de desenvolvimento já bastante utilizados. No canto superior (detalhe A da 1) esquerdo do ambiente está localizada a janela Code Explorer, onde as Procedures da unit, definições dos objetos visuais declarados na unit (Resources), as units referenciadas na Uses Clause (Uses) e das constantes definidas (Constants) podem ser acessadas mais rapidamente. Logo abaixo da janela Code Explorer, está localizada a janela Project Manager (detalhe B da 1), onde as units do projeto são relacionadas. No canto inferior esquerdo está a janela Messages (detalhe C da 1) onde as mensagens e erros de compilação e status de execução da aplicação no emulador são mostrados. No canto inferior direito está a janela 1. Ambiente do PocketStudio 2. To-Do-List (lista de tarefas) (detalhe D da 1),
WebMobile 77
wm02.indb 77
6/4/2005 22:25:36
inicialização e finalização de uma aplicação, além do tratamento dos eventos globais para a aplicação.
1. Criando ícones para aplicações Palm. Cuidado ao criar ícones para o Palm, é necessário respeitar a quantidade de cores máxima suportada. Com o sistema operacional até a versão 4.1, podemos ter no máximo 256 cores. Os ícones grandes devem ter tamanho de 32x32 pixels, mas somente os primeiros 22 pixels na vertical devem ser preenchidos (o motivo é explicado mais abaixo, no item APPICONNAME). Os ícones pequenos devem ter 15x9 pixels e todos os pixels podem ser preenchidos. Adicionalmente, para Palms com sistema operacional cuja versão seja 5 ou superior, é possível adicionar mais um conjunto de ícones coloridos cujo ícone grande deve ter 64x64 pixels, mas somente os primeiros 44 pixels na vertical devem ser preenchidos. Os ícones pequenos devem ter 30x18 pixels e todos os pixels podem ser preenchidos. O PalmOS identifica automaticamente qual o melhor ícone para ser apresentado no Launcher para a sua aplicação em função do equipamento no qual a aplicação está sendo executada. Se for um equipamento com tela monocromática, o ícone em branco e preto será apresentado.
Configurações do projeto Quando o projeto é criado, algumas configurações são colocadas automaticamente no código fonte do projeto. É interessante alterá-las para adaptá-las às suas necessidades. As configurações básicas do projeto ficam no arquivo do projeto, o Cadastro.ppr. Abra este arquivo no editor de código e realize as configurações conforme descrito abaixo. Localize a linha {$CREATOR 'appl'} logo abaixo da cláusula program no código fonte. No PocketStudio, existem algumas diretivas de compilação que são feitas através de entradas como esta, ou seja, com o uso de {$CONFIGURAÇÃO VALOR}. A entrada {$CREATOR 'XXXX'} configura o CreatorID para a aplicação. CreatorID é uma informação extremamente importante para qualquer aplicação pois não pode haver duas aplicações instaladas no Palm com o mesmo CreatorID. Ele é um identificador único de quatro caracteres alfanuméricos que identifica quem criou a aplicação. Quando criar sua aplicação e for distribuí-la para Palms que podem ter muitas aplicações instaladas, você deve registrar um código de CreatorID para sua aplicação no site da PalmSource. Se os Palms onde sua aplicação irá rodar forem executar apenas a sua aplicação, não há necessidade de registrar o CreatorID, coloque qualquer identificador. Outras diretivas de compilação do PocketStudio que podem ser colocadas logo após a linha que configura o CreatorID são: {$BACKUPFLAG ON}: Marca o flag de backup na aplicação, indicando que o HotSync fará backup da sua aplicação para o desktop. {$BACKUPFLAG OFF}: Desmarca o flag de backup da aplicação, indicando que o HotSync não fará backup da sua aplicação para o desktop. {$COPYPREVENTIONFLAG ON}: Marca o flag que não
permite que a aplicação seja enviada por Beam para outro Palm. Atenção, isto não garante que a aplicação não será copiada, pois existem softwares gratuitos para download no site www.palmgear.com, como o FileZ, que permitem desmarcar e marcar qualquer flag dos softwares instalados no Palm. {$COPYPREVENTIONFLAG OFF}: Desmarca o flag que não permite que sua aplicação seja enviada por Beam para outro Palm. {$HIDDENFLAG ON}: Informa ao Launcher do PalmOS que a aplicação não deve ser mostrada na lista de programas do Launcher. {$HIDDENFLAG OFF}: Default. A aplicação aparece na lista de programas do Launcher do Palm. Mais abaixo, localize a entrada Resource. Há algumas configurações importantes que podemos realizar neste local: VERSION 1 '1.0': indica que sua aplicação terá a versão 1.0 gravada no programa gerado. Você pode alterar esta informação para a versão que achar necessário. O número 1 após a palavra VERSION é o identificador do Resource (ResourceID) e você não precisa mudá-lo. APPICONNAME 1000 'Project': é o nome que aparece sob o ícone da aplicação, no launcher do Palm. O motivo de você poder usar menos pixels na vertical nos ícones grandes é o fato do PalmOS desenhar o AppIconName logo abaixo do ícone, nos pixels inferiores. Mude o nome Project para Cadastro, este é o nome que será apresentado para nossa aplicação no Launcher do Palm. O número 1000 depois da palavra APPICONNAME é o identificador do Resource (ResourceID) e você não precisa mudá-lo. ICON 1000 'IconLBW.bmp' 'IconLC.bmp': indica os ícones grandes utilizados pela sua aplicação (o número 1000 após a palavra ICON não deve ser mudado pois identifica os ícones grandes). Note que estão colocados os dois arquivos de ícones, preto e branco, e colorido. Se você criar seus próprios ícones para a aplicação, mude o nome dos arquivos neste local. Para aplicações que serão executadas em Palms com versão 5 ou superior, é possível acrescentar mais um ícone com alta resolução (64x64) na lista de imagens com a cláusula DENSITY 144 DIRECTCOLOR, exemplo: ICON 1000 'IconLBW.bmp' 'IconLC. bmp' 'IconLHC.bmp' DENSITY 144 DIRECTCOLOR. ICON 1001 'IconSBW.bmp' 'IconSC.bmp': indica os ícones pequenos utilizados pela sua aplicação (o número 1001 após a palavra ICON não deve ser mudado, pois identifica os ícones pequenos). Note que estão colocados os dois arquivos de ícones, preto e branco, e colorido. Se você criar seus próprios ícones para a aplicação, mude o nome dos arquivos neste local. Para aplicações que serão executadas em Palms com versão 5 ou superior, é possível acrescentar mais um ícone com alta resolução (30x18) na lista de imagens com a cláusula DENSITY 144 DIRECTCOLOR, exemplo: ICON 1001 'IconSBW.bmp'
78 2º Edição
wm02.indb 78
6/4/2005 22:25:38
PDA’s
'IconSC.bmp' 'IconSHC. bmp' DENSITY 144 DIRECTCOLOR; Definição da categoria no Launcher: o Launcher do Palm pode separar as aplicações em categorias para melhor visualização. A lista de categorias do Launcher fica no canto superior direito do Launcher conforme mostrado na 2.
de uma unit .PAS para que a multi-segmentação seja possível. Problemas com segmentação de código são causados pela limitação do PalmOS em tratar segmentos grandes de código. É o mesmo limite que os antigos PCs tinham quando foram lançados em 1990 (antigos PC-XT).
2. Launcher do PalmOS.
Você pode mudar a categoria na qual sua aplicação aparece no Launcher ou mesmo criar a sua própria utilizando a entrada abaixo logo após a última linha da cláusula Resource no arquivo fonte PPR: LAUNCHERCATEGORY 1000 'ClubePDA';
Onde: LAUNCHERCATEGORY indica que você irá mudar a categoria na qual sua aplicação irá aparecer. 1000 é o número do Resource. Você pode usar este valor em todas as suas aplicações. ClubePDA é o nome da categoria que sua aplicação será colocada. Se esta categoria não existir no Launcher, ela será criada automaticamente. Existem configurações do projeto que podem ser feitas pelo menu Project Options (ver 3). Em Code Generation estão as principais configurações de compilação do projeto: Debug information prepara sua aplicação para aceitar Breakpoints e Watches para que um debug seja realizado. Com esta aplicação desmarcada, os Breakpoints não serão aceitos ou respeitados. Quando você gera uma aplicação com Debug information, códigos especiais de debug para o emulador são acrescentados no código gerado, portanto ela não pode ser executada no Palm ou diretamente no emulator, somente a partir do ambiente do PocketStudio! Multiple segments deve ser marcada quando sua aplicação tiver mais de 32KB de código gerado. O compilador do PocketStudio lhe avisará que a aplicação tem mais de 32KB de código gerado com a mensagem Code segment too large: exceds 32K. Neste momento, basta você marcar a opção Multiple segments e o compilador irá segmentar sua aplicação automaticamente. Se mesmo assim a mensagem continuar aparecendo, significa que há alguma (uma ou mais) unit na sua aplicação com muitas funções, cujo código gerado da unit esteja ultrapassando 32KB. Neste caso, divida as funções da unit em mais
Em Other: Show hints faz o compilador mostrar dicas de performance da sua aplicação e variáveis não utilizadas quando a aplicação é compilada. Show warnings faz o compilador mostrar avisos importantes quando compila. Application flags são os flags que podem ser configurados na aplicação. Estes flags são análogos às diretivas de compilação explicadas anteriormente. Em Directives, o campo Conditionals serve para definir rótulos, separados por ';' (ponto-e-vírgula), que podem ser testados dentro da aplicação. Por exemplo: XYZ;ABC. Assim você pode usar na aplicação o comando de compilação condicional: {$ifdef XYZ} // Códigos que só serão compilados se o rótulo XYZ estiver definido. {$endif} .... {$ifdef ABC} // Códigos que só serão compilados se o rótulo ABC estiver definido. {$endif}
Em Directories, o campo Output especifica um diretório onde o executável da sua aplicação será gerado.
3. Configurações do projeto.
WebMobile 79
wm02.indb 79
6/4/2005 22:25:41
Editando o formulário da aplicação
Adicionando código na aplicação
Uma das vantagens do PocketStudio é contar com um editor de objetos visual acessível pela tecla F12. Para acrescentar objetos visuais no formulário, basta selecionar o objeto desejado na barra de componentes e clicar com o mouse na área do formulário. Para alterar as propriedades visuais dos objetos, basta selecioná-lo e utilizar o Object Inspector, acessível pela tecla F11. A 4 mostra o formulário da aplicação exemplo deste artigo. Selecione os objetos e veja como eles foram declarados no Object Inspector, este será um bom exercício para que você aprenda a trabalhar facilmente com o editor visual do PocketStudio 2. Todos os objetos possuem eventos acessíveis através da aba “Events” no Object Inspector. Para incluir código nos eventos, basta clicar duas vezes ao lado do nome do evento e o protótipo do evento é criado automaticamente. A 5 mostra a função de tratamento de evento de seleção do botão “Novo” da aplicação exemplo.
Depois de criada a parte visual da aplicação, é necessário iniciar a codificação das units e funções da aplicação. O primeiro passo para criar uma aplicação que usa bancos de dados no PocketStudio é criar uma unit contendo a definição do banco de dados, sua estrutura e campos. Fizemos isto criando a unit ClientesDB.pas, cujo código completo está descrito na 1. Para abrir bancos de dados, recomendamos que o código seja colocado na função StartApplication, definida no arquivo principal do projeto (PPR). Para fechar os bancos, o local ideal é na procedure StopApplication, definida no mesmo arquivo fonte. Se você se esquecer de abrir um banco de dados, sua aplicação apresentará erros durante a execução e se esquecer de fechá-los, o Palm será resetado na próxima execução da sua aplicação. A 2 apresenta a unit PPR completa. A recuperação e configuração dos dados nos objetos visuais do formulário são feitas através do uso das units da biblioteca PocketStudio Library (PSLibrary), documentada no help da ferramenta e que abordaremos oportunamente nas próximas edições da WebMobile. A recuperação de dados de campos é feita pelo comando PSField.Text e a configuração dos dados através do comando PSField.SetText. Já para as listas, o comando de recuperação dos dados é o PSList.Selection para recuperar o texto do item selecionado ou PSList.SelectionIndex para recuperar o índice
4. Edição visual de formulário e Object Inspector.
5. Código de tratamento de evento de seleção do botão “Novo”.
80 2º Edição
wm02.indb 80
6/4/2005 22:25:44
PDA’s
selecionado na lista. Para configurar o item selecionado na lista, o comando é o PSList.SetSelectionIndex. Para compilar a aplicação utilize CTRL+F9. No diretório do projeto você encontrará o arquivo com extensão PRC que representa a aplicação compilada. Caso queira transferir a aplicação compilada para o seu equipamento Palm, não se esqueça de desmarcar a opção Debug Information (ver 3) nas configurações do projeto antes de compilar. O código completo da unit do formulário criado neste artigo estará disponível juntamente com este exemplo para download no site da revista. Faça o download, estude-o e teste a aplicação no seu equipamento Palm. É possível também executar a aplicação e fazer debug passo a passo a partir do PocketStudio, utilizando para isso o POSE – PalmOS Emulator. Para obter o PalmOS Emulator, acesse o site 1. Definição do banco de dados de Clientes.
www.palmos.com/dev/tools/ emulator/. Nesta página você encontrará informações de como efetuar download do executável e se cadastrar para ter acesso às ROMs que são necessárias para configurar o emulador. A execução da aplicação no emulador é demonstrada na 6. 6. Aplicação executada no emulador.
Conclusões
Como vocês puderam ver, a criação de aplicações em PocketStudio é simples e a similaridade do ambiente com ambientes de desenvolvimento amplamente
implementation
Unit ClientesDB; interface
// Abre ou Cria o banco de dados
uses PSL;
function Open : Boolean; begin // Tenta abrir o banco de dados
const
Result := PSDatabase.Open(
ClienteDBName = ‘ClientesDB’; // Nome do Banco de Dados
DBCli, ClienteDBName, dmModeReadWrite);
ClienteDBType = Rsc(‘DBCL’); // DatabaseType do Banco de Dados
if not Result then // Índices para recuperação e configuração dos valores
begin
// nos Campos do Banco de Dados de Clientes
// Se não conseguir, tenta criá-lo
ClienteCodigo = 0;
Result := PSDatabase.CreateDatabase( ClienteDBName, Creator, ClienteDBType);
ClienteNome = 1;
if Result then
ClienteEndereco = 2; ClienteBairro = 3;
// Depois de criado, abre o banco de dados
ClienteCidade = 4;
Result := PSDatabase.Open(DBCli, ClienteDBName, dmModeReadWrite);
ClienteUF = 5; end;
ClienteCep = 6;
// Se não conseguiu abrir nem criar o banco de dados, retorna
var // Definição da Seqüência e tipo dos campos
// erro
FieldDefs: array [0..6] of TFieldDef =
if not Result then
(
begin ShowSystemError(PSDatabase.LastError);
(DataType: ftUInt16),
// ClienteCodigo
(DataType: ftString),
// ClienteNome
(DataType: ftString),
// ClienteEndereco
(DataType: ftString),
// ClienteBairro
(DataType: ftString),
// ClienteCidade
// Configura a estrutura dos campos do banco de dados
(DataType: ftString),
// ClienteUF
PSDatabase.SetFieldDefs(DBCli, FieldDefs[0],
(DataType: ftString)
// ClienteCep
);
Exit; end;
SizeOf(FieldDefs) div SizeOf(FieldDefs[0])); end;
// Variável para controle de inclusão/alteração no registro ClienteInclui: Boolean;
// Fecha o banco de dados function Close : Boolean;
// Variável que armazena a referência ao banco de dados aberto DBCli : TDatabase;
begin Result := PSDatabase.Close(DBCli); end;
function Open : Boolean; function Close : Boolean;
end.
WebMobile 81
wm02.indb 81
6/4/2005 22:25:49
2. Unit principal do Projeto (PPR). program Cadastro(Cmd: Word; CmdPBP: Pointer; LaunchFlags: Word): LongWord;
var FormID: UInt16; Form: FormPtr; begin Result := False;
{$CREATOR ‘CBPD’}
if Event.eType = frmLoadEvent then begin
uses
FormID := Event.frmLoad.formID;
PSL,
Form := FrmInitForm(FormID);
uFrmPrincipal in ‘uFrmPrincipal.pas’,
FrmSetActiveForm(Form);
ClientesDB in ‘ClientesDB.pas’;
case FormID of FrmPrincipal: FrmSetEventHandler(
resource
Form, uFrmPrincipal.HandleEvent);
VERSION 1 ‘1.0’;
end;
APPICONNAME 1000 ‘Cadastro’; ICON 1000 ‘IconLBW.bmp’ ‘IconLC.bmp’; ICON 1001 ‘IconSBW.bmp’ ‘IconSC.bmp’; function StartApplication: Boolean; begin // Abre ou cria o banco de dados de Clientes // Se ainda assim falhar, não executa a aplicação if not ClientesDB.Open then begin Result := False; Exit; end;
Result := True; end end; procedure EventLoop; var Event: EventType; Error: UInt16; begin repeat EvtGetEvent(Event, evtWaitForever); if not SysHandleEvent(Event) then if not MenuHandleEvent(nil, Event, Error) then if not ApplicationHandleEvent(Event) then
// Apresenta o formulário principal da aplicação FrmGotoForm(FrmPrincipal); end;
FrmDispatchEvent(Event); until Event.eType = appStopEvent; end;
procedure StopApplication; begin
begin // Fecha o banco de dados de Clientes ClientesDB.Close;
if Cmd = sysAppLaunchCmdNormalLaunch then if StartApplication then begin EventLoop;
// Fecha o formulário ativo da aplicação
StopApplication;
FrmCloseAllForms;
end;
end; function ApplicationHandleEvent(var Event: EventType): Boolean;
utilizadas ajuda os desenvolvedores que já possuem experiência na construção de softwares. Quer mais? Veja o tamanho do executável gerado para esta aplicação, o arquivo PRC no diretório do projeto tem pouco mais de 10K! Nas próximas edições traremos mais informações sobre desenvolvimento PalmOS com PocketStudio. Até lá!
Faça o download no site: www.portalwebmobile.com.br/revista/ed2
end.
Marcio Alexandroni (marcio@clubepda.com.br) é Analista de Sistemas com 15 anos em experiência em TI. Pós-graduado em Oracle pela FIAP/SP, atua no segmento de tecnologia móvel desde 1998 criando soluções para empresas e ferramentas para desenvolvedores pela Cialogica (www.cialogica.com), empresa que dirige. Pelo ClubePDA (www.clubepda.com.br) ministra cursos, palestras e consultorias na ferramenta PocketStudio para empresas e desenvolvedores.
82 2º Edição
wm02.indb 82
6/4/2005 22:25:58
wm02.indb 83
6/4/2005 22:26:08
VEM AÍ A REVENDA LOCAWEB. LANÇAMENTO EM MAIO Para você - desenvolvedor - é uma ótima notícia. A LocaWeb está trabalhando para lançar mais um serviço que irá facilitar muito a sua vida. A Revenda LocaWeb. Com ela, você poderá oferecer soluções completas e flexíveis para seus clientes e com toda a qualidade e segurança da maior empresa de hospedagem do Brasil. Por tudo isso, vale a pena esperar.
wm02.indb 84
6/4/2005 22:26:14 CARILLO
REVISTA