0

Curso de Android Básico

by Luiz Jr 6. maio 2012 23:24

Splash Screen do Taskz

É, faz tempo que não escrevo por aqui. Ando extremamente ocupado atualmente cuidando de vários projetos em paralelo, mas devido a um grande acontecimento recente, tive de tirar um tempo para atualizar o blog. Neste final de semana terminou o curso que estava ministrando na Ulbra Canoas-RS sobre Android. O curso de 12h foi extremamente básico mas tenho certeza que os 24 alunos puderam aprender muito e estão aptos a desenvolver aplicações simples para a plataforma que mais cresce no mercado. A idéia deste post é agrupar o material do curso para que os alunos possam fazer download. Da mesma forma, qualquer pessoa que estiver interessada no material pode baixá-lo sem problemas e sem ter de me pagar royalties ou coisas do gênero.

Conteúdo do Curso

Para quem quizer fazer download dos slides do curso, use este link:

Curso Android.rar (2,49 mb)

  • Mercado Mobile
  • A Linguagem Java
  • A Plataforma Android
  • App Programming
  • App Design
  • Acesso à Dados
  • Deploy

Além disso, durante o curso desenvolvemos uma aplicação extremamente simples de registro de tarefas que eu chamei de Taskz. O código-fonte da referida aplicação pode ser baixado neste link:

Taskz.rar (961,98 kb)

Esta aplicação mostra o uso de variados recursos da plataforma como Activities, widgets, splash screen, dialogs, SQLite, manifesto, menus, etc, dando uma excelente introdução. Use estes fontes como material de estudo, acredito que algumas classes servirão inclusive para seus projetos pessoais, como DialogHelper (uma classe utilitária para lidar com diálogos de forma extremamente fácil) e DbAdapter (para lidar com bancos de dados).

Slide do Curso

Agradecimentos e Outras Edições

Antes de terminar gostaria de agradecer a participação dos alunos que bateram recorde em um curso ministrado por mim (até então a maior turma era a da 1ª edição do Curso Básico de ASP.NET da FAQI Gravataí, com 21 alunos). Também gostaria de agradecer à confiança e apoio dos professores Anderson Yanzer e Maurício Escobar, da Ulbra Canoas, que possibilitaram que o curso fosse ministrado e fizeram a divulgação entre os alunos.

No dia 07/07 estarei ministrando a 2ª edição do curso, desta vez na Ulbra Gravataí-RS, quem quiser participar contate a coordenação do curso de Ciência da Computação da universidade pelo e-mail informaticagra@ulbra.br. Se você estuda em alguma instituição do RS que não possui curso de extensão em cima de plataformas móveis e gostaria que este curso fosse ministrado por lá, peça para seu coordenador entrar em contato comigo pelo formulário de contato do blog e quem sabe eu não visito sua instituição para dar uma palestra ou curso sobre o assunto? Aguardo seu contato!

Foto da Turma

Tags: , , , ,

Android | Eventos | Experiências | Java | Mobile | Treinamentos

0

HTML 5 + CSS3, C# + Java e Windows Phone 7 em um post!

by Luiz Jr 24. dezembro 2011 10:43

