Tutorial : Symbian C++ : (UI e Estrutura da Aplicação) : Parte 02

1. Introdução

Na primeira parte desse tutorial foram introduzidos alguns conceitos sobre o sistema operacional Symbian e sua linguagem de programação correspondente chamada de Symbian C++. Nessa segunda parte, irei abordar um pouco mais sobre a estrutura de uma aplicação e como montar uma aplicação que explora os recursos gráficos do Sistema Symbian.
Esse artigo está dividido em seções. Na primeira seção, será descrita a estrutura de arquivos de forma mais aprofundada. A segunda seção aborda o tópico da arquitetura de uma aplicação no Symbian. Já a terceira parte é um exemplo para demonstrar os conceitos de uma arquitetura tradicional e seus elementos. No fim, concluímos com algumas breves considerações e a exibição de um aplicativo gráfico funcional para um celular série 60.

2. Arquitetura de uma aplicação

Para o desenvolvimento de aplicações com interface gráfica no Symbian, funcionalidades quem em outras plataforamas de desenvolvimento podem ser agrupadas em um único arquivo ou classe são separadas desde do início da sua concepção. Alguns exemplos dessas funcionalidases são o ponto de entrada da aplicação, a lógica da aplicação, o gerenciamento de eventos e as interfaces gráficas. Isso facilita a tarefa de separar a lógica de um programa da sua parte visual. No entanto, infelizmente, isso torna o entendimento de uma aplicação gráfica em Symbian mais difícil.

As aplicações com interface gráfica geralmente apresentam diversas funcionalidades no Symbian como: Exibir graficamente informações para o usuário e permitir a interatividade; responder a eventos iniciados pelo usuário e pelo sistema; ter a capacidade de salvar e recuperar os dados da aplicação; identificar-se unicamente para o sistema operacional; exibir informações sobre a aplicação para o sistema operacional; etc. Existe um conjunto básico de classes que formam a aplicação e algumas classes do sistema devem herdar tais classes a fim de obter as funcionalidades básicas para o funcionamento da aplicação. As classes que compõem a arquitetura da aplicação que provêem estas funcionalides são divididas nessas categorias: Application, Document, AppUi e View.

A classe Application tem uma função fixa e bem definida, que é de servir somente como ponto de entrada da aplicação e disponibilizar informações sobre a aplicação para o sistema operacional como o ícone e o nome da aplicação que deve aparecer no gerenciador de aplicativos, e o UID (Unique Identifier Number - número que identifica as aplicações Symbian) da aplicação. Esta classe tem um papel estático - ela não se envolve com os dados da aplicação ou com sua lógica.

A classe Document provê um contexto para a persistência dos dados da aplicação. Esta classe contém métodos para instanciar a classe de AppUI.

