Animações no Android Part 1 – View Animations

Standard

Com o surgimento do material design no android L vários princípios de design foram criados e dentre eles um dos mais interessantes e o Meaningful Motion.

De forma muito rápida e resumida, Meaningful Motion ou em uma tradução directa, Movimentações com sentindo explica que em uma app, os componentes devem mover-se de forma que dêem uma pista visual ao utilizador sobre o efeito causado pela sua interacção com um determinado componente. Como exemplo disto podemos olhar para a animação que acontece no momento em que fazemos swipe para a direita para marcar  em um e-mail para marcar como lido no inbox, facilmente temos uma pista visual de que aquele elemento esta a sair de cena devido ao movimento do componente para a direita e seu desaparecimento.

A pesar deste principio ter sido muito enfatizado nos últimos meses com a introdução do Material design e boom de apps com animações super interessantes como mostra este showcase das melhores apps com material design em 2015, o android ja possuía mecanismos de animação de componentes bem antes do material design que no fundo consistem na base por detrás dos novos mecanismos utilizados nas super animações em algumas apps no video acima.

Como mencionei acima, o android possui 2 sistemas de animações nomeadamente:

Property Animation que nos permite animar as propriedades de um certo objecto sem que seja necessariamente um componente que ira aparecer na nossa UI(Uma view) e View Animation que é especificamente para animar Views(TextViews,Buttons, etc).

Este post está divido em 3 partes e irá consistir basicamente na explicação dos dois primeiros sistemas de animação mencionados acima e exemplos de como implementar animações cools como as que temos hoje em dia.

View Animation

Para este primeiro post, iremos falar sobre o View animation.

Como brevemente explicado acima, o View Animation System permite-nos animar propriedades de uma View como alpha(visibilidade), scale(tamanho), rotation(rotação), translation(movimentação) de forma individual ou ainda coordenar a animação destas diferentes propriedades de forma sequencial ou simultânea.

A razão pelo qual escolhi este primeiro sistema para iniciar a série, é pelo simples facto deste sistema estar disponível no framework desde as versões mais antigas do framework e acredito que seja a forma mais simples de estabelecer o contacto com um mundo das animações.

Para realizar uma animação sobre uma view utilizando este sistema, podemos fazer de 2 maneiras diferentes:

Definindo a animação no XML

Definir animações pelo XML e super simples e para o fazer basta:

  1. Criar uma pasta dentro da pasta res com o nome anim onde ficaram guardados os ficheiros de xml que definem uma animação.

animfodler

2. Criar um ficheiro XML dentro da pasta anim como mostra a imagem acima. É neste ficheiro que iremos definir qualquer animação que queiramos aplicar sobre uma view. A tag de raiz deste ficheiro pode ser uma animação em especifico como <alpha>(visibilidade), <scale>(tamanho),<rotate>(rotação), <translate>(movimentação horizontal no eixo do X ou vertical no eixo do Y) ou <set> que permite definir e coordenar diferentes animações.

Olhando para a imagem acima e explicando só a animação de visibilidade ou alpha, termos o ficheiro fade_animation.xml com a seguinte estrutura e conteúdo:

<?xml version="1.0" encoding="utf-8"?>
<alpha xmlns:android="http://schemas.android.com/apk/res/android"
    android:fromAlpha="1"
    android:toAlpha="0"
    android:duration="500"
    >
</alpha>

Como mencionei acima este ficheiro represente uma só animação e temos como a tag de raiz, a animação que pretendemos com atributos específicos que iram definir o seu comportamento. Neste exemplo, os atributos fromAlpha, toAlpha e duration representam a visibilidade  da View no inicio da animação que pode variar de 0(transparente) a 1(totalmente opaco), a visibilidade no fim da animação e a duração  da animação em milisegundos. Cada tipo de propriedade que podemos animar contem atributos diferentes e podem ver com mais detalhes no código disponibilizado no fim do post.

3. No nosso código java, temos só de carregar esta animação utilizando o método loadAnimation disponível na classe AnimationUtils como mostra o sample abaixo:

/*inicia uma animacao sobre uma view passando a view e o id da animacao que e o 
nome do ficheiro xml na pasta anim.*/
public void runAnimationFromXml(View view, int animResId){
    Animation animation = AnimationUtils.loadAnimation(this,animResId);
    view.startAnimation(animation);
}

E com 3 simples passos, vimos como definir e aplicar uma animação sobre uma view.

Uma limitação deste sistema de animações é que ele aplica animação sobre a view mas não modifica ou actualiza os valores no final da animação , isto é, se estivermos a fazer uma animação em que movemos um botão na horizontal 200dp, o botão ira movimentar-se e no fim ao clicar na nova posição em que conseguimos ver o botão,nada ira acontecer pois este não foi realmente desenhado na nova posição que deveria estar.

A forma de resolver isto seria calcular o valor da posição onde o botão estará e actualizar o botão invalidando a posição anterior e desenhando a nova no método onDraw()(Não liguem para isto agora). Este é um dos tópicos que irei abordar com mais detalhes no próximo post sobre o outro sistema de animações e demonstrar porque este é melhor que o que acabamos de ver.

A segunda forma de definir animações directamente pelo código java, passa por utilizar as classes disponíveis como AlphaAnimation, TranslateAnimation dentre outras que seguem o mesmo padrão <nomeDaPropriedade>+Animation para atingir o mesmo efeito. Neste post não irei falar sobre esta forma pois apesar de não ser muito prática, acho que deixa o código muito feio algo que podemos evitar com o primeiro método:)

E de forma muito simples e rápida conseguimos introduzir a um dos tópicos considerado complicado no android(ja foi para mim).
Espero por vocês para as próximas partes e ate la deixem o vosso comentário e partilhem com um amigo que acham que gostaria de ler este post 🙂

Aqui vai um gist com as partes relevantes e mais exemplos : https://gist.github.com/realdm/40ad4b0d121066be499c

DM

Advertisements

Desenvolvendo para Android – Utilizando Loaders

Standard

Hello para todos os devs, espero que todos estejam muito bem e aprendendo com esta série sobre desenvolvimento para android/ Para quem esteja começando a embarcar no mundo do bonequinho verde sugiro que veja o inicio da serie neste POST

Dando continuidade ao que temos vindo a aprender, hoje irei escrever sobre uma API, que vem disponível por defeito na plataforma mas infelizmente é muito pouco utilizada pelos desenvolvedores.

Falo da Loaders API, que é uma API que oferece mecanismos para efectuar o carregamento de dados de forma assíncrona (Para quem quiser, tem uma boa descrição sobre Main / UI thread e background operations AQUI  ).