Sim, este post tratará sobre estes três assuntos: HTML5 + CSS3 (+Javascript), interoperabilidade entre sistemas Java e .NET (não necessariamente C#) e Windows Phone 7, mas não, não serão ao mesmo tempo, hehehe. Neste final de ano o pessoal da Microsoft Brasil resolveu suar a camisa e nos entregar uma série de treinamentos gratuitos para capacitar os desenvolvedores de suas plataformas melhor. O post é breve, afinal ninguém quer ficar lendo nerdices em plena véspera de Natal, exceto eu é claro...

HTML5 &  Javascript Center

A Microsoft criou um hotsite chamado HTML5 & Javascript Center, onde dão muitas informações sobre como utilizar HTML5, CSS3 e Javascript juntos para criar páginas web ainda melhores. O site já contém muito material, incluindo tutoriais simples como uso da tag Áudio e Vídeo até coisas mais complexas como manipulação da tag Canvas (o canivete suíço do HTML5). Além disso, boa parte desse material está em Português, e mesmo o material em inglês é fácil de entender (afinal HTML é HTML em qualquer idioma...). O site também contém links de referências e está muito bem organizado por categoprias. Vale a pena conferir no http://msdn.microsoft.com/pt-br/hh442325.

Interoperabilidade entre Java e .NET

Desde que venho acompanhando a comunidade em torno da Microsoft Brasil em 2008, pude notar que uma postura que se instaurou na cia. é a de interoperabilidade de plataformas. Ultimamente a Microsoft tem lançado cada vez mais soluções interoperáveis, como seu Hyper-V e SCVMM para Linux, WebMatrix para PHP, TFS para Eclipse, Azure para PHP, Java, etc; material dedicado a HTML5 + CSS3 (existe algo mais interoperável que uma página HTML?), disponibilização de fontes para o pessoal do projeto Mono e Moonlight e por aí vai. Isto foi uma atitude muito inteligente do novo CEO Steve Ballmer, que tem atraído mais união entre os desenvolvedores de diferentes plataformas.

Dentro desta mesma linha, recentemente a Microsoft Brasil colocou no ar uma nova página dentro de seu famoso Centro de Treinamento (que eu já citei em outro post): Interoperabilidade entre Java e .NET. Todo mundo que está no mercado a alguns anos e já trabalhou em algumas empresas diferentes sabe que hoje Java e .NET são os bam-bam-bams do mercado mundial de software. As maiores cias. de software do mundo desenvolvem em tais tecnologias e os maiores salários do mercado são ofertados para analistas e desenvolvedores das mesmas. Parece que esse panorama não irá mudar nem mesmo com a crescente das aplicações móveis, uma vez que você pode continuar usando Java e .NET para programar para Android e iOS.

Mas voltando ao assunto da página, acesse http://msdn.microsoft.com/pt-br/hh314025, lá você encontra tutoriais em português sobre o funcionamento das arquiteturas (que são muuuito parecidas), sobre como fazer serviços Java conversarem com .NET e o inverso, como utilizar WCF e Glassfish e inclusive como colocar JEE na nuvem do Azure!

Windows Phone 7

E a minha notícia favorita de final de ano: uma página novinha em folha no Centro de Treinamento somente sobre Windows Phone 7 e 100% em português! Lembram-se de meu post anterior sobre Windows Phone 7, onde falei sobre os vídeos existentes no Channel 9, com o Bob Tabor? Pois é, agora temos a nossa versão tupiniquim e com ótimo conteúdo. Acesse http://msdn.microsoft.com/pt-br/hh230679 e veja uma gama completa de conteúdos como instalação do ambiente, Silverlight, XNA, deploy, debug, app lifeycle, gestos, orientação, themes, globalization, SQL Server Compact (toma SQLite!), GPS e por aí vai.

Resta saber se a parceria Microsoft + Nokia vai emplacar o WP7 na terra do Blanka, uma vez que nossa carga tributária é altíssima e fica difícil concorrer com o Android, que possui aparelhos em torno de R$500. Mas já é bom ir se adiantando, não é mesmo?

Tags: , , , , , ,

ASP.NET | Dica | Mercado | Mobile | Web | WP7 | Java

11

Criando uma app Android com banco de dados SQLite

by Luiz Jr 20. novembro 2011 23:34

Android + SQLite

Hoje o post irá tratar de um assunto muito importante: persistência de dados. Todas as aplicações que lidam com um grande volume de dados devem ter algum mecanismo de persistência, mais conhecido como banco de dados, para garantir a segurança, confiabilidade e integridade dos mesmos. O Android possui um mecanismo nativo, chamado de SQLite (o mesmo utilizado pelo Corona SDK) que provê funcionalidades de SGBD para suas aplicações. Iremos ver algumas dessas funcionalidades neste post, de uma maneira bem simples, mas que servirá como base para estudos futuros.

Armazenamento persistente de dados

Para cumprir com muitas das atividades oferecidas pelos celulares modernos, como busca de contatos, eventos, e tarefas, o sistema operacional e as aplicações estar aptos a manter e rastrear grandes quantidades de dados. A maior parte destes dados está estruturado como uma planilha, na forma de linhas e colunas. Cada aplicação Android é como uma ilha por si só, e cada aplicação somente consegue ler e escrever dados criados por ela mesma, mas muitas vezes é necesário compartilhar dados além de suas fronteiras. Android suporta características de um provedor de conteúdo para que as aplicações possam compartilhar dados. Existe uma interface Java para que o Android possa se comunicar com a base de dados relacional SQLite. Esta interface suporta uma implementação de SQL rica o suficiente para qualquer coisa que você queira em uma aplicação mobile, incluindo facilidades como cursores.

Bases de Dados

Dados são melhores armazenados em um formato de base de dados relacional se ela puder incluir muitas instâncias de um mesmo tipo de dado. pegue uma lista de contatos, por exemplo. Existem muitos contatos, todos com os mesmos tipos de informação (endereço, telefone, etc). Cada "linha" de dados armazena informações sobre uma pessoa diferente, enquanto cada "coluna" armazena um atributo específico de cada pessoa: nomes em uma coluna, endereços em outra coluna, e telefone em uma terceira.

Android usa a engine de base de dados SQLite, uma auto-contida, engine transacional que não requer um processo de servidor para funcionar. Ele é usado por muitas aplicações e ambientes além de Android, e é desenvolvido por uma grande comunidade.

O processo que inicia a operação de base de dados, como um SELECT ou UPDATE, faz o trabalho necessário de leitura e escrita no disco que contém a base de dados visando completar a requisição. Com SQLite, a base de dados é um simples arquivo no disco. Todas as estruturas de dados formando uma base de dados relacional - tabelas, views, indíces, etc. - estão contidas neste arquivo.

SQLite não é um projeto do Google, embora o Google contribua com o mesmo. SQLite tem um time internacional de desenvolvedores dedicados a melhorar as capacidades do software e sua confiabilidade. Alguns desses desenvolvedores trabalham full time no projeto.

Confiança é a característica chave do SQLite. Mais de metade do código do projeto é devotado a biblioteca de testes. A biblioteca é desenvolvida para lidar com muitos tipos de falhas de sistema, como pouca memória, erros de disco, e falhas de energia. Em nenhum caso a base de dados pode ficar em um estado irreparável: isto é uma grande preocupação em um telefone onde muitos dados críticos são armazenados em bases de dados. Se a base de dados fosse suscetível a corrupção de arquivos, o telefone estaria em sérios apuros quando a bateria acabasse...

Este post irá tratar dos percalços para se criar uma aplicação muito simples que consuma dados no SQLite e não se atrá à sintaxe SQL propriamente. Um pouco de Engenharia de Software será utilizada, mantendo toda a lógica de acesso à dados em uma única classe chamada ContextoDados.java como segue (ela ainda não está completa, iremos construindo-a ao longo do post):

import android.content.ContentValues;
import android.content.Context;
import android.database.Cursor;
import android.database.SQLException;
import android.database.sqlite.SQLiteCursor;
import android.database.sqlite.SQLiteCursorDriver;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;
import android.database.sqlite.SQLiteQuery;
import android.util.Log;

public class ContextoDados extends SQLiteOpenHelper {

	/** O nome do arquivo de base de dados no sistema de arquivos */
	private static final String NOME_BD = "Agenda";
	/** A versão da base de dados que esta classe compreende. */
	private static final int VERSAO_BD = 1;
	private static final String LOG_TAG = "Agenda";
	/** Mantém rastreamento do contexto que nós podemos carregar SQL */
	private final Context contexto;
	
	public ContextoDados(Context context) {
		super(context, NOME_BD, null, VERSAO_BD);
		this.contexto = context;
		}

	@Override
	public void onCreate(SQLiteDatabase db) 
	{
		String[] sql = contexto.getString(R.string.ContextoDados_onCreate).split("\n");
		db.beginTransaction();
		
		try 
		{
			// Cria a tabela e testa os dados
			ExecutarComandosSQL(db, sql);
			db.setTransactionSuccessful();
		} 
		catch (SQLException e) 
		{
			Log.e("Erro ao criar as tabelas e testar os dados", e.toString());
		} 
		finally 
		{
			db.endTransaction();
		}
	}

	@Override
	public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) 
	{
		Log.w(LOG_TAG, "Atualizando a base de dados da versão " + oldVersion + " para " + newVersion + ", que destruirá todos os dados antigos");
		String[] sql = contexto.getString(R.string.ContextoDados_onUpgrade).split("\n");
		db.beginTransaction();
		
		try 
		{
			ExecutarComandosSQL(db, sql);
			db.setTransactionSuccessful();
		}
		catch (SQLException e) 
		{
			Log.e("Erro ao atualizar as tabelas e testar os dados", e.toString());
			throw e;
		} 
		finally 
		{
			db.endTransaction();
		}
		
		// Isto é apenas didático. Na vida real, você terá de adicionar novas colunas e não apenas recriar o mesmo banco
		onCreate(db);
	}
	
	/**
	* Executa todos os comandos SQL passados no vetor String[]
	* @param db A base de dados onde os comandos serão executados
	* @param sql Um vetor de comandos SQL a serem executados
	*/
	private void ExecutarComandosSQL(SQLiteDatabase db, String[] sql)
	{
		for( String s : sql )
			if (s.trim().length()>0)	
				db.execSQL(s);
	}
}

Estrutura Básica da classe ContextoDados

Em nosso exemplo, a classe ContextoDados encapsula completamente toda a lógica SQL necessária para trabalhar com a base de dados. Todas as outras classes na aplicação não possuem acesso aos dados diretamente, usando ContextoDados como uma interface de abstração dos mesmos. Esta é uma boa prática de programação e deve ser aplicada em todas suas aplicações Android que utilizem base de dados.

Antes de aprofundarmo-nos nos detalhes da aplicação em si, é importante entender o funcionamento da classe ContextoDados. Esta classe herda de SQLiteOpenHelper, e sobrescreve (override) os métodos onCreate e onUpgrade. O método onCreate é automaticamente chamado quando a aplicação roda pela primeira vez; sua tarefa é criar a base de dados. Como novas versões daaplicação podem ser lançadas, a base de dados pode ser atualizada também, uma tarefa que dispara o método onUpgrade. Quando você entrega uma nova versão da base de dados, você também deve incrementar a versão, como irei explicar rapidamente a seguir.

