Content Providers

Os Content Providers são parte importantíssima da arquitetura de um sistema android. É responsabilidade deles prover às aplicações o conteúdo que elas precisam para funcionar, ou seja, os dados.

ContentProviderMas por que são realmente necessários?

As aplicações poderiam muito bem acessar diretamente um banco de dados, por exemplo. Porém, é uma boa prática tornar o modo como os dados são gravados transparente à aplicação. Dessa forma, a aplicação pode manter o foco nas interações com o usuário.

Além disso, essa técnica permite a criação de Shared Content Providers, que são providers “públicos” que podem ser acessados por várias aplicações. Por exemplo, existe o content provider de SMS/MMS que permite a qualquer aplicação ler as mensagens recebidas por um telefone celular.

E como é feita a comunicação entre Content Providers e Aplicações?

Uri. Guarde bem este nome, pois você irá precisar muito dele durante a sua carreira como desenvolvedor android.

Toda a comunicação entre aplicações e providers é feita através dos métodos da interface ContentProvider, que sempre recebem um objeto Uri como parâmetro. O formato da Uri é definido pelo content provider. Por exemplo, a Uri content://sms/inbox acessa as mensagens de inbox no Content Provider de SMS. Falaremos um pouco mais sobre as Uris a seguir, mas primeiro, vamos conhecer os métodos que usaremos para enviá-las para o provider:

  • query(Uri, String[], String, String[], String)– usado para recuperar dados.
  • insert(Uri, ContentValues) – usado para inserir dados.
  • update(Uri, ContentValues, String, String[]) – usado para atualizar dados.
  • delete(Uri, String, String[]) – usado para deletar dados.
  • getType(Uri) – usado para obter o MIME type de certo dado.

O QuickNotes Content Provider

Depois dessa rápida introdução, vamos colocar a mão na massa.

Iremos criar um content provider para o QuickNotes, que servirá para gravar e recuperar as anotações do usuário, da seguinte forma:


diagrama ContentProviderIntencionalmente coloquei a caixa que define como o provider irá gravar os dados para mostrar que isso é irrelevante para a aplicação.

A estrutura das URIs

Uma Uri usada para acessar Content Provider segue o formato:

content://<authority>/<parametro1>/<parametro2>/…/<parametroN>

Onde authority é o “nome” do provider, e os parâmetros são aqueles definidos pelo provider. Por exemplo, a seguinte Uri:

content://sms/conversations/10

Acessa o Content Provider de SMS, e seleciona a conversation de Id número 10.

Criando um Content Provider

Para criar seu próprio content provider, é preciso fazer 2 coisas:

  1. Criar uma sub-classe da ContentProvider, implementando os métodos públicos que eu citei no começo do artigo;
  2. Registrar o provider no AndroidManifest.xml

Vamos começar criando a classe QuickNotesProvider:

package br.com.felipesilveira.quicknotes;

import android.content.ContentProvider;
import android.net.Uri;
import android.content.ContentValues;
import android.database.Cursor;

public class QuickNotesProvider extends ContentProvider {
	// Aqui definimos os formatos possíveis de Uri que
	// o nosso provider irá aceitar.
	public static final Uri CONTENT_URI = Uri
.parse("content://br.com.felipesilveira.quicknotes.quicknotesprovider");

	@Override
	public int delete(Uri uri, String selection, String[] selectionArgs) {
		return 0;
	}

	@Override
	public String getType(Uri uri) {
		return null;
	}

	@Override
	public Uri insert(Uri uri, ContentValues values) {
		return null;
	}

	@Override
	public boolean onCreate() {
		return false;
	}

	@Override
	public Cursor query(Uri uri, String[] projection, String selection,
			String[] selectionArgs, String sortOrder) {
		return null;
	}

	@Override
	public int update(Uri uri, ContentValues values, String selection,
			String[] selectionArgs) {
		return 0;
	}
}

Agora, vamos registrar o nosso provider no AndroidManifest, adicionando a seguinte linha entre as tags <application …> e </application>

<provider
android:authorities="br.com.felipesilveira.quicknotes.quicknotesprovider"
android:name=".QuickNotesProvider"/>

E assim o nosso Content Provider está pronto para receber requisições da aplicação. Ainda não retorna nenhum resultado significativo – mas isso faremos no próximo artigo, onde ensinarei como acessar um banco de dados SQLite, para fazer esse provider realmente efetivo.