Como disse acima, a Loaders API foi inicialmente introduzida no framework na versão do Android 3.0 e posteriormente introduzida na android support library v4 para que pudesse ser utilizada em versões inferiores. Esta API vem com varias vantagens comparadas ao AsyncTask e possui as seguintes características:

  • Disponiveis para todos Fragments e Activities: Diferentemente dos AsyncTasks, os Loaders estão ligados ao ciclo de vida das Activities ou Fragments, o que significa que se a Activity é obstruída por outra e vai para o estado onStop, o loader também será parado.
  • Monitoram a fonte de dados: Os loaders, permitem monitorar a fonte de dados a que estão ligados, permitindo que no momento que este verifica uma mudança nos dados, ele ira automaticamente enviar os novos dados para serem actualizados na UI.
  • Carregam a ultimo Loader criado:  Voltando para o primeiro ponto das características dos loaders, porque estas estão ligadas ao ciclo de vida das Activities ou Fragments, se uma Acitivity mudar de configuracao (Orientação de Portrait  para Landscape), no momento que a Activity for recriada, o loader ira pegar a ultima instância que contem os dados carregados antes da Activity ser destruída e voltar a apresentar a UI.

Ao longo deste post, irei demonstrar como e onde implementei os loaders durante o projecto MyMovieApp do nanodegree do udacity.

Durante o desenvolvimento do MyMovieApp do udacity, deparei-me com dois momentos que precisava de carregar dados e apresentar na UI.

  1. Precisava de carregar os filmes mais populares e mais votados a partir da API do themoviedb.com.
  2. Uma vez marcados como favoritos, os filmes eram guardados na base de dados e ao seleccionar  filmes favoritos, estes tinham de ser carregados e apresentados na UI.

A Loaders API oferece a class Loader que pode ser extendida de acordo com a funcionalidade(tipo de dados que pretendemos carregar) que se quer dar ao loader. Tomando como exemplo os 2 pontos citados acima, durante a implementação no projecto utilizei duas classes classes que estendem a classe  Loader (AsyncTaskLoader e CursorLoader)

Começando pela classe AsyncTaskLoader, a definição é que esta classe é um loader que oferece uma AsyncTask para efectuar operacoes em uma background thread. Como nas AsyncTasks, esta classe requer que o metodo doInBackground() seja implementado pois é dentro deste método que devemos realizar as operações que podem levar muito tempo.(descodificar bitmaps, Carregar informação da cloud etc).

A implementacao deste loader é muito simples e para tal basta seguir os passos abaixo:

  1. Criar uma classe e extender a class AsyncTaskLoader.
  2. Especificar o tipo de dados que o loader deve retornar assim que acabar de fazer os seu trabalho.
  3. implementar a logica para realizar o trabalho dentro do método doinBackground.
  4. Retornar o tipo de dados especificado na definicao do loader dentro do método doInBackground.
//Extender a class AsyncTaskLoader e especificar o tipo de dados a ser retornado
public class MovieAsyncLoader extends AsyncTaskLoader<List<Movie>> {

    private Context mContext;
    
    public MovieAsyncLoader(Context context, String queryType) {
        super(context);
        mContext = context;
    }

    @Override
    public List<Movie> loadInBackground() {

        //Implementar toda logica e retornar uma lista de filmes
        List<Movie> movies = new ArrayList<Movie>();

        return movies;
    }

}

Seguidos os passos, temos um AsyncTaskLoader rapidamente criado e com a logica para carregar os dados implementada dentro do metodo doInBackground como mostra o codigo acima. O código completo utilizado no MyMooviApp Encontra-se AQUI.

Os próximos passos a seguir são: inicializar o loader, deixar que este faca o trabalho, mostrar os dados na UI no fim do trabalho.

Como mencionado acima os loaders so podem existir dentro de uma Activity ou Fragment. Este requesito leva-nos a mais uma classe dentro desta API denominada LoaderManager.

O LoaderManager é uma classe abstracta e esta directamente associada as Activities our Fragments para gerir uma ou mais instâncias de Loaders dentro da aplicação. Uma aspecto a tomar em consideracao e que uma Activity ou Fragment só pode ter um LoaderManager. Esta classe Loader Manager, possui uma interface chamada LoaderCallbacks que como o nome sugeri, define métodos de callback que serão utilizados para  interagir com o Loader.

Os três métodos de callback que tem de ser rescritos são:

  • onCreateLoader –  Este método e invocado assim que e especificado o metodo initLoader para  inicializar um loader. A sua implementação é a criação de um Loader que será retornado ao loader manager para ser inicializado logo de seguida pelo LoaderManager.
  • onLoadFinished: Este método é invocado assim que o  loader acaba de fazer o trabalho e os resultados são enviados de volta para UI thread. Neste método podemos interagir com a UI e passar os dados para um adapter  ou qualquer outro componente.
  • onLoadReset : Este método serve para reiniciar o loader e dar o comando para reiniciar o trabalho. fazer o initLoader tambem tem o mesmo efeito entretanto ao faze-lo dessa forma, o loader manager vai pegar a instância antiga do loader e re-apresentar os dados que ja tinham sido carregados anteriormente.

Com os métodos todos implementados, o ultimo passo para executar o loader, temos de  pegar o loader manager e invocar o método initLoader. Este método recebe  3 parâmetros:

  • Loader ID :Um inteiro que será utilizado pelo loader manager para identificar o loader que este tem de iniciar ou fazer restart.
  • Bundle : Este bundle é utilizado para passar um conjunto de informações para o loader. Por exemplo no  MyMovieApp passei um bundle onde coloquei uma string com com o tipo de query a realizar (Popular, top Rated , Favorite);
  • Callback methods : Como ultimo parâmetro temos de passar uma referencia aos métodos de callback que temos implementados. Como normalmente implementamos na definicao da Activity ou Fragment, podemos simplesmente passar este parametro como this.
getLoaderManager().restartLoader(LOADER_ID, bundle, this)
public class BlogLoadersActivity extends AppCompatActivity implements LoaderManager.LoaderCallbacks<List<Movie>> {

    private GridView moviesGrid;

    private final int LOADER_ID=1;