E por fim, o método ExecutarComandosSQL é um método para facilitar a execução de comandos SQL múltiplos, que apenas chama os comandos nativos do Android para execução de comandos SQL.

A classe ContextoDados utiliza duas strings estáticas (que ficam no arquivo strings.xml): R.string.ContextoDados_onCreate e R.string.ContextoDados_onUpgrade com os scripts de criação e atualização do banco de dados. Estas strings estão abaixo e não passam de um SQL comum, quevocê já deve estar acostumado:

<string name="ContextoDados_onCreate">
        CREATE TABLE Contatos (ID INTEGER PRIMARY KEY AUTOINCREMENT, Nome TEXT,    Telefone TEXT, Endereco TEXT);
</string>
<string name="ContextoDados_onUpgrade">"
        DROP TABLE IF EXISTS Contatos
</string>

Lendo dados da base

Existem muitas maneiras de ler dados de uma base SQL, mas todos eles fazem uma sequência básica de operações:

  1. Cria um comando SQL que descreve os dados que você deseja retornar
  2. Executa o comando na base de dados
  3. Mapeia os dados SQL resultantes em uma estrutura de dados que a linguagem que você está utilizando possa entender.

Este processo pode ser muito complexo no caso de um software de mapeamento objeto relacional, ou relativamente simples quando escrevendo as consultas diretamente em sua aplicação. A diferença é a fragilidade. Ferramentas complexas de ORM protegem seu código das complexidades inerentes às bases de dados e o mapeamento de objetos, movendo esta complexidade para eles mesmos. O resultado é um código mais robusto face às alterações na base, mas ao custo de mais complexidade na configuração e manutenção do ORM.

A iniciativa de escrever consultas diretamente na sua aplicação trabalha bem somente para projetos bem pequenos que não irão mudar muito com o passar do tempo. Aplicações com código de base de dados são muito frágeis devido às alterações da mesma, pois todo o código que referenciava um elemento alterado deve ser examinado e potencialmente reescrito.

Uma técnica "meio-termo" é capturar toda a lógica de base de dados em um grupo de objetos cujo único propósito é traduzir as requisições da aplicação em requisições de banco de dados e entregar os resultados de volta para a aplicação. Esta opção é a utilizada em nossa aplicação de teste utilizando a classe ContextoDados.java.

Android nos dá a habilidade de personalizar cursores, e eu usarei essa característica para reduzir dependências de código escondendo toda a informação sobre uma operação de dados específica dentro d eum cursor personalizado. Cada cursor personalizado é uma classe dentro da classe ContextoDados, no nosso caso, somente o ContatosCursor.

Desta forma, criei um método RetornarContatos, cuja função é retornar um ContatosCursor preenchido com contatos da base de dados. O usuário pode escolher (através de um simples parâmetro) para ordenar os contatos por Nome crescente ou decrescente (este código vai dentro da classe ContextoDados criada anteriormente):

 

/** Retorna um ContatosCursor ordenado
	* @param critério de ordenação
	*/
	public ContatosCursor RetornarContatos(ContatosCursor.OrdenarPor ordenarPor) 
	{
		String sql = ContatosCursor.CONSULTA + (ordenarPor == ContatosCursor.OrdenarPor.NomeCrescente ? "ASC" : "DESC");
		SQLiteDatabase bd = getReadableDatabase();
		ContatosCursor cc = (ContatosCursor) bd.rawQueryWithFactory(new ContatosCursor.Factory(), sql, null, null);
		cc.moveToFirst();
		return cc;
	}
	
	public static class ContatosCursor extends SQLiteCursor
	{
		public static enum OrdenarPor{
			NomeCrescente,
			NomeDecrescente
		}
		
		private static final String CONSULTA = "SELECT Contatos.ID, Nome, Endereco FROM Contatos ORDER BY Nome ";
		
		private ContatosCursor(SQLiteDatabase db, SQLiteCursorDriver driver, String editTable, SQLiteQuery query) 
		{
			super(db, driver, editTable, query);
		}
		
		private static class Factory implements SQLiteDatabase.CursorFactory
		{
			@Override
			public Cursor newCursor(SQLiteDatabase db, SQLiteCursorDriver driver, String editTable, SQLiteQuery query) 
			{
				return new ContatosCursor(db, driver, editTable, query);
			}
		}
		
		public long getID()
		{
			return getLong(getColumnIndexOrThrow("Contatos.ID"));
		}
		
		public String getNome()
		{
			return getString(getColumnIndexOrThrow("Nome"));
		}
		
		public String getEndereco() 
		{
			return getString(getColumnIndexOrThrow("Endereco"));
		}
	}

Tela de listagem

Como o foco deste post não é a criação de um layout ideal para exibição de dados, criei um bem simples que utiliza um TextView para mostrar os dados do banco concatenando strings. O código XML abaixo mostra como deve ser codificado o layout main.xml e a imagem mostra como ele deve se parecer:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    >

    <TextView
        android:id="@+id/textView1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="@string/contatos"
        android:textAppearance="?android:attr/textAppearanceLarge" />

    <TextView
        android:id="@+id/listaContatos"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Nenhum contato cadastrado." />

    <Button
        android:id="@+id/btnNovo"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Novo Cadastro" />
   
</LinearLayout>

E o código Java a seguir mostra o início da codificação da Activity principal, que mantém o nome padrão de MainActivity.java (este código vai dentro do corpo da classe MainActivity):

 

Button btnSalvar, btnCancelar, btnNovo;
EditText txtNome, txtEndereco, txtTelefone;
	
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        CarregarInterfaceListagem();
    }
    
    public void CarregarInterfaceListagem()
    {
    	setContentView(R.layout.main);
        
        //configurando o botão de criar novo cadastro
        btnNovo = (Button)findViewById(R.id.btnNovo);
        btnNovo.setOnClickListener(new OnClickListener(){
			public void onClick(View v) {
				CarregarInterfaceCadastro();
			}});
        
        CarregarLista(this);
    }

Neste trecho de código podemos ver as chamadas aos métodos CarregarLista (mostrado abaixo) e mais a seguir implementaremos o CarregarInterfaceCadastro:

 

public void CarregarLista(Context c)
    {
    	ContextoDados db = new ContextoDados(c);
        ContatosCursor cursor = db.RetornarContatos(ContatosCursor.OrdenarPor.NomeCrescente);
        
        for( int i=0; i < cursor.getCount(); i++)
        {
        	cursor.moveToPosition(i);
        	ImprimirLinha(cursor.getNome(), cursor.getTelefone());
        }
    }
    
    public void ImprimirLinha(String nome, String telefone)
    {
    	TextView tv = (TextView)findViewById(R.id.listaContatos);
    	
    	if(tv.getText().toString().equalsIgnoreCase("Nenhum contato cadastrado."))
    		tv.setText("");
    	
    	tv.setText(tv.getText() + "\r\n" + nome + " - " + telefone);
    }

Este código nada mais faz do que concatenar strings em um TextView para simular uma listagem de dados vindos do banco. Com o código que vimos até agora, já é possível listar os dados que já estão no banco, mas provavelmente você irá querer escrever também, que veremos na próxima parte!

Escrevendo no Banco de Dados

Voltando ao ContextoDados, o trecho de código a seguir insere um novo registro no banco de Contatos e serve como exemplo para futuras inserções em outras tabelas (este código vai dentro da classe ContextoDados):

 