A classe AppUI é um repositório para várias notificações vindas do sistema operacional, como eventos de teclado ou de sistema. Esta classe irá gerenciar a forma como a aplicação irá tratar esse eventos, despachando para o View que deveria receber a notificação desse evento( por exemplo: a tela do formulário é a tela que deveria ser avisada (View) de que o usuário finalizou o preenchimento desse formulário (AppUI é quem avisa).

A View é uma representação dos dados da aplicação na tela. Ela não é uma categoria de classe de forma restrita. Existem diversas formas de se fazer o View na série 60, e serão demonstradas no decorrer desse tutorial.


Image:Classediagrama.JPG

Este diagrama demonstra de forma simples as classes que formam uma aplicação.

  • Application - Retorna o ponteiro da classe documento e o UID3 da aplicação.
  • Document - Realização a criação da Interface do Usuário (AppUi).
  • AppUI - Manipula eventos do teclado e é responsável pela criação do View.
  • View - Responsável por exibir controles para o usuário.

3. O framework

O framework do sistema operacional é a forma de como uma aplicação interage com o próprio sistema. Quando se deseja, por exemplo, finalizar uma aplicação, o sistema operacional se comunica com a aplicação por meio desse framework. Ele é formado por um conjunto de classes básicas que forma a base para todas as aplicações. Essas classes formam a estrutura necessária e encapsulam a comunicação entre a aplicação e o sistema operacional. O diagrama abaixo, também disponível nesse link, mostra as 4 camadas de classes do framework simplifcado para facilitar o entendimento.

Image:Derivacoesclasse.JPG

Figura 1: Arquitetura do Framework

A primeira camada é dividida em dois componentes fundamentais: o AppArc (Application Architecture) e o CONE (Control Enviroment). As classes no AppArc provêem a estrutura básica da aplicação e os mecanismos para retornar ao sistema as informações sobre essa aplicação e sobre os dados persistentes. Esse é um componente do Symbian e suas classes tem o nome iniciado com o prefixo "Apa", como CApaApplication.
As classes no componente CONE provêem mecanismos básicos para gerenciar a entrada de dados pelo usuário e criar a interface gráfica. Esse também é um componente do Symbian, e suas classes tem o nome iniciado por "Coe", como em CCCoeControl.

A segunda camada de classes pertence ao componente Uikon, também chamado de Eikon. Este componente contém implementações de interfaces gráficas que são consideradas independentes de plataforma dos diversos recursos existentes no Symbian. As classes desse componente têm o nome iniciado por "Eik", como em CEikApplication.

A terceira camada de classes é uma implementação das interfaces gráficas do Uikon para Séries 60. Ela é chamada de Avkon. A escolha de qual implementação (Avkon ou Uikon) suas classes deverão herdar é uma questão de projeto importante e deverá escolhida baseado em algumas considerações descritas posteriormente nesse tutorial.

A quarta camada é a camada específica da aplicação, e demonstra como você poder derivar as classes básicas de modo a construir a sua própria aplicação.

A maior parte das classes da primeira camada são abstratas, definindo apenas as assinaturas das funções que serão posteriormente utilizadas pelo framework. A segunda camada adiciona implementações comuns ao Symbian e já a terceira adiciona implementações específicas parao Série 60. Por fim a quarta adiciona as implementações específicas da sua aplicação.

As classes que compõem a última camada - Application, Document, AppUI e AppView serão detalhadas nessa próxima seção.


4. Classe Application

A classe da aplicação deve derivar de CEikApplication ou outra classe que derive desta, por exemplo CAknApplication) . Existem duas funções que devem ser implementadas por esta classe. A primeira função, CreateDocumentL() é utilizada para criar um documento, e por isso, deve retornar um objeto do tipo CApaDocument. A segunda função a ser implementada é a AppDllUID() e deverá identificar a aplicação, retornando seu UID. 'Na figura abaixo tem uma implementação comum dessa classe. Bom frisar a definição de uma constante estática KUidMyFirstProjectApp que deve conter estritamente o mesmo valor encontrado no arquivo mmp da aplicação (o arquivo de propriedades do projeto). Esse valor é retornado pela funçao AppDllUID(), o qual identifica a aplicação para o sistema operacional. Já a função CreateDocumentL() é utilziada para criar um documento padrão.
A grande parte das aplicações Symbian que utilizam esse framework já implementam de forma padrão as funções abaixo. Essa imposição faz parte do framework, ou seja essas funções devem estar definidas na sua aplicação e devem realizar estas ações. Esse é o comportamento esperado pelo sistema operacional de qualquer aplicação Symbian.

Figura 2: MyFirsProjectApplication.cpp



5. Classe Document

A classe Document deve derivar de CeikDocument (ou de uma classe que deriva desta, como, CAknDocument) . Em geral, esta classe instancia a lógica da aplicação e cria um objeto do tipo AppUI por uma chamada ao método CreateAppUil(). O AppUi é necessário para manipular os eventos do sistema. Como pode-se ver nessa classe, ela tem uma estrutura muito bem definidia, sendo pouco flexível assim como a classe Application. Eles devem obedecer a um comportamento específico, não sendo permitidos desvios deste comportamento.
A classe Document é a classe que essencialmente representa a persistência no programa, sendo responsável por abrigar os métodos para criar, abrir e modificar os arquivos de dados.Na figura abaixo pode-se ver um trecho de código dessa classe. Este código apenas cria um objeto da classe AppUI e retorna um ponteiro para ele.

Figura 3: Trecho de código do MyFirstProjectDocument.cpp

6. Classe AppUI