    BlogCursorAdapter mMoviesAdapter;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_blog_loaders);

        moviesGrid = (GridView)findViewById(R.id.movies_grid);

        moviesGrid.setAdapter(mMoviesAdapter);

        Bundle b = new Bundle();
        b.putString("QueryType","favorite");
        //inicializa o loader passando o id, o bundle com informacao
        getSupportLoaderManager().initLoader(LOADER_ID, b,this);
    }

    @Override
    public Loader<List<Movie>> onCreateLoader(int id, Bundle args) {

        //Extraimos os dados do Bundle
        String queryType = args.getString("QueryType");

        //Inicializa e o loader e retorna ao loader Manager
        return new MovieAsyncLoader(this,queryType);
    }

    @Override
    public void onLoadFinished(Loader<List<Movie>> loader, List<Movie> data) {

        //verifica se a lista e recebida e null
        if(data!=null){
            //popular os dados na Aqui
            //definir os dados no adapter etc.
            //mAdapter.swapData(data);

        }
    }

    @Override
    public void onLoaderReset(Loader<List<Movie>> loader) {

    }
}

Com o código acima, consegui resolver o primeiro problema de conexão a API utilizando AsyncTasksLoader. A implementacao ompleta do fragment utilizado no projecto encontra-se AQUI.

Passando para o segundo momento em que precisava de carregar dados através de um Content Provider, após aprender sobre AsyncTaskLoaders poderia implementar essa funcionalidade da mesma forma apenas mudando o tipo de dados para Cursor mas o framework ja dispõe de um Loader que retorna um Cursor denominado CursorLoader.

A utilização do CursorLoader  bastante simples e para poder utilizar é preciso garantir os seguintes requisitos:

  • Ter o Content provider devidamente criado – Para quem nao sabe como o fazer pode ver o post anterior AQUI.
  • Ao implementar os LoaderCallbacks na Activity ou fragment, definir o Cursor como tipo de dados a retornar :
    public class BlogLoadersActivity extends AppCompatActivity implements LoaderManager.LoaderCallbacks<Cursor>
  • Implementar os métodos de callbacks explicados mais acima.
  • Ao implementar o metodo onCreateLoader, devemos inicializar e retornar um CursorLoader e por fim executar. PS: Os parâmetros passados ao CursorLoader, são similares aos que são passado ao invocar o método query do contentresolver como vimos no POST Anterior quando falávamos de providers.

    Com a simples implementação do AsyncTaskLoader e  CursorLoader, chegamos ao fim de mais um post e deste modo ja podemos ate agora construir uma app que descarrega dados da cloud, armazena a informação no dispositivo, oferece um mecanismo de leitura de dados independente da forma como estes foram armazenados e mais do que tudo consegue realizar todas estas operações de forma eficiente e seguindo as boas praticas.

Espero que tenham gostado do post e ate a próxima !

Links : Documentação oficial sobre Loaders

DM 🙂

Material Goodies – Utilizando o CoordinatorLayout com o Toolbar

Standard

Hello Devs,  sejam todos muito bem vindos a mais um post sobre desenvolvimento para android. Com este post, vamos começar uma serie chamada Material Goodies, em que iremos implementar aqueles pequenos detalhes do material design que tornam apps incríveis e que os utilizadores não terão outra opção senao amar:).

Durante o IO15, foi anunciada e lançada a android design support library com o intuito de facilitar a vida dos desenvolvedores ao oferecer formas simples, rápidas e práticas de implementar o material design para que sejam compatíveis as versões anteriores ao Lolipop.  Esta biblioteca veio cheia de novidades como o NavigationView  que é uma forma fácil de implementar o NavigationDrawer( Usaremos no próximo post para actualizar o post anterior sobre a support library), a SnackBar, FAB(Floating Action Button), CoordinatorLayout o componente que utilizaremos neste post dentre outros.

Começaremos o material utilizando o CoordinatorLayout, pois foi um dos primeiros componentes da design support library que utilizei no momento em que ia implementar o Details screen da segunda fase da app do nanodegree do android e o resultado foi  o seguinte:

Screenshot_20150715-203246

Screenshot_20150715-203231

Entrando ja para os detalhes de implementação irei começar por falar sobre o CoordinatorLayout. O CoordinatorLayout  é um componente introduzido no android design support library e é um layout que permite maior controle dos eventos de cliques e animações na UI isto significa que podemos controlar como cada componente na UI ira se comportar ao receber um evento de click ou scroll em relação a todos os outros componentes  na UI. Este componente pode ser usado de diferentes formas fazendo com que o limite esteja apenas na cabeça do desenvolvedor.

O primeiro passo antes de passar para o código e garantir que temos as dependências bem especificadas no nosso build.gradle do module app como vem abaixo:

dependencies {
    compile fileTree(dir: 'libs', include: ['*.jar'])
    compile 'com.android.support:appcompat-v7:22.2.1'
    compile 'com.android.support:design:22.2.0'
    compile 'com.squareup.picasso:picasso:2.5.2'
    compile 'com.android.support:cardview-v7:22.2.0'
    compile 'com.android.support:recyclerview-v7:22.2.0'
}

Para atingir o objectivo super cool das imagens acima, neste post iremos utilizar o CoordinatorLayout e a AppBar que era antigamente conhecida como ActionBar e agora é composta pela statusBar, Toolbar, Tab/Search Bar e Um Flexible Space como mostra a imagem abaixo tirada das especificações no GUIDE criado pela google(Aconselho que se de uma vista de olhos).

O link acima e as imagens não são referentes a um guide do AppBar mas sim a scrolling techniques  que explica como cada parte do AppBar se deve comportar ao fazer o scroll de forma a oferecer uma boa experiência de utilizador. Volto a aconselhar que entrem para o link e vejam os vídeos associados a cada possível técnica :).

Dado isto, o primeiro passo para criar este efeito incrivel é definir o layout como mostra abaixo:

<android.support.design.widget.CoordinatorLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <FrameLayout
        android:id="@+id/details_container"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        app:layout_behavior="@string/appbar_scrolling_view_behavior"
        android:padding="8dp"/>

    <android.support.design.widget.AppBarLayout
        android:layout_height="wrap_content"
        android:layout_width="match_parent">

        <android.support.design.widget.CollapsingToolbarLayout
            android:layout_width="match_parent"
            android:id="@+id/collapsingToolbar"
            android:layout_height="wrap_content"
            app:layout_scrollFlags="scroll|exitUntilCollapsed"
            app:contentScrim="?attr/colorPrimary">

            <include layout="@layout/layout_movie_details_header" android:id="@+id/headerLayout"
                app:layout_scrollFlags="scroll"/>

            <android.support.v7.widget.Toolbar
                android:id="@+id/toolbar"
                android:layout_height="?attr/actionBarSize"
                android:layout_width="match_parent"
                app:layout_collapseParallaxMultiplier="0.7"
                app:layout_collapseMode="pin"/>
        </android.support.design.widget.CollapsingToolbarLayout>

    </android.support.design.widget.AppBarLayout>