public long InserirContato(String nome, String telefone, String endereco)
	{
		SQLiteDatabase db = getReadableDatabase();
		
		try
		{
			ContentValues initialValues = new ContentValues();
			initialValues.put("Nome", nome);
			initialValues.put("Telefone", telefone);
			initialValues.put("Endereco", endereco);
			return db.insert("Contatos", null, initialValues);
		}
		finally
		{
			db.close();
		}
	}

Cadastro.xml - Como deve se parecer

E agora devemos criar o layout para a tela de cadastro, que chamei de cadastro.xml. A seção a seguir mostra o código XML para o layout, e a imagem à direita, como ele deve se parecer se tudo estiver correto:

<?xml version="1.0" encoding="utf-8"?>
<AbsoluteLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent" >

    <TextView
        android:id="@+id/lblNome"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_x="8dp"
        android:layout_y="9dp"
        android:text="@string/lblNome"
        android:textAppearance="?android:attr/textAppearanceSmall" />

    <TextView
        android:id="@+id/lblTelefone"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_x="7dp"
        android:layout_y="52dp"
        android:text="@string/lblTelefone"
        android:textAppearance="?android:attr/textAppearanceSmall" />

    <TextView
        android:id="@+id/lblEndereco"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_x="8dp"
        android:layout_y="95dp"
        android:text="@string/lblEndereco"
        android:textAppearance="?android:attr/textAppearanceSmall" />

    <EditText
        android:id="@+id/txtNome"
        android:layout_width="180dp"
        android:layout_height="40dp"
        android:layout_x="78dp"
        android:layout_y="8dp"
        android:inputType="textPersonName" >

        <requestFocus />
    </EditText>

    <EditText
        android:id="@+id/txtTelefone"
        android:layout_width="180dp"
        android:layout_height="40dp"
        android:layout_x="78dp"
        android:layout_y="50dp"
        android:inputType="phone" />

    <EditText
        android:id="@+id/txtEndereco"
        android:layout_width="180dp"
        android:layout_height="40dp"
        android:layout_x="78dp"
        android:layout_y="93dp"
        android:inputType="textPostalAddress" />

    <Button
        android:id="@+id/btnSalvar"
        android:layout_width="82dp"
        android:layout_height="wrap_content"
        android:layout_x="173dp"
        android:layout_y="142dp"
        android:text="@string/btnSalvar" />

    <Button
        android:id="@+id/btnCancelar"
        android:layout_width="92dp"
        android:layout_height="wrap_content"
        android:layout_x="78dp"
        android:layout_y="141dp"
        android:text="Cancelar" />

</AbsoluteLayout>

Note que neste layout temos alguns EditTexts e dois botões. O botão de cancelar apenas retorna à tela inicial, com a listagem tosca de contatos. Já o botão de salvar, deve invocar o método de inserir novo registro, da classe ContextoDados. O código restante da MainActivity está abaixo, para que você possa copi-colar:

 

public void CarregarInterfaceCadastro()
    {
    	setContentView(R.layout.cadastro);
    	
    	//configurando o botão de cancelar cadastro
        btnCancelar = (Button)findViewById(R.id.btnCancelar);
        btnCancelar.setOnClickListener(new OnClickListener(){
			public void onClick(View v) {
				CarregarInterfaceListagem();
			}});
        
        //configurando o formulário de cadastro
        txtNome = (EditText)findViewById(R.id.txtNome);
        txtEndereco = (EditText)findViewById(R.id.txtEndereco);
        txtTelefone = (EditText)findViewById(R.id.txtTelefone);
        
        //configurando o botão de salvar
        btnSalvar = (Button)findViewById(R.id.btnSalvar);
        btnSalvar.setOnClickListener(new OnClickListener(){
			public void onClick(View v) {
				SalvarCadastro();
			}});
    }
    
    public void SalvarCadastro()
    {
    	ContextoDados db = new ContextoDados(this);
		db.InserirContato(txtNome.getText().toString(), txtTelefone.getText().toString(), txtEndereco.getText().toString());
		setContentView(R.layout.main);
		CarregarLista(this);
    }

 

O código é auto-descritivo, mas caso tenha alguma dúvida, não hesite em perguntar pelos comentários.

Conclusões

Este post mostrou o básico de seleção e inserção de dados, com uma exibição bem tosca, longe de ser a ideal para uma base de dados. Você realizar o download dos fontes completos do projeto no link abaixo. Posts futuros devem cobrir outros aspectos da persistência de dados, como deleção e atualização, bem como listagem profissional dos dados usando ListAdapters. Mas isto fica pra próxima!

Agenda.zip (68,85 kb)

Tags: , , , ,

Android | BD | Mobile

8

Utilizando o recurso de GPS em uma app Android

by Luiz Jr 19. novembro 2011 15:03

Olá, este será mais um post sobre a melhor plataforma de desenvolvimento mobile da atualidade, o Android. Os números não me deixam mentir, com o SO do Google dominando mais de 50% do mercado de smartphones no mundo e com mais de 250 mil aplicativos disponíveis no Android Market (desses, cerca de 130 mil gratuitos). Neste post, iremos tratar do uso do hardware de GPS presente em alguns dispositivos com Android, como o Motorola Defy e o Motorola Milestone, só para citar alguns exemplos que pude utilizar (sem contar a infinidade de xing-lings que tem no mercado). A idéia é utilizar tal hardware para descobrir onde o usuário da app está e com essa informação em mãos, você fazer o que quiser, como plotar esta localização em um mapa do Google Maps, por exemplo.

Mas já não existe aplicações que fazem isso? Sim, e aos montes. Então por que diabos eu iria querer aprender a fazer isso? Simplesmente porque a idéia aqui é estudar o funcionamento de aplicações que consumam os dados do GPS nativo do aparelho, para então, desenvolver suas próprias aplicações que necessitem de tais dados. Como exemplo podemos citar aplicações como o Four Square, que coleta a informação de sua localização para garantir que você realmente está no local que diz estar ou o Google Latitude, que permite ver onde seus amigos estão neste exato momento, só para citar algumas. No meu caso o estudo é pertinente a um trabalho freelancer com a plataforma, que exigirá conhecimentos dessa API.

Usando a Android Location-Based API

O Android SDK contém uma API que foi criada especialmente para utilizar de forma abstrata sua Activity com qualquer hardware de GPS que possa existir em seu dispositivo. Uma vez que normalmente trabalhamos com um emulador baseado em software (O AVD - Android Virtual Device), e não com um dispositivo de verdade, a presença do hardware de GPS terá que ser simulada. Para que isto ocorra o emulador que você está utilizando deve prover simulação de hardware GPS, o que você pode aplicar indo no AVD Manager e criando (ou editando) um AVD, adicionando tal recurso, como mostra na tela abaixo:

Adicionando suporte ao GPS

Uma vez que seu AVD tenha suporte à GPS, você usará o console do ADB (Android Debugger Bridge) para enviar comandos de localização, simulando que o usuário do dispositivo se locomoveu. Também usaremos as ferramentas existentes no Motodev Studio 3 (e provavelmente devem existir no Eclipse tradicional também) para enviar as coordenadas ao emulador que você deseja testar. Estas ferramentas ficam disponíveis na aba Emulator Control, no rodapé da IDE, como mostra a figura abaixo. Com elas é possível simular que o celular encontra-se em uma região diferente da atual, para que você possa testar sua aplicação sob diferentes circunstâncias (as configurações de GPS estão na aba Emulator Control, porém devem rolar um pouco para baixo até encontrá-las).

