logo
  • Home
  • Acerca
  • Autores
  • Faq
  • Rede
  Twitter   Feed-me! RSS!

Android ContentProvider

Colocado por Fábio Batista da Silva na(s) categoria(s): 1, abas, Android, app, AR, Arquitetura, arte, auto, Banco de Dados, BI, boolean, case, class, classe, código, comunicação, control, Curso, dados, demo, Dica, Dicas, err, exemplo, Flex, for, ide, IE, if, image, int, interface, Java, lite, map, mg, O, on, override, Partilha, pattern, pt, RIA, Ria’s Geral, runtime, SQLite, string, tag, TAT, Tema, tv, UI, update, utils, XML, XP em 02 11th, 2011 | Sem comentários

Olá,

Esse sera o primeiro post que escrevo sobre android, estou começando a “brincar” com ele e resolvi compartilhar um pouco do pouco que descobri. :)
Nesse post vou dar uma ideia de como implementar o seu próprio ContentProvider.


SQLite :

Uma das grandes facilidades do android e o suporte ao SQLite.
As aplicações poderiam acessar diretamente o banco porem é uma boa pratica encapsular isso em um ContentProviders
de forma que isso fique acessível para sua aplicação ou qualquer outra que precise acessar esses dados.

ContentProviders :

O ContentProviders é uma parte muito importante da arquitetura de um sistema android.
São eles quem provem os dados para a aplicação.

Uri :

No Android a comunicação entre aplicações e providers é feita através de Uri.
Cada ContentProviders expõe URIs públicas que identificam o seu conjunto de dados
e controla uma ou mais tabelas e expondo uma URI diferente para cada uma delas.

Uma Uri segue o formato: “content://{authority}/{table}/parametroN”
{authority} é o “nome” do ContentProviders
{table} é a tabela que esta acessando
{parametroN} são os parâmetros esperados pelo provider.

EX :
Todos os registros da tabela (Diretório): content://br.com.flexria.jobsdroid.jobsdroidprovider/jobs
Um único registro com id 1 (Item) : content://br.com.flexria.jobsdroid.jobsdroidprovider/jobs/1

Escrevendo seu ContentProvider :

Bom, vajamos na pratica com isso funciona.
Para escrever seu ContentProviders vc precisa basicamente de quatro coisas.

  • BaseColumns
  • ContentProviders
  • SQLiteOpenHelper
  • Registrar o provider no AndroidManifest.xml :

ContentProvider :

E a classe que provera os dados a nossa aplicação,
A classe abstrata ContentProvider exige a implementação dos métodos :

* query(Uri, String[], String, String[], String)- Recuperar dados.
* insert(Uri, ContentValues) – Insere um novo registro.
* update(Uri, ContentValues, String, String[]) – Atualiza um registro existente.
* delete(Uri, String, String[]) – Deleta um registro.
* getType(Uri) – Obter o MIME type do dado.

Dentro desses métodos iremos implementar a logica que encapsula esses comportamentos.
Isso é valido para cada uma das tabelas que o provider esteja acessando,
Como aqui só tenho uma tabela e esse é apenas um exemplo didático esta tudo na mesma classe,
porem isso pode ficar meio confuso com quando temos varias tabelas e comportamentos diferentes.
Uma solução para isso seria implementar o Pattern Strategy para encapsular cada comportamento.

O exemplo é bem básico porem gostaria de salientar três pontos
* Método getType – Informa que tipo de dado esta sendo requisitado, se é um item ou o diretório.
* Variável mMatcher – Usado para verificar qual Uri esta sendo acessada, se é um item ou o diretório.
* Constante AUTHORITY – Mesma identificação do provider utilizado no AndroidManifest.xml

Bom, como uma Imagem diz mais que mil palavras ai vai o código:

public class JobsDroidProvider extends ContentProvider {
  /**
  * Provider Authority
  */
  public static final String AUTHORITY = "br.com.flexria.jobsdroid.jobsdroidprovider";
  /**
  * DataBase Name
  */
  private static  final String DATABASE_NAME = "jobsdroid.db";
  /**
  * DataBase Version
  */
  private static  final int  DATABASE_VERSION = 1;
  /**
  * match for directory of jobs.
  */
  private  static final int MATCH_JOBS 		= 1;
  /**
  * match for sub-directory of a single jobs.
  */
  private  static final int MATCH_JOBS_ID 	= 2;
  /**
  * Log Tag
  */
  public static final String TAG = "JobsDroidProvider";
  /**
  * DBHelper instance
  */
  private DBHelper mHelper;
  /**
  * UriMatcher instance
  */
   private static final UriMatcher mMatcher;
   /**
   * Projection Map instance
   */
   private static HashMap<String, String> mProjection;
?
   static {
	mProjection = new HashMap<String, String>();
	mProjection.put(Jobs._ID, 	Jobs._ID);
	mProjection.put(Jobs.NAME, 	Jobs.NAME);
    }
?
    static {
    	mMatcher = new UriMatcher(UriMatcher.NO_MATCH);
	mMatcher.addURI(AUTHORITY, Jobs.TABLE, 		MATCH_JOBS);
	mMatcher.addURI(AUTHORITY, Jobs.TABLE+"/#", 	MATCH_JOBS_ID);
    }
?
?
    @Override
    public String getType(Uri uri) {
?
	switch (mMatcher.match(uri)) {
		case MATCH_JOBS:
			return Jobs.CONTENT_TYPE;
		case MATCH_JOBS_ID:
			return Jobs.CONTENT_ITEM;
		default:
			throw new IllegalArgumentException("Unsupported URI: " + uri);
	}
    }
?
?
    @Override
    public boolean onCreate() {
	mHelper = new DBHelper(getContext());
	return (mHelper != null);
    }
?
?
    @Override
    public Cursor query(Uri uri, String[] projection, String selection,String[] selectionArgs, String sortOrder) {
	String type = this.getType(uri);
	Log.i(TAG, "query " + uri.toString());
?
	Cursor cursor;
	SQLiteQueryBuilder builder = new SQLiteQueryBuilder();
	SQLiteDatabase database = mHelper.getReadableDatabase();
	builder.setTables(Jobs.TABLE);
	builder.setProjectionMap(mProjection);
?
	if (type.equals(Jobs.CONTENT_ITEM)) {
		builder.appendWhere(this.whereItem(uri, selection));
	}
?
	if (sortOrder == null || sortOrder.length() == 0) {
		sortOrder = Jobs.NAME;
	}
?
	cursor = builder.query(database, projection, selection, selectionArgs,null, null, sortOrder);
	cursor.setNotificationUri(getContext().getContentResolver(), uri);
?
	return cursor;
    }
?
?
    @Override
    public Uri insert(Uri uri, ContentValues values) {
	this.getType(uri);
	Log.i(TAG, "insert " + uri.toString());
?
	SQLiteDatabase db = mHelper.getWritableDatabase();
	long rowId = db.insert(Jobs.TABLE, Jobs.NAME, values);
?
	if (rowId > 0) {
	    Uri itemUri = ContentUris.withAppendedId(Jobs.CONTENT_URI, rowId);
	    getContext().getContentResolver().notifyChange(itemUri, null);
	    return itemUri;
	}
?
	throw new RuntimeException("Failed to insert row into : " + uri);
    }
?
?
    @Override
    public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) {
	String type 		= this.getType(uri);
	SQLiteDatabase db 	= mHelper.getWritableDatabase();
?
	Log.i(TAG, "update " + uri.toString());
?
	if(type.equals(Jobs.CONTENT_ITEM)){
		selection = this.whereItem(uri, selection);
	}
?
      	int count = db.update(Jobs.TABLE, values, selection, selectionArgs);
	getContext().getContentResolver().notifyChange(uri, null);
?
	return count;
    }
?
?
    @Override
    public int delete(Uri uri, String selection, String[] selectionArgs) {
	String type 		= this.getType(uri);
	SQLiteDatabase db 	= mHelper.getWritableDatabase();
?
	Log.i(TAG, "delete " + uri.toString());
?
	if(type.equals(Jobs.CONTENT_ITEM)){
		selection = this.whereItem(uri, selection);
	}
?
	int count = db.delete(Jobs.TABLE, selection, selectionArgs);
	getContext().getContentResolver().notifyChange(uri, null);
	return count;
    }
?
    private String whereItem(Uri uri, String selection) {
	if(this.getType(uri).equals(Jobs.CONTENT_ITEM)){
		String where  =  Jobs._ID + " = " + uri.getPathSegments().get(1);
		if(!TextUtils.isEmpty(selection)){
			return where + " AND (" + selection + ")" ;
		}else{
			return where;
		}
	}
	return selection;
    }
?
    /**
    * Inner class Jobs
    */
    public static final class Jobs implements  BaseColumns {
    	    ....
    }
?
    /**
    * Inner class DBHelper
    */
    private static class DBHelper extends SQLiteOpenHelper {
       	....
    }
}

BaseColumns :

Inner class que representa a tabela do banco de dados,
estende a interface BaseColumns que possue as constantes _ID e _COUNT.
A classe Jobs possuí as constantes que representam as colunas da tabela e a Uri que a identifica

/**
* Inner class Jobs
*/
 public static final class Jobs implements  BaseColumns {
    public static final Uri CONTENT_URI = Uri.parse("content://"+ JobsDroidProvider.AUTHORITY + "/" + Jobs.TABLE);
?
    /**
    * The MIME type of a directory.
    */
    private static final String CONTENT_TYPE = "vnd.android.cursor.dir/vnd.flexria." + Jobs.TABLE;
?
?
    /**
    * The MIME type of a single Jobs.
    */
    private static final String CONTENT_ITEM = "vnd.android.cursor.item/vnd.flexria." + Jobs.TABLE;
?
    /**
     * Table name
     */
    private static final String TABLE 	= "jobs";
?
    /**
     * Column name
     */
    public static final String 	NAME = "name";
}