</android.support.design.widget.CoordinatorLayout>

Entrando em detalhes para o layout nesta imagem, encontramos o CoordinatorLayout como o layout mais alto da hierarquia(parent) e dentro dele temos os seguintes componentes que são de extrema importância:

  • AppBarLayout: AppBarLayout e o layout onde encontramos o toolbar e todos outros componentes bem explicados acima e referenciados ao guide de scrolling techniques. Dentro do AppBar, encontramos um CollapsingToolbarLayout que é responsável por ajudar a criar transições e animações fixes dos componentes que colocamos dentro delas quando a activity recebem eventos de scroll.

Ao CollapsingToolbarLayout e todos os componentes que queremos que se movam ao receber um evento de scroll, devemos definir o atributo layout_scrollFlags  que ira especificar como determinada view ira se comportar. As flags existentes são:

scroll: flag definida a todas as views que queremos que movam-se ao mover ao fazer scroll do conteúdo da activity.

enterAlways: flag que garante que ao fazer o scroll para baixo, a view voltara a ficar visível.

enterAlwaysCollapsed: flag que indica que a view sempre ira ser apresentada com o valor definida pelo atributo minHeight que representa a mínima altura que esta pode ter.

exitUntilCollapsed: flag que indica que ao fazer scroll do conteúdo no sentido que a view ira desaparecer, ela diminua o tamanho ate ao mínimo predefinido.

Seguindo o que esta acima, no ficheiro acima definimos as scroll flags para o CollapsibleToolbarLayout e o layout que representa o header(A imagem e o rating das figuras acima). Nota: E possivel escrever o layout do header directamente no ficheiro activity_main.xml mas por questões de performance especificamente falando da hierarquia profunda que isto causaria(possivel de ver no Hierarchy viewer) achei melhor fazer o include. A view do toolbar é a única que aparece sem o atributo do scrollFlag e por essa razão é o ultimo componente a ser colocado dentro desta hierarquia. Não temos o scroll no Toolbar porque não queremos que ele se mova e que esteja presente quando o header desaparecer no scroll. Para garantir que a toolbar fica sempre la, devemos definir o atributo layout_collapseMode=”pin”.

  • Content Container: Esta view, representada  no nosso exemplo pelo fragment, é que vai conter o conteudo que mandatoriamente deve estar dentro de um Layout com a possibilidade de fazer scroll como o RecyclerView e o NestedScrollView. Infelizmente utilizar o ListView ou GridView nao funciona para este caso e não é motivo de preocupação pois estes dois layouts podem ser implementados utilizando o RecyclerView e definindo o LayoutManager apropriado :). A este layout que ira receber o conteúdo, temos de sempre colocar a linha :
    app:layout_behavior="@string/appbar_scrolling_view_behavior"

    para informar que e desta view que estamos a espera e receber eventos de scroll.

chega a ser muito estranho ter de dizer que o essencial do post acaba aqui mas sim e exactamente isso para atingir o efeito das imagens acima não precisamos de mais código e nem mais configurações…SIMPLESMENTE SIMPLES :).

Para terminar o post e ter um exemplo funcional so nos restam duas coisas:

  1. Criar um fragment com um RecyclerView dentro a representar o conteúdo que um dia poderemos ter. gists : fragment_layout_dummy.xmlDummyFragmentlayout_dummy_card.xml
  2. Na classe da activity, preencher os dados do header(fotos e texto) e por fim colocar dinamicamente o fragment criado no FrameLayout da activity reservado ao conteúdo. Gist: MainActivity.java

Desta forma chegamos mesmo ao fim do primeiro post sobre Material Goodies e ficarei feliz em receber de voces requests de posts sobre alguma coisa incrivel do material design etc.

Espero por vocês no próximo post 🙂

Link : Código Completo

DM

Desenvolvendo para Android – Como Implementar Content Providers

Standard

Hello Team, Ja vai algum tempo desde o ultimo  pois  o tempo ficou meio curto para escrever  principalmente depois de ter começado o  nanodegree do Udacity que tem sido bastante animado, tenho aprendido varias novas técnicas no android e o melhor de tudo é poder fazer novos amigos dentro dos grupos e forums de discussões.

Para quem queira começar o desenvolvimento de apps para android ou levar os conhecimentos que ja tem ao próximo nível, pode dar uma olhada nos seguintes cursos Android Fundamentals e Android Nanodegree.

Voltando para a jornada que faziamos, no ultimo post estivemos a falar sobre como persistir os dados para a utilização offline logo após de descarregar da cloud.

Até então demos um passo realmente importante para garantir uma boa experiência de utilizadores pois em países como Moçambique( Meu amado pais) e outros países africanos onde a conectividade a Internet não é estável e disponível para todos, o utilizador poderá ver as informações mais importantes mesmo quando a ligação a internet não esta disponível. Sendo especifico, o ultimo post focou-se nos seguintes pontos:

  • Como criar um contracto que contem a informação sobre as tabelas da nossa base de dados.
  • como usar o SQLiteOpenHelper para criar a base de dados com as tabelas definidas no contracto.
  • Como usar o android testing framework para poder testar se os dados estão a ser inseridos e lidos devidamente.

Com o os pontos mencionados acima, podemos criar uma boa experiência offline, fazendo a inserção e leitura dos dados ao SQLite de forma directa utilizando os métodos expostos pela class SQLiteDatabase.

Esta forma é bem rápida e fácil de implementar mas desvantagiosa pois em casos em que queremos partilhar as informações na nossa base de dados com outras aplicações (Exemplo: a app de contactos e o calendário partilham os seus dados para outras aplicações) a outra aplicação não só teria de saber que tipo de dados precisa mas como a leitura e escrita desses dados foi feita do nosso lado.

Felizmente, no android foi criado um componente denominado Content Provider que permite que apps possam partilhar informações umas  com as outras, encapsulando todo o código assim como o tipo de armazenamento utilizado para a escrita e leitura de dados fazendo com que os desenvolvedores da outra app só precisem saber qual a Uri(ja falamos sobre isso) para a informação que desejam.

Sendo assim se quiséssemos obter na nossa aplicação um filme guardado no dispositivo através de um Content Provider, seria desencadeado o seguinte processo:

  1. Especificamos a Uri, ou por outras palavras um caminho que identifica os dados no Content Provider. Um exemplo de uma Uri e a seguinte String  : content//com.app.mymooviapp/movie/2  que representa um filme com o id 2 dentro de uma tabela movie. Esta  Uri assim como as outras contem 2 partes importantes em que a parte ‘com.app.mymooviapp’  o content authority que representa o nome de todo provider e a parte ‘/movie/2′   que representa o path,o caminho para as tabelas e neste caso em concreto para um dado existente na tabela.
  2. A Uri especificada e(add acento) mais a operação que desejamos efectuar(insert,delete,update) são  passados  ao Content Resolver   que será responsável por dividir a Uri, pegar o content Authority  para procurar pelo Provider na lista conhecida pelo sistema e após encontrar o provider, a partir do path conseguir realizar a operação especificada sobre o(s) dados no path.