Simulando coordenadas GPS

A outra forma, é usando o Console do ADB, que você habilita indo na aba Gerenciador de Dispositivos e clicando no ícone Console. Uma vez com o console aberto, você pode enviar comandos ao emulador que está rodando em seu MotoDev/Eclipse. O comando que você utiliza para enviar posições GPS é o geo. O geo na verdade é um grupo de comandos para manipulação de localização, e o que iremos usar é o geo fix. Digitando "geo fix help" no console você consegue dicas de como usar este comando. Resumindo, basta digitar "geo fix <longitude> <latitude>" visto que dificilmente você irá usar os demais parâmetros, como altitude, por exemplo. A figura abaixo mostra o funcionamento do console, inserindo as coordenadas de Porto Alegre-RS:

Comando geo fix

Lendo os dados de GPS com a Android Location-Based API

O restante deste post irá tratar exclusivamente do desenvolvimento de uma aplicação "OndEstou" que identifica a localização do usuário, sendo esta primeira parte bem simples, pois apenas exibirá a informação de latitude e longitude de onde o usuário se encontra, lhe dando uma base para prosseguir com o restante dos estudos da API. Os seguintes passos serão executados para que nossa demo tenha sucesso: devemos ajustar os níveis de permissão, criar o layout de nossa Activity, escrever o cpodigo da Activity e testá-la.

Ajustando o Nível de Permissão

O primeiro passo para trabalhar com a Android Location-Based API é ajustar o nível de permissão. Usar a API por si só não requer nenhuma permissão específica, mas usar a mesma para acessar informações de localização no GPS sim. A maneira mais fácil de setar permissões para um aplicativo é através da edição do manifesto do seu projeto, que foi descrito em meu último post. Este manifesto é facilmente editável pelo MotoDev Studio (de forma idêntica ao Eclipse tradicional).

Primeiramente, vamos criar um novo projeto no MotoDev/Eclipse com o nome de OndEstou, a versão do Android 2.2 (a mais comum no Brasil), com a Activity MainActivity.java. Em seguida, vamos abrir o arquivo AndroidManifest.xml e na aba Permissions do editor visual do manifesto, vamos adicionar a seguinte permissão (do tipo Uses Permission): ACCESS_FINE_LOCATION, como indicado na figura abaixo:

Acces Fine Location

Criando o layout de sua aplicação

Para iniciar o desenvolvimento do seu layout, abra o arquivo main.xml no MotoDev/Eclipse. Você terá de adicionar um Button e quatro TextView no seu layout, como a tela abaixo mostra:

Layout OndEstou

Este layout pode ser obtido com o código de exemplo abaixo, mas encorajo que você tente criar o seu sem utilizar este código (afinal, é um layout bem simples):

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent">

    <Button
    android:id="@+id/btnGps"
    android:layout_width="fill_parent"
    android:layout_height="wrap_content"
    android:text="Onde estou?"/>
   
    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content">
   
    <TextView
    android:id="@+id/lblLatitude"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:text="Latitude: "/>
   
    <TextView
    android:id="@+id/txtLatitude"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"/>
    </LinearLayout>
   
    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content">
   
    <TextView
    android:id="@+id/lblLongitude"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:text="Longitude: "/>
   
    <TextView
    android:id="@+id/txtLongitude"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"/>
    </LinearLayout>

</LinearLayout>

Escrevendo o código da sua Activity

Agora que você criou o layout, você pode começar a escrever o código que irá executar sua Activity. Seu Button precisa iniciar o serviço de monitoramento do GPS, para então enviar a latitude e longitude ao TextView correspondente. Primeiro você irá precisar adicionar nove diretivas import, que são os packages necessários para o funcionamento da Activity. Embora alguns programadores sintam-se tentados a adicionar imports mais genéricos como android.location.*, evitem isso para diminuir o tamanho de suas aplicações com código de biblioteca desnecessário:

 

import android.app.Activity;
import android.os.Bundle;
import android.view.View;
import android.widget.TextView;
import android.content.Context;
import android.widget.Button;
import android.location.Location;
import android.location.LocationListener;
import android.location.LocationManager;

 

A seguir, devemos criar o código para o evento OnCreate de sua Activity, que irá carregar os widgets de sua aplicação e definir o algoritmo para o evento Click do Button. O objetivo é que quando se clique no botão, seja registrado um Listener para o serviço de GPS que passará a enviar informações de localização à app. O código abaixo exemplifica o código necessário:

 

Button btnGps;
	TextView txtLatitude;
    TextView txtLongitude;
	
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        
        txtLatitude = (TextView) findViewById(R.id.txtLatitude);
        txtLongitude = (TextView) findViewById(R.id.txtLongitude);
        
        btnGps = (Button) findViewById(R.id.btnGps);
        btnGps.setOnClickListener(new Button.OnClickListener() {
	        public void onClick(View v){
	        	IniciarServico();
        }});
    }

Note que ainda não criamos o método IniciarServico, então é natural que sua IDE acuse um erro neste código. Além de carregarmos o botão, carregamos os TextViews que serão editados (txtLongitude e txtLatitude, neste exemplo). Os demais TextViews não serão instanciados pois eles são apenas rótulos de texto, e não serão editados posteriormente. Agora começamos a brincar com o serviço de GPS do Android, que é invocado através de um objeto Location Manager, que carrega o serviço de localização do dispositivo, como segue (agora criando nosso método IniciarServico):

 

public void IniciarServico()
    {
    	LocationManager locationManager = (LocationManager)getSystemService(Context.LOCATION_SERVICE);
    	
    	LocationListener locationListener = new LocationListener() {
    	    public void onLocationChanged(Location location) {
    	      Atualizar(location);
    	    }

    	    public void onStatusChanged(String provider, int status, Bundle extras) {}

    	    public void onProviderEnabled(String provider) {}

    	    public void onProviderDisabled(String provider) {}
    	  };

    	  locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 0, 0, locationListener);
    }

 

E por fim, devemos codificar o método Atualizar, que nada mais faz do que pegar o objeto Localization enviado pelo serviço de GPS e jogar suas informações nos TextViews correspondentes à latitude e longitude:

 

public void Atualizar(Location location)
    {
    	Double latPoint = location.getLatitude();
    	Double lngPoint = location.getLongitude();
        
        txtLatitude.setText(latPoint.toString());
        txtLongitude.setText(lngPoint.toString());
    }

App GPS funcionando

Para testar sua aplicação, basta rodá-la no MotoDev/Eclipse em um AVD configurado com o hardware de GPS, como citei no início do post e clicar no botão "Onde estou?" para ficar monitorando o serviço de GPS. Nada aconteceu? Não esqueça de enviar comandos de localização pelo console (usando geo fix) ou pelo editor gráfico na aba Emulator Control. O resultado esperado você vê na direita.

Abaixo você pode fazer download de todo o código fonte do projeto. Futuramente talvez eu continue este post ensinando como plotar esta informação em uma camada overlay na App do Google Maps, disponível em todos os aparelhos Android. Espero que tenham gostado do post e até a próxima.