Desenvolvendo para Android

DICA: Usando o MOTODEV Studio, a tarefa de criar um content provider fica muito mais fácil. Basta acessar New > Android Content Provider, que um template será criado, com todos os métodos! daí é só implementar a lógica deles.

23 respostas to “Content Providers”

  1. ErickPetru disse:

    Parabéns pela iniciativa da série. Comecei com Android recentemente e estou gostando muito e prevendo investir muito desenvolvimento nela.
    Estava aguardando pela parte de Providers e esta introdução foi bem objetiva. Agora aguardo a parte de SQLite.

  2. Valeu Erick!
    Estou quase terminando o artigo sobre SQLite, em breve estará aqui.

  3. Tom disse:

    Fala Felipe, Parabéns pelos artigos, muito bom mesmo, pow cara nao para de fazer esses artigos nao, sei que é dificil arrumar tempo para atualizar o site… mas seria legal que todos que foram e serão beneficiados com seus artigos nada mas justo que façamos um doação para insentivar….. abraços

  4. Marivaldo disse:

    Felipe, Content Provider é uma espécie de Hibernate para Android??

  5. Oi Marivaldo,
    Hum, o conceito é um pouco diferente. O Content Provider é também uma abstração de um banco de dados, porém a forma de acessa-lo é bem diferente do hibernate.

    Valeu!

  6. Tiago Rocha disse:

    Boas Felipe, pode-me explicar uma coisa por favor.
    Estou também desenvolvendo uma aplicação para android.
    Tenho a base de dados alojada num servidor da empresa onde estou a estagiar.. como poderei acessar essa BD?
    É através do contentprovider? E depois a aplicação comunica com a base de dados, e recolhe a informação consoante a query?

    Obrigado pela atenção desde já.
    Gostaria de falar com você de uma maneira mais directa, se pudesse facultar o seu endereço electronico ou assim agradecia.

    Cumprimentos ,
    Tiago Rocha.

    tiago.aziz@gmail.com

    Me mande um mail. 🙂

  7. Jorge disse:

    Obrigado pelo conteúdo e pelas dicas Felipe!

  8. Arthur disse:

    Olá Felipe, estava seguindo seu curso normalmente, mas nessa fase quando fui debugar o quick_notes deu esse erro no logcat:

    12-23 16:04:28.813: E/AndroidRuntime(1120): FATAL EXCEPTION: main
    12-23 16:04:28.813: E/AndroidRuntime(1120): java.lang.RuntimeException: Unable to get provider br.com.promptinf.DBProvider: java.lang.ClassNotFoundException: br.com.promptinf.DBProvider
    12-23 16:04:28.813: E/AndroidRuntime(1120): at android.app.ActivityThread.installProvider(ActivityThread.java:4201)
    12-23 16:04:28.813: E/AndroidRuntime(1120): at android.app.ActivityThread.installContentProviders(ActivityThread.java:3963)
    12-23 16:04:28.813: E/AndroidRuntime(1120): at android.app.ActivityThread.handleBindApplication(ActivityThread.java:3917)
    12-23 16:04:28.813: E/AndroidRuntime(1120): at android.app.ActivityThread.access$1300(ActivityThread.java:122)
    12-23 16:04:28.813: E/AndroidRuntime(1120): at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1184)
    12-23 16:04:28.813: E/AndroidRuntime(1120): at android.os.Handler.dispatchMessage(Handler.java:99)
    12-23 16:04:28.813: E/AndroidRuntime(1120): at android.os.Looper.loop(Looper.java:137)
    12-23 16:04:28.813: E/AndroidRuntime(1120): at android.app.ActivityThread.main(ActivityThread.java:4340)
    12-23 16:04:28.813: E/AndroidRuntime(1120): at java.lang.reflect.Method.invokeNative(Native Method)
    12-23 16:04:28.813: E/AndroidRuntime(1120): at java.lang.reflect.Method.invoke(Method.java:511)
    12-23 16:04:28.813: E/AndroidRuntime(1120): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:784)
    12-23 16:04:28.813: E/AndroidRuntime(1120): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:551)
    12-23 16:04:28.813: E/AndroidRuntime(1120): at dalvik.system.NativeStart.main(Native Method)
    12-23 16:04:28.813: E/AndroidRuntime(1120): Caused by: java.lang.ClassNotFoundException: br.com.promptinf.DBProvider
    12-23 16:04:28.813: E/AndroidRuntime(1120): at dalvik.system.BaseDexClassLoader.findClass(BaseDexClassLoader.java:61)
    12-23 16:04:28.813: E/AndroidRuntime(1120): at java.lang.ClassLoader.loadClass(ClassLoader.java:501)
    12-23 16:04:28.813: E/AndroidRuntime(1120): at java.lang.ClassLoader.loadClass(ClassLoader.java:461)
    12-23 16:04:28.813: E/AndroidRuntime(1120): at android.app.ActivityThread.installProvider(ActivityThread.java:4186)
    12-23 16:04:28.813: E/AndroidRuntime(1120): … 12 more

    O que devo fazer?
    Obrigado
    Arthur

  9. Fabiana disse:

    Parabéns pelo tutorial! Simples, direto e engloba o básico para se começar a desenvolver!

  10. leonardo disse:

    Como eu crio Uma content provider no netbeans ? Sou programador de c , estou aprendendo java , então ainda estou um pouco deslocado .

  11. leonardo disse:

    Resolvido .

  12. Oi Leonardo,
    Não existe plugin Eclipse para o netbeans (até onde eu saiba). Eu recomendo o uso do Eclipse.
    Boa sorte!

  13. Diogo Paulino disse:

    Poxa que boa iniciativa hein Felipe. Depois de muita procura achei um site que fala claramente sobre o desenvolvimento para android e sem enrolações. Está de parabéns, a facilidade está clara e objetiva e no seu site obtemos informações de modo rápido e simples sem muita frescura como muitos sites por ai. Já add o site ao favoritos..t +

  14. Alejandro Fuentes disse:

    me esta dando um erro quando adiciono a linha…

    coloquei issa linha dentro das tag’s …
    O error em tempo de desenho que fala:

    “Exported content providers can provide access to potentially sensitive data”

    VOcÊ pode me dar uma dica sobre o que pode ser?
    Muito obrigado

  15. Alejandro Fuentes disse:

    me esta dando um erro quando adiciono a linha…

    [provider
    android:authorities=”content://com.example.aleteste.quicknotes.quicknotesprovider”
    android:name=”.QuickNotesProvider” ][/provider]

    coloquei issa linha dentro das tag’s [application]
    O error em tempo de desenho que fala:

    “Exported content providers can provide access to potentially sensitive data”

    VOcÊ pode me dar uma dica sobre o que pode ser?
    Muito obrigado

  16. willian oliveira disse:

    minha aplicaçao fica dando erro e nao abre o que pode ser, esta tudo certo.

  17. Leandro disse:

    Sobre as pessoas que comentaram que estão se deparando com o seguinte erro:
    “Exported content providers can provide access to potentially sensitive data”.

    Eu solucionei colocando o seguinte atributo dentro da tag provider: android:exported=”false”.

    Ficando assim :

  18. luiz disse:

    Estou desenvolvendo para controle de peso, a parte de cadastro de usuario funciona normalmente porem implemente a mesma logica para cadastrar a dieta do usuario e a activity não abre o logcat menciona que não conseguiu encontrar a tabela de dietas que eu ja havia criado. a duvida eh se eu devo usar o mesmo a mesma uri para todas as tabelas ou devo criar uma para cada agradeço a atenção e caso seja necessario eu posto trechos do codigo ^^

  19. Matheus disse:

    Olá Felipe,

    Onde eu crio esse content provider? No MainActivity?
    Muito boa a sua iniciativa!!

    Att,
    Matheus

  20. Oi Matheus!

    Na verdade será uma nova classe (em outro arquivo chamado QuickNotesProvider.java)

    Boa sorte!

  21. Sheluki disse:

    Tenho um fragmento com lista que faz um query no content provider, e agora preciso de um dialogfragment pra editar e outro dialogFragment para inserir.

    Eu devo instanciar um content provider dentro dos dialogfragment, ou devo fazer os dialogfragment passar a responsabilidade de usar o content provider para o fragmento principal que já usa o content provider?

    qual é a melhor pratica de programação?

    A responsabilidade de usar o content provider deve ser centralizada?

  22. Carlos disse:

    Olá! Gostaria de saber se para iniciar o aprendizado em desenvolvimento de app é necessário o domínio de alguma linguagem de programação como requisito básico.

Deixe um comentário