A questão que viria logo após o ultimo paragrafo seria como e que o sistema tem conhecimento do nosso Content provider e a content authority.

A resposta para essa pergunta é que assim como as Activities, os Content Providers devem ser registrados no androidmanifest e é especificado o nome da classe com a sua implementação e o content authority.

3. O content resolver nos da uma resposta de acordo com a operação que queriamos efectuar.(query  retorna Cursor, inser retorna int e mutio mais como especificado na documentação.)

Sabendo agora como funcionam os Content Providers, vamos passar para  a melhor parte que e(acento) a implementação de um content providers que será responsável por ler e escrever informações sobre os filme e para tal existem os seguintes passos que temos de seguir:

  1. Criar os contratos de dados e a base de dados.(Como no post anterior)
  2. Dentro do contracto denfir o BASE_CONTENT URI que ira representar o caminho para o “topo do provider”, e dentro de cada uma das classes internas ao contrato que representam uma tabela em outras palavras  um Content URI que representa o caminho ate a tabela.
basepath

Base Content URI. URI para o topo do content provider

Content Uri e Content type strings para a tabela Movie

Exemplo de Content Uri e Content type strings para a tabela Movie dentro do Contracto

3.Pensar e entender que tipo de leituras e escritas de dados iremos fazer para que possamos construir Uris apropriadas. Esta é a parte mais difícil do processo pois temos de conseguir pensar de antemão algumas coisas que não podem estar mais claras no principio. Um exemplo do que pensar nesta fase que veremos mais abaixo é por exemplo se vamos precisar de procurar filmes pelo titulo? pelo id? etc etc.

4. Apos pensar nas possíveis operações de leitura e escrita, devemos métodos auxiliares para gerar Uris dentro das classes correspondentes as tabelas no nosso contracto. Note que cada classe ou tabela terá diferentes métodos pois para tabelas diferentes podemos ter fazer a leitura de dados de forma diferente e com parâmetros diferentes como esta neste ficheiro de contracto disponível AQUI.

5.Com as Uris criadas, devemos criar uma classe e fazer com que ela extenda de Content Provider e registrar no android manifest( caso seja criada utilizando o wizzard será registrada automaticamente). Ao estender a classe Content Provider, esta obriga-nos a implementar alguns métodos importantes como (insert, delete, update, etc).

6.IMPORTANTE: Criar variáveis do tipo de dados inteiro que irão representar cada uma das Uri’s. (Exemplo: MOVIE_ID=100).

uri matcher variables

7. Criar um Uri matcher que será responsável por mapear os inteiros especificados no passo anterior a um determinado caminho. Ao fazer o mapeamento das Uri’s, é importante ter em conta que os  parâmetros do path ao invés de ter o nome escrito, devemos colocar um # (especifica que o parâmetro e um inteiro ou numero) ou um * (especifica que o parâmetro pode ser qualquer tipo de texto) para a parte do path que pode ser variavel. Na Uri content://com.app.mymooviapp/movie/2 o especificamos o id do filme mas em situacoes reais dentro da app esse id pode ser um numero qualquer. Sendo o id um numero variavel a Uri que apropriada para colocar no matcher deve ser content://com.app.mymooviapp/movie/*  onde no fim especificamos que vem um numero que nao sabemos qual .

Uri Matcher dentro da classe Content Provider

Uri Matcher dentro da classe Content Provider

8.Depois de fazer o match de todos inteiros as Uri’s, a magia ja esta quase pronta para acontecer e um ultimo passo antes de começar fazer aquilo que e o nosso verdadeiro objectivo de escrever e ler dados, e(acento) inicializar o content provider pelo método on create que se encontra dele mesmo. Este método e o local on o provider e inicializado durante o startup da nossa aplicação e todo processamento e feito na Main thread e como vimos no post, não podemos colocar operações pesadas dentro da main thread. O ideal aqui e fazer inicializações como criar uma instância do nosso SQLiteOpenHelper, SQLiteDatabase. Uma coisa extremamente importante neste método é que retorna um boolean que significa se o provider foi bem inicializado ou não. No caso do nosso provider, não fizemos nenhuma verificação e garantimos que o provider retorna true.

on Create dentro do Content Provider

on Create dentro do Content Provider

9. O ultimo passo da implementação do content provider, é a implementação dos métodos insert, query, update, delete que são os responsáveis por fazer a inserção, leitura, actualização e remoção dos dados respectivamente. Implementar estes métodos e relativamente fácil , mas e preciso tomar em conta o seguinte:

a. Todos estes métodos recebem uma Uri quando são invocados pelo content resolver e a primeira coisa que temos de fazer e utilizar o matcher quer criamos no passo 7 para encontrar o equivalente em inteiro a string do Uri.

b. Com o valor numérico que conseguimos ao mapear a Uri, devemos realizar um Switch case para que no mesmo método possamos tomar conta de varias Uris e realizar varias operações de forma diferente.

Exemplo de implementação do método Insert

Exemplo de implementação do método Insert

c. No fim das operações, antes de retornar o tipo de dados que cada método obriga, devemos notificar ao content resolver sobre a mudança na fonte de dados para que todos os cursores associados  e esta fonte possam actualiza-los de forma instantânea.

Notifica a mudança de conteúdo

Notifica a mudança de conteúdo

Os passos acima não são um guia definitivo, mas sim os aspectos que tomei e costumo tomar em conta no momento de implementar Content Providers. Por experiência própria, a melhor forma de aprender a implementar content providers, é implementando e lendo o código de outras implementações. Um exemplo de código super interessante de implementacao de content providers, é a aplicacao do google io 2015 iosched a qual aprendi varias coisas e encontrei classes auxiliares como Lists,Maps e SelectionBuilder(A classe ideal para remover a necessidade de pensar em detalhes de queries SQL) como poderam ver na classe final do nosso Movie Provider.

Uma outra dica no momento de implementar os content providers, e efectuar os testes de cada um dos métodos de forma individual e garantir que cada um deles, cada uma das Uri’s esta a funcionar pois ao testar no fim da implementação podemos ter erros muito difíceis de resolver principalmente nas primeiras vezes. A Classe que utilizei para testar os métodos do provider encontra-se aqui.