OndEstou.zip (53,42 kb)

Tags: , , ,

Android | Mobile

0

Fundamentos de Aplicações Android

by Luiz Jr 11. novembro 2011 21:38

Continuando com meus posts acerca da arquitetura da plataforma Android, hoje escrevo sobre o básico das aplicações Android, seu funcionamento, componentes, recursos, etc, para que você entenda um pouco mais antes de sair codificando para sua plataforma mobile favorita. Este material é fortemente baseado na documentação oficial do Android, disponível em http://developer.android.com (em inglês).

Fundamentos Iniciais

Aplicações Android são escritas na linguagem de programação Java. As ferramentas do Android SDK compilam o código - juntamente com quaisquer outros dados e arquivos de recurso - em um pacote Android, um arquivo com a extensão .apk. Todo o código em um único arquivo .apk é considerado uma aplicação e este é o arquivo que dispositivos usando Android usam para instalar a aplicação.

Uma vez instalado no dispositivo, cada aplicação Android reside em sua própria sandbox segura:

  • O sistema operacional Android é um sistema Linux multi-usuário onde cada aplicação roda com um usuário diferente.
  • Por padrão, o sistema ssocia cada aplicação a um ID de usuário Linux único (o ID usado somente pelo sistema e que é desconhecido pela aplicação). O sistema define permissões por todos os arquivos de uma aplicação para somente aquele ID de usuário poder acesá-los.
  • Cada processo tem sua própria maquina virtual (VM), portanto o código de uma aplicação é executado isolado de outras aplicações.
  • Por padrão, cada aplicação executa seu próprio processo Linux. Android inicia o processo quando qualquer dos componentes de uma aplicação precisa ser executado, desligando o processo quando o mesmo não é mais necessário ou quando o sistema deve recuperar memória para outras aplicações.

Desta forma, o sistema Android implementa o princípio do menos privilegiado. Isto é, cada aplicação, por padrão, tem acesso somente aos componentes que ele necessita para funcionar e nada mais. Isto cria um ambiente muito seguro onde cada aplicação não pode acessra partes do sistema onde não possui permissão.

Entretanto, há algumas maneiras para uma aplicação compartilhar dados com outras aplicações e para uma aplicação acessar serviços do sistema:

  • É possível organizar duas aplicações para compartilhar o mesmo ID de usuário Linux, neste caso elas estarão aptas a acessar arquivos uma da outra. Para conservar recursos do sistema, aplicações com o mesmo ID de usuário podem também organizar-se para executar no mesmo processo Linux e compartilhar a mesma VM (as aplicações devem ser assinadas com o mesmo certificado).
  • Uma aplicação pode requisitar permissão para acessar dados do dispositivo como os contatos do usuário, mensagens SMS, o armazenamento removível (cartão SD), câmera, Bluetooth e muito mais. Todas permissões de aplicação devem ser concedidas pelo usuário durante a instalação.

Isto cobre o básico a respeito de como uma aplicação Android existe dentro do sistema. O resto deste post lhe dá uma introdução sobre:

  • Os componentes centrais do framework que definem sua aplicação.
  • O arquivo de manifesto onde você declara os componentes e as caracteristicas do dispositivo que são obrigatórias para sua aplicação.
  • Recursos que são separados do código da aplicação para otimizar enormemente seu comportamento para uma variedade de configurações de dispositivo.

Componentes de Aplicação

Componentes de aplicação são os blocos de construção essenciais de uma aplicação Android. Cada componente é um ponto diferente através do qual o sistema pode entrar na sua aplicação. Nem todos componentes são na verdade pontos de entrada para o usuário e alguns dependem de outros, mas cada um existe como sua própria entidade e executa um papel específico - cada um é um bloco de construção específico que ajuda a definir o comportamento geral de sua aplicação.

Existem quatro tipos diferentes de componentes de aplicação. Cada tipo serve a um propósito distinto e tem um ciclo de vida diferente que define como o componente é criado e destruído.

Aqui estão os quatro tipos de componentes de aplicação:

Activities

Uma activity (atividade) representa uma tela comum com uma interface de usuário. Por exemplo, uma aplicação de e-mail pode ter uma activity que mostra a lista de novos e-mails, outra activity para compór e-mails, e outra activity para ler e-mails. Emboras as activities trabalhem juntas para formar uma experiência de usuário coesa na aplicação de e-mail, cada uma é independente das outras. Desta forma, uma aplicação diferente pode iniciar qualquer uma destas activities (se a aplicação de e-mail permitir). Por exemplo, uma aplicação de câmera pode iniciar a activity na aplicação de e-mail para compor um novo e-mail, visando ao usuário compartilhar a foto.

Uma activity é implementada como uma subclasse de Activity e falareos mais delas nos posts futuros.

Services

Um service (serviço) é um componente que roda em background para executar operações demoradas ou para executar processos remotos. Um service não possui interface do usuário. Por exemplo, um service pode tocar música no background, enquanto o usuário está em uma aplicação diferente, ou ele pode carregar dados através da rede sem bloquear a interação do usuário com uma activity. Outro componente, como uma activity, pode iniciar o service e deixá-lo rodando ou conectar-se nele para interagir com o mesmo.

Um service é implementado como uma subclasse de Service e falaremos mais deles em posts futuros.

Content Providers

Um content provider (provedor de conteúdo) gerencia um grupo de dados de aplicação compartilhados. Você pode armazenar dados no sistema de arquivos, uma base SQLite, na web, ou em qualquer outro local de armazenamento persistente que sua aplicação possa acessar. Através do content provider, outras aplicações podem consultar ou mesmo modificar os dados (se o content provider permiti-lo). Por exemplo, o sistema Android provê um content provider que gerencia as informações dos contatos do usuário. Desta forma, qualquer aplicação com as permissões apropriadas pode consultar parte do content provider (como um ContactsContract.Data) para ler e escrever informações sobre uma pessoa em particular.

Content providers também são úteis para ler e escrever dados quee stão privados na sua aplicação e não são compartilhados. Por exemplo, salvar notas pessoais.

Um content provider é implementado como uma subclasse de ContentProvider e deve implementar um conjunto de APIs que permite a outras aplicações executarem transações. Mais informações em posts futuros.

Broadcast Receivers

Um broadcast receiver (receptor de notificações) é um componente que responde a notificações a nível de sistema. Muitas notificações originam-se do sistema - por exemplo, uma notificação anunciando que a tela foi desligada, a bateria está fraca, ou uma foto foi tirada. Aplicações também podem iniciar broadcasts—por exemplo, para deixar outras aplicações sabendo que alguns dados foram baixados para o dispositivo e estão disponíveis para uso. Embora broadcast receivers não exibam interface ao usuário, eles podem criar notificações na barra de status para alertar o usuário quando um evento broadcast ocorre. Mais comumente, embora, um broadcast receiver é somente um "gateway" para outros componentes e é intencionalmente criado para fazer a menor quantidade de trabalho. Por exemplo, ele pode iniciar um service para executar alguma tarefa baseada no evento.

Um broadcast receiver é implementado como uma subclasse de BroadcastReceiver e cada broadcast é entregue como um objeto Intent. Mais informações futuramente, neste mesmo blog.