A classe AppUI deve derivar de CEikAppUi (ou de alguma classe que derive desta, como CAknAppUI), que por sua vez deriva de CCoeAppUI, que pertence ao controle do ambiente (CONE). É neste ponto que a ação de GUI efetivamente se inicia, tendo essa classe duas tarefas principais: Capturar os comandos para aplicação e distribuir eventos de teclas para os vários views da aplicação.
A maior parte das funções dessa classe não são abstratas ("Virtuais na convenção C++), ou seja, apenas tem suas implementações vazias. Isso faz com que o desenvolvedor só implemente as funções que ele vai realmente utilizar, livrando o mesmo de precisar implementar todas as funções existentes nessa classe.

Algumas funções importantes implementadas nessa classe são descritas rapidamente abaixo:

  • HandleKeyEvent() : chamada quando um evento de tecla pressionada ocorre;
  • HandleForegroundEventL() : chamada quando o aplicativo perde o foco ou obtém o foco novamente (rodando em background);
  • HandleCommandL(): chamada quando um comando é selecionado;
  • HandleSystemEventL(): chamada quando um evento de sistema é gerado;
Outra função importante dessa classe é a responsabilidade por criar e gerenciar os applications views.


Figura 4: Trecho de Código do MyFirstProjectAppUI.cpp


7. Classe AppView

A application View deriva do CONE CCoeControl ( ou qualquer uma que derive desta). De acordo com a forma de como a arquitetura da sua aplicação esteja sendo projetada, uma classe diferente poderá fazer o papel do AppView, mas o AppView sempre está ligado à classe que realmente desenha as informações na tela.


Figura 5: Trecho de código da classe MyFirstProjectAppView.cpp


8. Ciclo de vida de uma aplicação

Nessa seção iremos demonstrar os principais passos que o sistema operacional executa desde momento em que você seleciona o aplicativo a ser executado até o momento que a aplicação está efetivamente executando na tela ( o primeiro momento que ela se desenha na tela).

O ciclo de vida para o início de execução de uma aplicação Symbian se dá pelos seguintes passos:

  • Passo 1: Toda a aplicação com GUI para Série 60 deve implementar a função global E32Dll(). Essa será a primeira função que será chamada pelo sistema operacional quando ocorre a tentativa de iniciar a aplicação. É considerado o ponto de entrada do DLL e deve estar presente na sua aplicação.
  • Passo 2: O próximo passo do framework é chamar a função NewApplication(), que efetivamente cria o objeto da aplicação, retornando um ponteiro para o sistema operacional. Esta deve ser exportada pela aplicação.
  • Passo 3: Uma vez criado o objeto da aplicação, o framework chama a função ApDllUid(), encontrada na classe Application da sua aplicação (Ex: CMyFirstProjectApplication.cpp), que retorna o UID3 da aplicação. O valor retornado deve ser o mesmo encontrado no arquivo .mmp (especificações do projeto) da aplicação, e é usado pelo sistema operacional verificar se já existe alguma instância desse aplicativo sendo executada.
  • Passo 4: O próximo passo é a chamada ao método do CreateDocumentL() existente na classe Application (CMyFirstProjectApplication.cpp, por exemplo). Esse método retorna para o framework um ponteiro para um objeto do tipo CApaDocument, que aponta para o objeto da classe Document (CMyFirstProjectDocument.cpp que estende CAknDocument). Note que um ponteiro para a classe Application é passado para classe Document como parâmetro de forma que esta possa ser capaz de chamar o método AppDllUuid() para descobrir o UID3 da aplicação e gerenciar os arquivos dessa aplicação.
  • Passo 5: Agora o framework usa este ponteiro para criar o objeto AppUI (no exemplo, CMyFirstProjectAppUI) chamando o método CreateAppUiL().
Dessa forma, o framework tem ponteiros para os objetos principais da aplicação - Application, Document e AppUI, que foram obtidos a partir de uma estrutura específica na qual a aplicação foi construída. Esses ponteiros possibilitam ao framework chamar funções dessas classes para descobrir a UID3 e identificar a aplicação, no caso da Application; abrir ou modificar um documento, no cado da Document; repassar um evento do sistema, no caso da AppUI.

Esses ponteiros podem ser usados pelo framework para controlar a aplicação, repassando eventos específicos do sistema para o aplicativo.

Image:Sequenciainicializacao.JPG

Cada um dos métodos apresentados aqui precisam ser criados para o funcionamento adequado (minimo) de um aplicativo S60.

1) - O framework faz a chamada a função NewApplication() para criar o objeto da aplicação.
2) - CMyAppApp::CreateDocumentL() diretamente chama MyAppDocument::NewL().
3) - Construção da primeira e segunda classe é feita aqui.
4) - CMyAppDocument::CreateAppUiL() chama diretamente o construtor padrão c++ de CMyAppAppUi.
5) - O construtor padrão aloca memória para o objeto e inicializa seus membros com 0.
6) - MyAppAppUi::ConstructL() cria o container.
7) - Objeto do container é criado aqui.
8) - CMyAppContainer::SetMopParent() define o pai do container como o AppUI. Este procedimento é necessário se o container precisar utilizar scrollbars.
9) - CMyAppContainer::ConstructL() é chamado para realizar a construção em duas fases do container. Note que o TRect& é passado como referência para o container neste estágio. O container não será exibido até que CCoeControl::ActivateL() seja chamado.