Espero que este post tenha aumentado o vosso arsenal como de armas ninjas como desenvolvedores para android e que seja mais um passo da emocionante e fantástica aventura que temos pela frente.

Para qualquer questão, como habitual podem postar um comentário abaixo ou agora um hangout request para qualquer dia no período das 21h as 22h (Maputo GMT +2) que ficarei feliz de vos ouvir e trocar opiniões..

Link do Projecto : MyMooviApp

Abraços

DM,

Android Support Library v22.1 – Como Comecar

Standard

No último post e o primeiro da  nova secção do blog, fiz a introdução a nova biblioteca do support v22.1 que veio melhorar a vida dos programadores permitindo implementar o material design e passar uma experiência única para todos  os dispositivos incluindo os que antecedem ao lolipop.

Para quem não teve a oportunidade de ler sobre as bibliotecas de suporte e  que novas ferramentas estão disponíveis pode fazer aqui.

Como o último post foi apenas sobre uma visão geral das novidades adicionadas,  neste post iremos olhar para o tópico de forma mais técnica e criar um novo projecto. Sendo assim, este post estará divido nas seguintes partes:

  • Como colocar as dependências para a nova biblioteca de suporte.
  • Como configurar o tema para implementar o Material design.
  • Implementar o Toolbar e Navigation Drawer.
  • Mudar cor do icon da linha seleccionada no Navigation drawer utilizando a classe DrawableCompat.

Para começar com a parte divertida do post vamos criar um novo projecto .No momento de escolher o minimumSDK, escolham a API 8 pois é do nosso interesse levar as funcionalidades novas para as versões mais antigas.

Depois de criar o projecto, temos de ir até a pasta app e clicar no ficheiro build.gradle para adicionar ou modificar as dependências de forma que possamos utilizar a nova versão da biblioteca de suporte.

Como nos criamos um novo projecto é possível ver dentro da secção dependencies { }  a linha compile ‘com.android.support:appcompat-v7:22.1.0’  como mostra a figura abaixo que indica que já temos esta dependência incluída por defeito. Para quem esta a modificar um projecto existente, basta substituir a linha similar caso exista ou copiar e colar caso não.

build.gradle

build.gradle

De seguida basta só fazer save no projecto e clicar em syncnow que aparece no canto superior direito do editor para que o gradle comece a fazer a resolução das dependências. SIMPLES 🙂

Com a nova biblioteca de suporte incluída no projecto, vamos continuar a construção do projecto passando para o passo seguinte que é a definição do tema da nossa aplicação seguindo as guidelines do material design.

Para definir temas na nossa aplicação, devemos criar um ficheiro themes.xml  que é onde estará o nosso código xml com a definição do tema.

Create Theme xml file

O ficheiro que acabamos de criar, irá conter os atributos do tema, que são suportados pelas versões que antecedem o lolipop. De forma a fazer com que o mesmos temas tenham o comportamento  incluindo as funcionalidades somente existentes no lolipop, devemos  criar uma pasta com o nome values-v21  dentro da pasta res e copiar para dentro da mesma o ficheiro themes.xml que criamos acima.

Create Values 21 folder

Criado o ficheiro, vamos colocar o conteúdo neles e definir o tema que utilizaremos na nossa aplicação e para tal  vamos copiar o código disponível nos seguintes gists: values->themes.xml e values-v210->themes.xml.

Na construção destes ficheiros, é preciso ter em conta que todas as tags <style>  tem os atributos name parent  que representam o nome que vai identificar o tema e o pai de quem herdar os atributos respectivamente.

De seguida temos de utilizar a  tag item de forma a definir os atributos do tema. Os atributos mais importantes a ter em conta são:

  • primaryColor: Define a cor principal que será  utilizada no toolbar  ou outra área que ocupe muito espaço.
  • primaryColorDark: Define a versão mais escura da primary color que será utilizada no status bar.
  • colorAccent: Define a cor de contraste que é utilizado para colorir acções que precisam da atenção do utilizador.

NB: A Paleta de cores assim como as regras que ditam que tons escolher para cada um dos atributos encontra-se aqui!

Com o tema definido, resta-nos só ir até ao ficheiro androidManifest e definir que a aplicação deve utilizar o tema criado como na figura baixo.

ChangeTheme

Ate então, se clicarmos no botão do Run para executar o projecto, a nossa aplicação ira abrir e só será possível ver uma tela branca com o status bar da cor que definida e para a grande surpresa, SEM ACTIONBAR.

A ActionBar não aparece  pois dentro do ficheiro themes.xml  nós definimos que iríamos herdar os atributos do tema AppCompat.NoActionBar que significa que o tema não terá um actionBar. Herdamos este tema de forma que no lugar do Actionbar possamos utilizar o novo componente introduzido no material design chamado Toolbar.

Para continuar com o post, vamos de seguida definir o Toolbar e colocar o navigation drawer  no nosso layout. Para poder ter o navigation Drawer, temos de ter como raiz o LayoutManager DrawerLayout disponível no pacote android.support.v4.widget.DrawerLayout e dentro dele colocamos a ListView, o Toolbar e o FrameLayout que será utilizado para trocar os fragments ao selecionar uma determinada opção no Drawer. O código do layout da main activity encontra-se AQUI.

Passando para o código java correspondente a MainActivity disponível aqui, temos de dar especial atenção ao seguintes pontos:

  • a nossa Activity  passou a extender a AppCompatActivity devido a depreciação da ActionBarActivity na versão nova da biblioteca de suporte.
  • no método inicializarToolbar, pegamos o Toolbar pelo seu id, e podemos definir o título, subtítulo etc como faríamos em uma ActionBar normal.

Pouco antes do lançamento desta biblioteca, era comum definir o ActionBar apartir do Toolbar fazendo  setSupportActionBar(Toolbar toolbar)  e passávamos a ter uma actionbar bastando fazer getSupportActionBar().

Mas Porque no Material design o conceito ActionBar foi deixado para trás, neste post nos utilizamos o Toolbar para definir o titulo, definir o icon do navigation drawer fazendo setNavigationIcon passando o Drawable do icon e por fim definir um evento para ficar a espera de clicks no icon utilizando setNavigationOnClickListener.

  • no método inicializarDrawer
    • começamos por pegar o DrawerLayout e a ListView pelos id’s.
    • Inicializar o ActionBarDrawerToggle e um listener para que possamos saber quando o drawer esta aberto ou fechado pelos métodos que temos implementar onDrawerOpened ou onDrawerClosed respectivamente.
    • definir o listener criado no passo anterior ao DrawerLayout
    • Criar um Adapter para a Lista do NavigationDrawer.( A criação do adapter e feita como neste Post. A grande diferença neste adapter é que temos na mesma lista dois tipos de linhas diferentes em que o primeiro tipo representa o Header com um background e o espaço para uma foto de perfil e o segundo tipo é apenas uma linha com um icon e um texto.)
    • Definir o adapter na lista.
    • Para terminar este método, registamos um listener que irá ficar a espera dos clicks nos itens da  lista.