Um aspecto único do design do sistema Android é que qualquer aplicação pode iniciar um componente de outra aplicação. Por exemplo, se você quer que o usuário tire uma foto com a câmera do dispositivo, provavelmente existe uma outra aplicação que faz isso e que sua aplicação pode usar, ao invés de desenvolver uma activity sua para tirar a foto. Você não precisa incorporar ou mesmo linkar código da aplicação da câmera. Ao invés disso, você simplesmente inicia a activity na aplicação da câmera que tira a foto. Quando completada, a foto é retornado para sua aplicação e então você pode usá-la. Para o usuário, parece que a câmera é na verdade parte de sua aplicação.

Quando o sistema inicia um componente, ele inicia o processo para aquela aplicação ( se ele ainda não está rodando) e instancia as classes necessárias para o componente. Por exemplo, se sua aplicação inicia a acitivity na aplicação da câmera que captura a foto, a activity roda no processo que pertence à aplicação da câmera, não no processo de sua aplicação. Entretanto, diferente da maioria dos outros sistemas, aplicações Android não possuem um único ponto de entrada (não existe uma função main(), por exemplo).

Devido ao sistema rodar cada aplicação em um processo separado com permissões de arquivo que restrigem o acesso de outras aplicaç~ies, sua aplicação não pode ativar diretamente um componente de outra aplicação. O sistema Android, entretanto, pode. Então, para ativar um componente de outra aplicação, você deve entregar uma mensagem para o sistema que especifica sua intenção (intent) de iniciar um componente em particular. O sistema então ativa o componente para você.

Ativando Componentes