SQLiteOpenHelper :

Inner class que é responsável pela criação e alteração do banco de dados,
A classe abstrata SQLiteOpenHelper exige a implementação dos métodos :

* onCreate() – Chamado quando o banco de dados for aberto pela primeira vez. Aqui que criaremos o banco de dados.
* onUpdate() – Chamado quando a versão do banco de dados muda. Quando uma nova versão da app for instalada.

Como nesse caso temos a primeira versão não tenho nada no método onUpdate.

/**
* Inner class DBHelper
*/
private static class DBHelper extends SQLiteOpenHelper {
    private static final String SQL_CREATE_TASKS = "CREATE TABLE " + Jobs.TABLE +
                     " (" +
                           Jobs._ID 	+ " INTEGER PRIMARY KEY AUTOINCREMENT," +
                           Jobs.NAME 	+ " TEXT" +
                       " );";
?
    DBHelper(Context context) {
       super(context, DATABASE_NAME, null, DATABASE_VERSION);
    }
?
    @Override
    public void onCreate(SQLiteDatabase db) {
        db.execSQL(SQL_CREATE_TASKS);
    }
?
    @Override
    public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
?
    }
}

AndroidManifest :

Depois disso podemos registrar o provider no AndroidManifest.xml


 android:authorities="br.com.flexria.jobsdroid.jobsdroidprovider"
			android:name=".JobsDroidProvider" />

Utilizando o Provider :

Feito isso ja podemos utilizar o provider na Activity,
quando utilizamos o método getContentResolver da Activity e passamos como parâmetro a Uri do conteúdo
o nosso provider é chamado e os métodos que implementamos podem ser utilizados.

EX :
* getContentResolver().query(JobsDroidProvider.Jobs.CONTENT_URI, null, null, null, null);

ContentValues values 	= new ContentValues();
values.put(JobsDroidProvider.Jobs.NAME, "Fabio B. Silva");
?
getContentResolver().query(JobsDroidProvider.Jobs.CONTENT_URI, null, null, null, null);
getContentResolver().insert(JobsDroidProvider.Jobs.CONTENT_URI, values);
?
?
Uri uri = ContentUris.withAppendedId(JobsDroidProvider.Jobs.CONTENT_URI, 1);
// uri = content://br.com.flexria.jobsdroid.jobsdroidprovider/jobs/1
getContentResolver().update(uri, values,null,null);
getContentResolver().delete(uri, null, null);

Em um próximo momento volto a falar sobre isso, mais por hora é só.

Espero que essa dicas possam ajudar aos que como eu estão começando com o android

Abraço e até a próxima….



Veja o post original no blog do autor aqui!  

Fábio Batista da Silva

Escrito por Fábio Batista da Silva @ http://www.flexria.com.br/home
Saiba mais sobre o autor na sua pagina de perfil
Outros posts do autor:
» PHP + MongoDB
» Lumine + ZendAmf + Flex 4/5
» PHP + MongoDB

Deixe um comentário



Spam Protection by WP-SpamFree

ACERCA

O que é o RedeRIA ?

O redeRIA não é nada mais que um agregador de feed's que disponibiliza o conteudo de varios blogs e autores ao redor do mundo RIA, actualmente agregamos mais de 2791 entradas vindas de 53 blogs especializados em ria’s, pelo que só fica a ganhar em assinar o feed ou seguir a comunidade no twitter.

Se acha que o seu blog ou um blog de um amigo é interessante e util para os leitores o redeRIA, faça a sua submissão aqui.

Feed: assine já
Twitter: siga-nos

GOOGLE

Votação


Deveria o RedeRia agregar conteúdo em inglês?
Ver Resultados

AUTORES


Eduardo KrausAlexandre TadashiBindableCognitiva SoluçõesDaniel LopesDaniel SchmitzDanielPedrinhaDClick TeamEbercomEdgard DavidsonElvis FernandesErko BrideeFabiel PrestesFábio Batista da SilvaFabio da SilvaFabriccio BernardesFelipe BorellaFlavia MoreiraGabriel VersalliniGabriela T. PerryIgor MusardoJanderson CardosoJoão AugustoJose Carlos FielKelps SousaLeonardo FrançaLucas MarçalLuis MessiasLuiz TarabalMario JuniorMário SantosMauro MartinsPablo SouzaPedro ClaudioreneRia BrazilriaPTRicardo CerqueiraRobson FernandesRodrigo Pereira FragaSaintBrSamuelFacchinelloSergio SouzaSilva DeveloperStefan HorochovecTech CaffeTecinforThiago BuenoVedVinícius SandimWillian ManoXAML Cast

PUBLICIDADE








Powered by Wordpress & msdevstudio.com