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,

Advertisements

2 thoughts on “Desenvolvendo para Android – Como Implementar Content Providers

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s