Três dos quatro tipos de componentes - activities, services, e broadcast receivers - são ativados por mensagens assíncronas chamadas de intent (intenção). Intents conectam componentes individuais com outros componentes em tempo de execução (você pode pensar neles como mensageiros que requisitam uma ação de outros componentes, quer o componente pertença à sua aplicação ou  outra.

Um intent é criado com um objeto Intent, que define uma mensagem para ativar um componente específico ou tipo específico de componente - um intent pode ser explícito ou implícito, respectivamente.

Para activities e servicesm um intent define a ação a ser executada (por exemplo, para ver ou enviar algo) e pode especificar a URI do dado para agir sobre (ou outras coisas que o componente a ser iniciado precisa saber). Por exemplo, um intent pode ser uma requisição para uma activity mostrar uma imagem a ser aberta em uma página web. Em alguns casos, você pode iniciar uma activity para receber um resultado, neste caso, a activity também retorna o resultado como um Intent (por exemplo, você pode criar um intent para pegar contatos pessoais e ter eles retornados para você - o intent de retorno inclui a URI apontando para o contato escolhido).

Para broadcast receivers, o intent simplesmente define a notificação sendo divulgada (por exemplo, uma notificação que indica que a bateria do dispositivo está baixa inclui somente uma string que indica "bateria baixa").

O outro tipo de componente, content provider, não é ativado por intents. Ao invés disso, ele é ativado quando alvejado por uma requisição de um ContentResolver. O content resolver manipula todas transações diretas com o content provider para que o componente que está executando as transações com o provider não precise fazê-lo e ao invés disso chame métodos no objeto ContentResolver. Isto deixa uma camada de abstração entre o content provider e o componente requisitando a informação (por segurança).

Existem métodos separados para ativar cada tipo de componente:

  • Você pode iniciar uma activity (ou dar algo novo pra ela fazer) passando um Intent para startActivity() ou startActivityForResult() (quando você quer que a activity retorne um resultado).
  • Você pode iniciar um service (ou dar novas instruções a um service em execução) passando um Intent para startService(). Ou você pode ligar ao service passando um Intent para bindService().
  • Você pode iniciar um broadcast passando um Intent para métodos como sendBroadcast(), sendOrderedBroadcast(), ou sendStickyBroadcast().
  • Você pode executar uma consulta a um content provider chamando query() em um ContentResolver.

Mais informações sobre o uso de intents serão vistos em posts futuros, bem como a ativação de componentes específicos.

O Arquivo Manifest

Antes do sistema Android poder iniciar um componente de aplicação, o sistema deve saber que o componente existe lendo o arquivo AndroidManifest.xml da aplicação (o arquivo "manifest"). Sua aplicação deve declarar todos seus componentes neste arquivo, que deve estar na raix do diretório do projeto da aplicação.

O manifest faz um número de coisas em adição à declaração de componentes da aplicação, como:

  • Identificar quaisquer permissões de usuário necessárias à aplicação, como acesso à Internet ou acesso de leitura nos contatos do usuário.
  • Declarar o API Level mínimo necessário pela aplicação, baseado nas APIs que a aplicação usa.
  • Declarar as características de hardware e software usadas ou requeridas pela aplicação, como câmera, serviço de bluetooth, ou tela multitouch.
  • Bibliotecas de API necessárias para a execução (além das nativas das APIs do framework Android), como a biblioteca do Google Maps.
  • E muito mais.

Declarando Componentes

A tarefa primária do manifesto é informar ao sistema sobre os componentes da aplicação. Por exemplo, um arquivo de manifesto pode declarar uma activity como segue:

<?xml version="1.0" encoding="utf-8"?>
<manifest ... >
   
<application android:icon="@drawable/app_icon.png" ... >
       
<activity android:name="com.example.project.ExampleActivity"
                 
android:label="@string/example_label" ... >
       
</activity>
        ...
   
</application>
</manifest>

No elemento <application>, o atributo android:icon aponta para o recurso de um único que identifica a aplicação.

No elemento <activity>, o atributo android:name especifica o nome completo da subclasse de Activity e o atributo android:label especifica a string a ser usada no rótulo visível ao usuário para a activity.

Você deve declarar todos componentes da aplicação desta maneira:

  • elementos <activity> para activities
  • elementos <service> para services
  • elementos <receiver> para broadcast receivers
  • elementos <provider> para content providers

Activities, services, e content providersque você incluir no seu fonte mas não declarar no manifesto não estão visíveis para o sistema e, consequentemente, nunca podem rodar. Entretanto, broadcast receivers podem ser declarados no manifesto ou criados dinamicamente no código (como objetos BroadcastReceiver) e registrados no sistema chamando registerReceiver().

Veremos mais detalhes do arquivo de manifesto em posts futuros.

Declarando Capacidades dos Componentes

Como discutido acima, você pode usar um Intent para iniciar activities, services, e broadcast receivers. Você pode fazê-lo explicitamente nomeando o componente alvo (usando o nome de classe do componente) no intent. Entretanto, o verdadeiro poder dos intents reside no conceito de ações intencionais (intent actions). Com intent actions, você simplesmente descreve o tipo da ação que você quer executar (e opcionalmente, os dados que você deseja que sejam utilizados) e permite ao sistema encontrar um componente no dispositivo que possa executar a ação e iniciá-la. Se existem múltiplos componentes que possam executar a ação descrita pelo intent, então o usuário seleciona qual quer usar.

A maneira do sistema identificar os componentes que podem responder a um intent é comparando o intent recebido com os filtros de intenção (intent filters) providos no XML de manifesto de outras aplicações no dispositivo.

Quando você declara um componente no manifetso de sua aplicação, você pode opcionalmente incluir intent filters que declaram as capacidade do componente para que ele possa responder a intents de outras aplicações. Você pode declarar um intent filter para seu componente adicionando um elemento <intent-filter> como nó filho do elemento de declaração de um componente.

Por exemplo, uma aplicação de e-mail com um activity de compor um novo e-mail pode declarar um intent filter em seu manifesto para responder a intents "send" (para enviar e-mails). uma activity na sua aplicação pode então criar um intent com a ação “send” (ACTION_SEND), que o sistema irá combinar com a activity "send" da aplicação de e-mail e lançá-la quando você invocar o intent com startActivity().

Mais informações sobre criar intent filters serão discutidas futuramente.

Declarando Requisitos da Aplicação

Existem uma infinidade de dispositivos rodando Android e nem todos provêem as mesmas características e funcionalidades. Para prevenir que sua aplicação seja instalada em dispositivos que não possuem as características necessárias, é importante definir claramente um perfil de tipos de dispositivos que suportam sua aplicação declarando os requisitos de hardware e software no seu arquivo de manifesto. A maioria destas declarações são informacionais somenyte e o sistema não lê elas, mas serviços externos como o Android Market, visando fornecer serviço de filtragem aos usuários utilizam.

Por exemplo, se sua aplicação requer uma câmera e usa as APIs introduzidas no Android 2.1 (API Level 7), você deve declarar estes requisitos no seu manifesto. Desta forma, dispositivos que não possuem uma câmera e tem uma versão de Android inferior à 2.1 não podem instalar sua aplicação pelo Android Market.

Entretanto, você também pode declarar que sua aplicação usa câmera, mas que ela não é obrigatória. Neste caso, sua aplicação deve executar uma checagem em tempo de execução para determinar se o dispositivo possui uma câmera e desabilitar quaisquer características que usam a câmera se ela não estiver disponível.

Aqui estão algumas características importantes dos dispositivos que você deve considerar quando projeta uma aplicação:

Tamanho e Densidade de Tela

Para categorizar dispositivos pelo seu tipo d etela, Android define duas características para cada dispositivo: tamanho de tela (as dimensões físicas da tela) e densidade de tela (a densidade física dos pixels na tela, ou dpi - pontos por polegada). Para simplificar todos os tipos diferentes de configurações de tela, o sistema Android generaliza em grupos que tornam mais simples a declaração.

Os tamanhos de tela são: small, normal, large, e extra large.
As densidades de tela são: low density, medium density, high density, e extra high density.

Por padrão, sua aplicação é compatível com todos os tamanhos e densidades de telas, porque o sistema Android faz os ajustes apropriados para seu layout de UI e recursos de imagem. Entretanto, você deve criar layouts especializados para certos tamanhos de telas e prover imagens específicas para certas densidades, usando recursos alternativos de layout, e declarando no seu manifesto exatamente quais tamanhos de tela sua aplicação suporta com o elemento <supports-screens>.

Mais informações em breve.

Configurações de Entrada

Muitos dispositivos provêem um tipo diferente de mecanismo de entrada, como teclado, trackball, ou botões de navegação. Se sua aplicação requer um hardware de entrada específico, entãao você deve declarar no seu manifesto com o elemento <uses-configuration>. Entretanto, é raro uma aplicação que requer certo tipo de configuração de entrada.

Características do Dispositivo

Existem muitas características de hardware e software que podem ou não existir em um dado dispositivo Android, como uma câmera, sensor de luz, bluetooth, versão de OpenGL específica ou fidelidade do touchscreen. Você nunca deve assumir que uma certa característica está disponível em todos dispositivos Android (exceto as disponíveis na biblioteca padrão do Android), então você deve declarar quaisquer características usadas pela sua aplicação com o elemento <uses-feature>.

Versão da Plataforma

Dispositivos Android diferentes muitas vezes rodam versões diferentes da plataforma Android, como Android Android 1.6 ou Android 2.3. Cada versão sucessiva inclui APIs adicionais não disponíveis em versões anteriores. Para indicar qual grupo de APIs está disponível, cada versão especifica um API Level (por exemplo, Android 1.0 é API Level 1 e Android 2.3 é API Level 9). Se você usa quaisquer APIs que foram adicionadas nas versões superiores à 1.0, você deve declarar um API Level mínimo no qualestas APIs foram introduzidas usando o elemento <uses-sdk>.

É importante que você declare todos os requisitos para sua aplicação, porque, quando você distribui sua aplicação no Android market, ele usa estas declarações para filtrar quais aplicações estão disponíveis para cada dispositivo. Desta forma, sua aplicação deve estar disponível somente para os dispositivos que estão de acordo com os requisitos da mesma.

Mais informações sobre os filtros de aplicação do Android Market serão dados futuramente.

Recursos da Aplicação

Uma aplicação Android é composta por mais do que somente código - ela requer recursos que estão separados de código fonte, como imagens, arquivos de áudio, e qualquer coisa relacionada à apresentação visual da aplicação. Por exemplo, você deve definir animações, menus, estilos, cores, e o layout das interfaces de usuário da activity com arquivos XML. Usar recursos de aplicação torna mais fácil atualizar várias características de sua aplicação sem ter de modificar o código além de prover grupos de recursos alternativos que servem para otimizar sua aplicação para uma variedade de configurações de dispositivos (como linguagens diferentes e tamanhos de tela).

Para cada recurso que você inclui no seu projeto Android, as ferramentas de compilação do SDK definem um ID inteiro único, que você pode usar para referenciar o recurso no código da sua aplicação ou de outro recursos definido no XML. por exemplo, se sua aplicação contém um arquivo de imagem chamado logo.png (salvo no diretório res/drawable/), as ferramentas do SDK geram um ID de recurso chamado R.drawable.logo, que você pode usar para referencuar a imagem e inseri-la na interface do usuário.

Um dos aspectos mais importantes de prover recursos separados de seu código fonte é a habilidade de você fornecer recursos alternativos para diferentes configurações de dispositivos. Por exemplo, definindo strings da UI em XML, você pode traduzir as strings para outro idioma e salvar estas strings em arquivos separados. Então, baseado no qualificados de idioma que você anexou ao nome do diretório do recurso (como um res/values-fr/ para strings em francês) e as configurações de idioma do usuário, o sistema Android aplica o idioma apropriado na sua interface.

Android suporta muitos qualificadores diferentes para seus recursos alternativos. O qualificador é uma string curta que você inclui no nome dos seus diretórios de recursos visando definir as configurações do dispositivo para as quais estes recursos devem ser usados. Como outro exemplo, você deve muitas vezes criar diferentes layouts para suas activities, dependendo da orientação e tamanho d atela do dispositivo. Por exemplo, quando a tela do dispositivo está em modo vertical (retrato), você pode querer um layout com botões verticais, mas quando a tela está na horizontal (paisagem), os botões devem ser alinhados horizontalmente. Para mudar o layout dependendo da orientação, você pode definir dois diferentes layouts e aplicar o qualificador apropriado em cada nome de diretório de layout. Então, o sistema automaticamente aplica o layout apropriado dependendo da orientação atual do dispositivo.

Eu sei que tudo isso é muito superficial, mas espero que tenha gostado, e aos poucos vamos explorando esta nova plataforma que cresce cada vez mais!

Tags: , ,

Android | Mobile

Powered by BlogEngine.NET 1.6.1.0
Design por Laptop Geek, adaptado por onesoft e personalizado por mim.