A parte interessante deste post, é a que se segue em que ao clicar em um item do navigation drawer, mudamos a cor do texto da linha assim como a cor do icon mudam utilizando a nova classe DrawableCompat.

Para atingir tal objectivo, temos de:

  • criar duas variáveis globais( mPosicaoSelecionada mUltimaPosicaoDoDrawer) para guardar a posição do item seleccionado no drawer e a posição do item seleccionado anteriormente. Estas duas variáveis começam com o mesmo valor mas ficam diferentes depois que um item é clicado pela primeira vez e é invocado o método onItemClick  do listener da lista.
  • Depois de definir as variáveis, fechamos o drawer utilizando mDrawerLayout.closeDrawer(mListaDrawer).
  • Implementar o método para  mudar as cores da linha seleccionada( pintarItems ) dentro do callback onDrawerClosed pois é o único momento em que não temos o drawer aberto e podemos fazer as mudanças sem que utilizador note antes da próxima vez que ele abrir o drawer. Na implementação do método pintarItems :
    •  pegamos a view da lista correspondente a posição passada no método.
    • pegamos a view que contem o icon e o texto o texto das linhas
    • pegamos o drawable definido como background na view do icon e fazemos o wrap pelo DrawableCompat.
    • verificamos com o boolean passado se estamos a querer pintar ou colocar a linha na cor normal e definimos a devida cor.
    • Mudamos a cor do texto do Textview e fazemos o tint do drawable fazendo DrawableCompat.setTint(drawable,color).

Feitos os últimos passos, completamos a nossa aplicação e ao executa-la, temos o navigation drawer a funcionar devidamente e a mudar a cor do icon da opção seleccionada utilizando o DrawableCompat e eliminando o sofrimento de ter Drawables de cores diferentes para gerir os diversos estados que podemos querer representar.

PostSupportPic0 PostSupport002

Desta forma chegamos ao fim do post e mais uma vez espero que acima de tudo tenham se divertido e dado mais um passo para que se possam tornar desenvolvedores Ninjas.

Até a próxima 🙂

DM!

Links:

-Github: https://github.com/realdm/PostSupportLibrary

A Nova Android Support Library V 22.1 – Visão Geral

Standard

Hello a todos os Devs e espero que estejam todos muito bem de saúde e com disposição para mais um post ! Depois de algumas semanas extremamente agitadas, finalmente tive a oportunidade de voltar a escrever!

A minha volta veio com algumas reestruturações no blog em que decidi organizar melhor os posts da série para os iniciantes no desenvolvimento de apps  para android, criando novas secções em que pudesse escrever sobre tópicos mais avançados ou novidades sobre o mundo do android. Para quem esta a ler o blog pela primeira vez e gostaria de iniciar o desenvolvimento de apps para android pode começar a serie AQUI ou escolher a secção “Android – Iniciantes”.

Esta nova secção com o nome “Android Geral” terá como objectivo, escrever sobre alguns temas, tutoriais mais avançados e específicos como a utilização de APIS( Google Maps, Places, Youtube, Google Cloud Messaging), animações, etc.  A decisão de criar essa nova secção foi baseada no desejo da vontade de me desafiar e partilhar conhecimentos mais avançados assim como organizar melhor os posts para que o pessoal que esta a começar possa ter uma melhor orientação e saber que caminho seguir no blog.

E para abrir este novo espaço, neste post irei falar sobre a nova versão da  Android Support Library V22.1 que veio para animar a festa e deixar os desenvolvedores com menos dor de cabeça.

Para quem não sabe, a Android Support Library  é uma biblioteca desenvolvida pela Google que como o nome sugere oferece suporte a funcionalidades de API’s avançadas as API’s mais antigas, isto é, permite que os desenvolvedores possam desenvolver uma  certa funcionalidade disponível em uma das versões (Ex: Lolipop) e fazer com que funcione da mesma maneira em versões mais antigas (Ex: ICS). A Support Library  vem sendo desenvolvida já a muito tempo e um dos momentos mais marcantes foi  a possibilidade de utilizar o ActionBar que só era disponível para as API 11+ em aplicações que utilizavam as API’s inferiores.

Com o surgimento do Material design na versão 5 do android (Lolipop), novos padrões, componentes e funcionalidades foram adicionadas e desde o lançamento no ano passado, vários desenvolvedores tem vasculhado o código fonte para poder recriar  a experiencia do Lolipop nas versões anteriores. Tendo esta situação em mente, na altura a equipe do Google decidiu fazer pequenas actualizações na biblioteca de suporte já existente de forma enquanto preparavam o lançamento da mais recente Android Support Library V22.1

O lançamento desta biblioteca veio com varias funcionalidade novas, muito bem descritas no blog oficial AQUI mas para este post, apenas irei focar-me nos aspectos que mais me chamaram atenção e que considero  muito interessantes.

A primeira novidade  e a introdução do DrawableCompat, uma classe que permite fazer o Tint de drawables(Falei chinês). Com o Tint  de drawables quero dizer a possibilidade de poder mudar por exemplo a cor de um icon durante o tempo de execução sem ter de disponibilizar o mesmo icon com cores diferentes. Para quem tiver a app “Play Newsstand” poderá notar a  mudança de cor do icon de um item quando seleccionado no navigation drawer. Para poder utilizar a classe e fazer o Tint basta encapsular o Drawable no método DrawableCompat.wrap(Drawable) e de seguida invocar os métodos seleccionados como o setTint(), setTintMode etc.

A segunda novidade e a classe ColorUtils  que oferece ferramentas para melhor trabalhar com cores permitindo calcular a relação do contraste entre as cores, a opacidade de forma a manter um determinado contraste. (Estas ferramentas são perfeitas para manter um texto legível quando por cima de uma imagem).

A terceira novidade e a introdução de Interpolators, que permitem controlar  a variação de uma determinada animação. O Lolipop já veio com vários interpolators que permitiram criação de animações bem suaves e de diferentes tipos. Ainda nas animações, foi também adicionado o PathInterpolatorCompat  que permite a criação de curvas de beizel quadráticas e cúbicas(Para mais informações sobre Path e curvas de beizel veja AQUI)