9. Design da arquitetura

Iremos descrever agora o design da arquitetura do programa de um celular Série 60. Atualmente, existem 3 formas de implementar tal arquitetura: Arquitetura tradicional, Arquitetura baseada em componentes e Arquitetura Avkon com troca de views.
A principal diferença entre elas é a forma como manipulam os eventos e como é feita a troca de views dentro do programa, além de mudar a implementação desse View.

Na arquitetura tradicional, o elemento View herda diretamente de CCoeControl, que funciona como uma tela em branco que pode ser desenhada conforme a necessidade. Essa classe é comumente chamada de Container. Isso permite uma grande flexibilidade, mas exige várias linhas de código para desenvolver coisas mais elaboradas, o que se torna às vezes inviável em certas aplicações. Em termos de gerenciamento de eventos, o AppUI é o responsável por gerenciar os eventos inciados pelo usuário, ativando o Container de acordo com a lógica da aplicação.

Na arquitetura baseada em componentes, o AppUI também é a classe que possui os controles. A diferença é que esses controles herdam de uma série de classes específicas (que por sua vez herdam de CCoeControl) que implementam diversos componentes como listas, formulários e outros elementos gráficos pré-programados pelo sistema operacional. A grande vantagem nessa arquitetura é que podemos ter diversas funcionalidades já prontas sem a necessidade de codifica-las com uma aparência padrão do sistema operacional. A desvantagem é que essa abordagem não tem a mesma flexibilidade que a arquitetura tradicional oferece.

Na arquitetura Avkon a troca de views é específica do Avkon, ou seja, específica para a plataforma Série 60, e foi criada para ser utilizada com aplicações de múltiplas telas e múltiplas trocas de tela. Ela tem a mesma estrutura da arquitetura tradicional, com a idéia de container, mas existe outra classe entre o container e o AppUi que faz o papel do Appview e herda de CAknViewAppui. Essa classe é responsável por ativa/desativas os containers de acordo com os comandos vindos do AppUI e de forma que fique ativo apenas uma View no momento.
O CAknViewAppUi é também responsável por criar e destrur as views, e normalmente o faz de forma que os views não estejam ativos sejam destruídos, para economizar memória.

10. Exemplo usando a arquitetura tradicional

Em Breve!

10. Referências

http://wiki.forum.nokia.com/index.php/Criando_um_Hello_Word (Forum Nokia Wiki em Português)

http://www.forum.nokia.com/document/Cpp_Developers_Library/ (C++ Developer Library 1.1)

http://mobideia.blogspot.com (Blog Mobidéia por Marcel Caraciolo)

Revista WebMobile, número 5. Artigo Desenvolvimento C++ para Symbian: Interface Gráfica. Autores: Eduardo Peixoto e Renato Faria.

1 comentários:

Heber P. Lopes disse...

olá amigo!

fiz meu 1° helloWorld no c+ symbian e funcionou! rsrsrs

estou tentando copiar e colar este codigo no meu hello world, mas nao essei onde fica o header , que arquivo é esse?

veja o artigo:
http://wiki.forum.nokia.com/index.php/CS001412_-_Getting_position_data_from_TPositionInfoBase

abraços!

top