Indo mais para o nível de Activities  e Widgets, existem 4 coisas que foram algumas modificadas e outras adicionadas:

  • Houve uma depreciação da ActionbarActivity para AppCompatActivity. Esta mudança não foi apenas no nome mas  na utilização da classe AppCompatDelegate que para vos ser sincero ainda estou a tentar entender o que  é e como funciona. Entretanto muitas das aplicações não precisam chegar ao detalhe de mexer com AppCompatDelegate pelo que no uso diário, convem extender a Activity da classe AppCompatActivity.
  • Adição do Material Design Dialogs permitiu a criação de dialogs(“pop ups) com o estilo do Material design utilizando a class AppCompatDialog e actualizando a antiga classe AlertDialog  para que tenha as mesmas capacidades.
  • Voltando ao primeiro aspecto sobre o Tinting falado acima, e possível (Finalmente =) )fazer o mesmo com widgets(Botões, TextView, CheckBoxes). Para tal, foram criados novos widgets com esta capacidade para substituir os antigos com os seguintes novos nomes:
    • AppCompatAutoCompleteTextView
    • AppCompatButton
    • AppCompatCheckBox
    • AppCompatCheckedTextView
    • AppCompatEditText
    • (Mais no blog oficial)
  • O quarto e o último aspecto é a capacidade que já tinha sido lançada no Lolipop de poder definir um tema para cada View, permitindo por exemplo colocar o Toolbar com um tema e cor diferente do tema da activity ou do resto dos componentes. Na versão antiga para definir o tema na Toolbar  era preciso definir o namespace app e na view  fazer app:theme=”<tema>” .O Atributo to theme foi adicionado ao android namespace permitindo que qualquer view na API 11+ possa definir seu próprio tema fazendo android:theme=”<tema>”.

Existem muito mais ferramentas como a Pallete , RecyclerView, RenderScript que foram adicionadas e que permitem a criação de novas  experiencias consistentes para todas as versões do android existentes.

Como desenvolvedor, fico grato a equipe da Google por lançar o update e espero que todos vocês façam uso destas novas ferramentas para desenvolver altas apps!

Caso tenha algum comentário ou questão, deixe ficar no comentário que poderemos continuar a conversa lá.

Muito Obrigado,

DM

Desenvolvendo para Android– Intents

Standard

Ola a todos os leitores  e bem vindos para mais um post da serie Desenvolvendo para android. Para quem não teve o oportunidade de ler o post anterior da série, pode o fazer já AQUI.

Porque muitas das aplicações existentes no playstore não são compostas por uma única Activity, e importante saber como navegar entre Activities utilizando os mecanismos correctos para o efeito. Este post será em volta do mecanismo de comunicação( messaging) que o android oferece de forma que possamos:

  • Passar de uma activity para a outra dentro da mesma aplicação
  • Passar informação entre activities.
  • Chamar Activities de outras aplicações.

Como mencionei acima, o android possui um mecanismo de comunicação entre componentes  das aplicacoes (Activites, Services, BroadCastReceivers)  altamente avançado e devidamente documentado com o nome de Intent.  Pela definição do site, um Intent e um objecto de messaging  que pode ser utilizado para pedir a realização de uma certa acção por parte de um componente na mesma ou em outra aplicação. Como o nome sugere, podemos entender um Intent como uma “intenção” que temos de fazer algo e as “intenções” comuns costumam ser:

  • Iniciar uma nova Activity: Ao utilizar um Intent para iniciar uma Activity, este contem a especificação sobre a Activity a inicializar e as possíveis informações que podemos querer passar. E possível  também fazer com que ao fechar a Activity iniciada, esta mande algum tipo de resultado para a activity que foi responsável pela sua inicialização. (Um clássico do envio de resultado a uma Activity é quando chamamos a activity da camera a partir do chat do whatsapp e depois de tirar a foto, temos ela já  na activity correspondente a conversa de chat em que pretendíamos enviar a foto) .
  • Iniciar um Service ou fazer a Entrega de um BroadCast: A esta altura não é importante falar de Services ou Broadcasts pois são tópicos que precisam um pouco de atenção mas para os mais curiosos, mais informação esta disponível AQUI.

O tópico sobre os Intents e muito mais pratico e para isso vamos continuar a modificar o codigo da aplicação anterior começando por abrir o ficheiro activity_main.xml e modificar para que fique como na figura abaixo e no seguinte gist.

activitymain

As modificações foram efectuadas de forma a  permitir que:

  • Ao clicar no botão “Mostrar Nome” utilizaremos um Intent para iniciar uma Activity que irá simplesmente mostrar o nome escrito no EditText em um TextView da nova Activity.
  • Ao clicar no botão “Enviar Email” utilizaremos um Intent para chamar uma activity fora da aplicação que tenha a capacidade de enviar um e-mail( De certeza o Gmail estará presente na).
  • Ao clicar no botão “Tirar uma Fotografia” iremos simular o que acontece no whatsapp ao tirar uma foto utilizando uma activity externa a nossa aplicação e depois mostrar a foto na ImageView no layout.

Antes de continuar para a modificação do ficheiro MainActivity.java vamos criar uma nova Activity e para tal basta ir até ao pacote que contem a Activity Main, fazer o right click no mouse e seleccionar new->Activity->Blank Activity e será apresentada uma janela para colocar o nome da activity como na imagem abaixo.

AddBlankActivity

Atenção:  E possível criar uma activity extendendo uma classe java directamente da Activity e de seguida criar o ficheiro xml correspondente dentro da pasta layout mas não aconselho esta prática pois e muito fácil cair no erro de esquecer de declarar a activity no manifest como foi explicado AQUI e consequentemente erros ao executar a aplicação.

Após criar a SegundaActivity será necessário efectuar as modificações na SegundaActivity.java contidas neste Gist e ao activity_segunda.xml neste gist..

Tendo a nossa segunda activity pronta, está na hora de efectuar as modificações na MainActivity.java. Porque a explicação do uso de Intents é mesmo técnica e directa ao assunto, siga o seguinte gist para copiar o codigo e acompanhar os comentarios contidos nele.

Com todas as modificacoes feitas e muito codigo escrito, e chegada a hora de  clicar no botao para correr a aplicacao e testar o que estivemos aqui a fazer.

Na minha opiniao, este e um tema bastante importante e acredito que assim que o entenderem, os proximos posts da série pareceram muito mais simples. Caso exista alguma duvida  ou sugestão basta deixar um comentário na secção a baixo que terei o prazer de responder ou debater sobre o assunto.

Obrigado e Até a Próxima