Um dos grandes diferenciais da plataforma android é a grande quantidade de módulos e APIs
que as aplicações tem à disposição para usar. Eles dão muito poder ao desenvolvedores, permitindo que estes façam coisas que eram impossíveis em outras plataformas móveis.
Um dos mais importantes módulos é o SQLite. Sim, amigos, já temos um SGDB (Sistema gerenciador de bancos de dados) instalado e pronto para usar! E é exatamente o que faremos no artigo de hoje.
No artigo anterior vimos como criar um Content Provider. Usaremos este provider para acessar o banco de dados.
Para fazer isso, precisamos implementar os métodos da classe ContentProvider que vimos no artigo passado (query(), delete(), update(), etc…) para prover ao usuário os métodos para criar, atualizar, deletar e recuperar os dados. Além disso, usaremos a classe SQLiteOpenHelper para gerenciar a conexão com o banco de dados.
A classe SQLiteOpenHelper
A classe SQLiteOpenHelper, como dito anteriormente, será usada para gerenciar o banco de dados. Para usá-la, é preciso criar uma subclasse implementando os métodos abaixo:
- onCreate() – Este método é chamado quando a conexão com o banco de dados for aberta pela primeira vez. É aqui que criaremos o banco de dados, com o comando sql CREATE.
- onUpdate() – Este método é chamado quando a versão do banco de dados muda. Por exemplo, digamos que você criou uma nova versão de seu aplicativo que usa uma tabela a mais no banco de dados. Quando esta nova versão for instalada (em um telefone que já possuir a primeira versão) este método será chamado, então você poderá criar apenas a nova tabela, mantendo os dados do usuário.
O código
O código do QuickNotesProvider fica assim, acessando o banco de dados. A seguir, eu explico algumas coisas que podem gerar dúvidas.
package br.com.felipesilveira.quicknotes;
import java.util.HashMap;
import android.content.ContentProvider;
import android.content.ContentUris;
import android.content.Context;
import android.content.UriMatcher;
import android.net.Uri;
import android.provider.BaseColumns;
import android.content.ContentValues;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;
import android.database.sqlite.SQLiteQueryBuilder;
public class QuickNotesProvider extends ContentProvider {
// Authority do nosso provider, a ser usado nas Uris.
public static final String AUTHORITY =
"br.com.felipesilveira.quicknotes.quicknotesprovider";
// Nome do arquivo que irá conter o banco de dados.
private static final String DATABASE_NAME = "quicknotes.db";
// Versao do banco de dados.
// Este valor é importante pois é usado em futuros updates do DB.
private static final int DATABASE_VERSION = 1;
// Nome da tabela que irá conter as anotações.
private static final String NOTES_TABLE = "notes";
// 'Id' da Uri referente às notas do usuário.
private static final int NOTES = 1;
// Tag usada para imprimir os logs.
public static final String TAG = "QuickNotesProvider";
// Instância da classe utilitária
private DBHelper mHelper;
// Uri matcher - usado para extrair informações das Uris
private static final UriMatcher mMatcher;
private static HashMap mProjection;
static {
mProjection = new HashMap();
mProjection.put(Notes.NOTE_ID, Notes.NOTE_ID);
mProjection.put(Notes.TEXT, Notes.TEXT);
}
static {
mMatcher = new UriMatcher(UriMatcher.NO_MATCH);
mMatcher.addURI(AUTHORITY, NOTES_TABLE, NOTES);
}
/////////////////////////////////////////////////////////////////
// Métodos overrided de ContentProvider //
/////////////////////////////////////////////////////////////////
@Override
public int delete(Uri uri, String selection, String[] selectionArgs) {
SQLiteDatabase db = mHelper.getWritableDatabase();
int count;
switch (mMatcher.match(uri)) {
case NOTES:
count = db.delete(NOTES_TABLE, selection, selectionArgs);
break;
default:
throw new IllegalArgumentException(
"URI desconhecida " + uri);
}
getContext().getContentResolver().notifyChange(uri, null);
return count;
}
@Override
public String getType(Uri uri) {
switch (mMatcher.match(uri)) {
case NOTES:
return Notes.CONTENT_TYPE;
default:
throw new IllegalArgumentException(
"URI desconhecida " + uri);
}
}
@Override
public Uri insert(Uri uri, ContentValues values) {
switch (mMatcher.match(uri)) {
case NOTES:
SQLiteDatabase db = mHelper.getWritableDatabase();
long rowId = db.insert(NOTES_TABLE, Notes.TEXT, values);
if (rowId > 0) {
Uri noteUri = ContentUris.withAppendedId(
Notes.CONTENT_URI, rowId);
getContext().getContentResolver().notifyChange(
noteUri, null);
return noteUri;
}
default:
throw new IllegalArgumentException(
"URI desconhecida " + uri);
}
}
@Override
public boolean onCreate() {
mHelper = new DBHelper(getContext());;
return true;
}
@Override
public Cursor query(Uri uri, String[] projection, String selection,
String[] selectionArgs, String sortOrder) {
// Aqui usaremos o SQLiteQueryBuilder para construir
// a query que será feito ao DB, retornando um cursor
// que enviaremos à aplicação.
SQLiteQueryBuilder builder = new SQLiteQueryBuilder();
SQLiteDatabase database = mHelper.getReadableDatabase();
Cursor cursor;
switch (mMatcher.match(uri)) {
case NOTES:
// O Builer receberá dois parametros: a tabela
// onde será feita a busca, e uma projection -
// que nada mais é que uma HashMap com os campos
// que queremos recuperar do banco de dados.
builder.setTables(NOTES_TABLE);
builder.setProjectionMap(mProjection);
break;
default:
throw new IllegalArgumentException(
"URI desconhecida " + uri);
}
cursor = builder.query(database, projection, selection,
selectionArgs, null, null, sortOrder);
cursor.setNotificationUri(getContext().getContentResolver(), uri);
return cursor;
}
@Override
public int update(Uri uri, ContentValues values, String selection,
String[] selectionArgs) {
SQLiteDatabase db = mHelper.getWritableDatabase();
int count;
switch (mMatcher.match(uri)) {
case NOTES:
count = db.update(NOTES_TABLE, values,
selection, selectionArgs);
break;
default:
throw new IllegalArgumentException(
"URI desconhecida " + uri);
}
getContext().getContentResolver().notifyChange(uri, null);
return count;
}
/////////////////////////////////////////////////////////////////
// Inner Classes utilitárias //
/////////////////////////////////////////////////////////////////
public static final class Notes implements BaseColumns {
public static final Uri CONTENT_URI = Uri.parse("content://"
+ QuickNotesProvider.AUTHORITY + "/notes");
public static final String CONTENT_TYPE =
"vnd.android.cursor.dir/" + QuickNotesProvider.AUTHORITY;
public static final String NOTE_ID = "_id";
public static final String TEXT = "text";
}
private static class DBHelper extends SQLiteOpenHelper {
DBHelper(Context context) {
super(context, DATABASE_NAME, null, DATABASE_VERSION);
}
/* O método onCreate é chamado quando o provider é executado pela
* primeira vez, e usado para criar as tabelas no database
*/
@Override
public void onCreate(SQLiteDatabase db) {
db.execSQL("CREATE TABLE " + NOTES_TABLE + " (" +
Notes.NOTE_ID + " INTEGER PRIMARY KEY AUTOINCREMENT," +
Notes.TEXT + " LONGTEXT" + ");");
}
/* O método onUpdate é invocado quando a versão do banco de dados
* muda. Assim, é usado para fazer adequações para a aplicação
* funcionar corretamente.
*/
@Override
public void onUpgrade(SQLiteDatabase db,
int oldVersion, int newVersion) {
// Como ainda estamos na primeira versão do DB,
// não precisamos nos preocupar com o update agora.
}
}
}
Cursores
O primeiro conceito importante a se falar é o conceito dos Cursores. Como você deve percebido, este é o tipo de retorno do método query(), e não é por acaso: Os cursores são “apontadores de dados” do banco de dados – ou seja, uma interface que permite o acesso aos dados retornados pela query enviada pelo usuário.
notifyChanges()
Em todos os métodos em que alteramos o banco de dados (inserimos, deletamos ou modificamos dados) é importante chamar o método modifyChanges(). Isso fará com que as aplicações que estejam utilizando este conjunto de dados sejam notificadas, permitindo a estas atualizar também os dados mostrados ao usuário.
No próximo post iremos usar o QuickNotesProvider na nossa aplicação.

Posts Relacionados



Cara, eu estou começando a programar para Android, participo de um fórum chamado Portal Android (www.portalandroid.org). Seu artigo ía ser super bem vindo lá
abraço, muito bom o artigo!
Felipeee,, po cara eu nao to conseguindo compila pq deu erro no meu AndroidMainfest.xml, eu declarei o , entre , mas está dando o seguinte erro:
Class br.com.felipesilveira.quicknotes.provider does not exist.
o que nao existe, o que eu esqueci d modificar? valew grande abraço, e tá muito legal, só q tá dificil d digita, muita paciencia, muitos erros, tenho certeza q esse é um erro bobo kaka!!! valew parabéns!
Olá Felipe… estou com duvidas quanto a criar a classe “helper” e quanto ao codigo acima vai todo na provider!?
att.
Paulo.
Oi Paulo, ele vai todo no provider sim!
Um abraço
A mim deu alguns erros resolvi pondo:
em vez de
e ao copiar para o clipboard ele copia
if (rowId > 0) { mas deverá ser if (rowId > 0) {
Depois dá erro no processo quando corro o sdk
**continuação
em vez de ();
tive de por
Tipo, na linha onde você coloca o CONTENT_URI (no método Notes do Provider).
você faz o “content://authority/NOTES”
O que é esse /NOTES? Devo criar essa pasta onde?
Porque para mim, ao fazer isso, dá Unknowk URL.
Achei o que era.
No seu projeto, você teve que cadastrar o namespace do provider.
Acho que esqueceu de mencionar isso no tutorial.
Obrigado.
Ah sim. Obrigado Zebra!
Agora estou com uma nova dúvida.
quero organizar meu projeto, então fiz assim:
Na src, eu tenho:
com.meuprojeto (nesse package, tenho as Activity)
com.meuprojeto.entidades (aqui montei a entidade Anotacoes)
com.meuprojeto.acessodados (aqui coloquei o provider da Anotacoes)
No AndroidManifest, só posso setar 1 package. Então passei o com.meuprojeto
Ainda no Manifest, passei o provider corretamente (com.meuprojeto.acessodados.provideranotacoes)
Sei que não está certo, pois ao executar a aplicação, diz que não é possível localizar o meu provider, porque ele tenta achar em “com.meuprojeto.provideranotacoes”, sendo que ele está em com.meuprojeto.acessodados.provideranotacoes.
Será que você entendeu o jeito que eu quero organizar o projeto e poderia me dar uma força?
Quero simplesmente, para cada tabela, seu respectivo provider fique dentro de um package diferente do com.meuprojeto.
É possível?
Valeu, cara. Teu tutorial é excelente!
Olá.
Quando puder responder, por favor. Ainda estou no aguardo.
Como proceder para efetuar uma organização e separação de camadas em meu projeto conforme exemplifiquei acima.
Obrigado.
Consegui.
No Manifest.xml, ao invés de passar o o nome do Provider como .MeuProvider, passe .acessodado.MeuProvider e bingo! funcionou.
Agora sim vou separar meu projeto por package e vai ficar zero bala!
Valeu, camarada!
Continua com os posts e novas técnicas no Android! Falow
Legal Zebra!
Eu também estava aqui tentando entender o que havia acontecido, que bom que deu certo. Valeu!
Sabe o que você poderia fazer? Um artigo sobre personalização dos componentes do Android (os widgets)
Estilizar os componentes. por exemplo… quero o meu modelo de ComboBox ou Button e não usar os default, entendeu?
No Flex (que também é com Eclipse), tem um recurso para você manipular o style de cada componente. Posso, por exemplo, fazer um simples combobox ter a estética de algo desenha a mão por uma criança.
Gostaria de saber como manipular os stilos dos componentes.
Funciona CSS?
Olá cara.
Mais uma dúvida.
No exemplo de provider que você fez, lá no método “insert”.
Você recebe pelo parâmetro a URI e o ContentValues, que é o conteúdo das respectivas colunas. Certo?
Bom, no seu exemplo, o cara só insere um texto e clica em “inserir”. Ao fazer isso, você faz o seguinte:
SQLLiteDB.insert(Nometabela, Coluna.TEXT, ContentValues);
Tudo isso te retornar o ID do insert. Blz, ótimo.
Mas olhando o método insert do SQLLite, ele aceita apenas uma coluna no segundo parâmetro.
E se no meu insert, eu tiver NOME, ENDERECO e TELEFONE, como vou passar esses parâmetros no lugar do “Coluna.TEXT”? É um tipo String. Se fosse array…
Não entendi como fazer um insert com várias colunas.
Tenho que ficar fazendo:
SQLLiteDB.insert(Nometabela, Coluna.NOME, ContentValues);
SQLLiteDB.insert(Nometabela, Coluna.ENDERECO, ContentValues);
SQLLiteDB.insert(Nometabela, Coluna.TELEFONE, ContentValues);
?
Não acho que seja assim. E mesmo que seja, como vou saber que ele está inserindo no mesmo escopo e para o mesmo registro?
Ou então, como vou dizer para o ContentValues qual coluna é qual?
Poderia me explicar melhor isso?
Obrigado.
Ah, achei como fazer. Apesar do parâmetro receber uma String, olhando a documentação do SQLite, no método insert, notei que ele aceita a string com separados, e o resto, ele se vira!
http://www.sqlite.org/lang_insert.html
Então, o que fiz foi criar uma string, jogar minhas colunas separadas por , (vírgula), e zap, inseriu n colunas. Nem precisei mudar o ContentValues. Ele já se adapta a quantidade de colunas que eu mandei. Muito prático isso.
Valeu, amigo.
Agora, me surgiu uma dúvida. Percebi que, o usuário pode, indo nas configurações, desinstalar minha aplicação ou excluir apenas a base de dados. Haveria uma maneira de evitar que o usuário possa excluir a base de dados?
Caso não for possível, onde é que fica salvo o base que eu criei? Em que local fisicamente no pocket fica a base criada?
VAleu, camarada.
Oi Zebra!
Quando eu consigo vir aqui para te responder vc ja achou a solução.. hehe. Obrigado por compartilhar as dúvidas e soluções, está enriquecendo bastante o conteúdo do post!
Quanto à sua pergunta, fisicamente os dados ficam armazenados em /data/data//databases
Abraço!
O que você sugere com relação aos provider?
1 Provider para cada tabela do banco?
Exemplo:
ProviderUsuarios.java (para tabela tUsuarios)
ProviderPedidos.java (para tabela tPedidos)
ProviderItens.java (para tabela tItens)
ou um provider só, com tudo dentro?
ProviderGlobal.java (e dentro, os métodos para criar e manipular as tabelas tUsuarios, tPedidos e tItens)?
O ideal é criar uma Uri para cada uma das tabelas que voce citou, porém sendo tratadas pelo mesmo provider.
Tipo, eu fiz assim…
No AndroidManifest, adicionei dois providers.
Então, para cada um, criei uma respectiva classe .java que extende de um ContentProvider.
O problema é, ele não está criando a segunda tabela. Sei lá. Na hora de tentar inserir registro, diz que a tabela Usuarios nao existe, que meu URI tá apontando para o caminho errado, mas ele está certo.
Oi zebra,
Verifique se a função para criação da tabela está correta. Pode ser que tenha algum erro… é o que eu imagino que pode ter acontecido.
Tá estranho isso. Acho que to fazendo errado.
Tenho uma classe chamada ProviderUsuarios. Nela, tenho os métodos que você fez e funciona. Tudo ok.
O que fiz?
criei uma nova Provider, com o nome de ProviderClientes.
Fui lá no Manifest, a adicioneu esse 2º provider. ou seja, é idêntica a primeira, mas só muda o alvo (que é a tabela de clientes)
O detalhe é que, ao rodar a plicação, coloquei um breakpoint na hora o create table da Usuarios e da cliente.
Na da Usuarios, ele passa e cria. Na de Cliente, ele nem passa.
Não posso ter dois provider no manifest? Só um?
Cara, aparentemente, não é permitido fazer o que eu quero.
Gostaria de ter uma classe Provider para cada tabela, pois assim a manutenção fica muito mais fácil.
Após testar várias maneiras organização, defini que não é possível fazer isso. Se você tiver dois Provider, cada um para sua tabela, e mesmo adicionando ambos no AndroidManifest, somente 1 delas executa o onCreate de sí mesmo. A outra, só se consegue acessar os métodos (insert, update). Estranhamente, nunca passa no onCreate.
Realmente, não compreendo isso.
Vou ser obrigado a criar 1 Provider, e dentro dele, gerenciar todas as tabelas de que precisa. Que chute na canela isso.
Triste…
Entendi… bom, como te falei anteriormente, geralmente criamos um provider só, e entao criamos diferentes Uris para tratar as tabelas.
Boa sorte!
Você diz então, no caso…
crio um Provider, e no onCreate dele, efetuo todos os create de todas as tabelas de que preciso? É isso?
To tentando fazer aqui tudo num único provider, mas me surgiu a dúvida.
Isso não vai ficar lento?
Tipo, o que to fazendo…
estou criando a variavel NomeTabela para cada tabela, criando um UriMather para cada tabela, uma projecao para cada tabela, e assim por diante.
tá certo isso?
Cara, não consegui achar um jeito bacana de fazer isso.
Poderia, por favor, com base no seu QuickNotesProvider, posta um modelo adaptável a duas ou mais tabelas?
Ainda estou cru no processo de chamadas do Android, e devido a isso, não consigo enchergar um padrao para usar.
Muito obrigado.
Zebra, é uma boa idéia. Vou preparar um post sobre isso, incrementando um pouco o QuickNotes.
Um abraço!
Valeu, cara.
Fico no aguardo!
Consegui!
Fiz assim: criei um ProviderBase. Nele, fiz os métodos base (insert, delete, update, query e gettype). Nessa classe, deixei todas as constantes que são a mesma independente da tabela (authority, nome do banco, versão, ContentType, etc…). Também criei um URIMatcher e Projeção para cada tabela.
No onCreate desse Provider, fiz o create das tabelas.
Para pode efetuar a separação que eu queria, bastou então criar as classes de cada tabela, e nelas, as respectivas colunas. Então, na ProviderBase, apenas faço um import das minhas classes de tabela e zap, ficou do jeito que eu queria.
Está assim:
ProviderBase (toda a estrutuda de acesso a dados)
- tUsuarios (classe de usuários que contém apenas o baseColumn e algumas outras regrinhas específicas da tabela)
- tClientes (idem)
E para diferenciar as requisições a ProviderBase (ou seja, quem está chamando: Usuario ou Clientes), fiz um case atravé do retorno da URIMAtcher.
Assim, case “Usuario”: faz as ações dele, usando os métodos na classe tUsuario.
case “Cliente”, faz as ações dele, usando os métodos na classe tCliente.
Perfeito.
Muito bom.
Valeu pela ajuda, cara. Se seu artigo, jamais teria chego numa solução bacana e organizada para meu propósito.
valeu!
Uma dúvida quanto a construção: seria possível cria separadamente as classes Note e DBHelper, ao invés de deixa-las internamente?? Isso afeta em alguma coisa no desempenho??
Sou iniciante em programação mobile, mas sei que todo o ganho de performace, mesmo que pequeno, é muito bem-vindo.
Obrigado e parabéns pelo site.
Diego Moreira
Oi Diego,
Não não existe nenhuma limitação, você pode organiza-las da forma que quiser
Obrigado!
Felipe, bom dia.
tenho duas perguntas:
1 – O banco de dados SQLite + Android suportam transações (Begin, Commit e Rollback)?
2 – Você faz trabalho de free-lance?
temos um sistema de força de venda escrito em C# e gostariamos de “migrá-lo para a plataforma Android.
Grato.
Oi Marcelo,
Voce pode ver a documentação de transactions em SQLite aqui > http://www.sqlite.org/lang_transaction.html Mas nunca testei em android.
Quanto a free-lance, infelizmente eu não faço, por falta de tempo.
Obrigado!
Olá Felipe, desde já agredeço e te dou os parabéns por todos os tutoriais sobre Android disponíveis em seu blog. Estou com um problema em trabalhar com Banco de Dados em android, segui todo seu tutorial e aqui da o seguinte erro:
05-04 20:39:51.598: ERROR/Database(815): android.database.sqlite.SQLiteException: table usuarios has no column named nome: , while compiling: INSERT INTO usuarios(nome) VALUES(?);
Você tem alguma ideia do que seja?
Obrigado!
Att Dalton
Felizpe…
Me responde uma coisa…
Usei seu exemplo e a partir dele criei um provider cabuloso para minhas aplicações. Muito bom mesmo.
Minha dúvida agora é: qual a melhor maneira de trabalhar com um banco de dados já criado (ou seja, já modelado num SQLite Managementes).
Já tenho o banco.db
No caso, precisaria que esse banco fosse junto com a aplicação e já fosse jogado no local certo minha minha aplicação atual funcionar.
Hoje, de acordo com seu exemplo, o provider verifica se o banco existe… se não existe, ele cria tudo. Blz até aqui.
Mas eu gostaria de agora enviar o banco já pronto, e ao rodar minha aplicaçao pela primeira vez, ele já reconhecesse que o banco está lá.
COmo proceder?
Onde devo jogar o banco?
Boa Tarde Felipe, estou tendo um problema quanto a URI do meu provider.
Tenho o package br.com.agenda.agendaprovider e dentro dele tenho minha Classe AgendaProvider que extende o ContentProvider.
No meu manifest tenho:
O meu AUTHORITY = “br.com.agenda.agendaprovider.agendaprovider”
e
o meu Uri CONTENT_URI = Uri.parse(“content://” + AgendaProvider.AUTHORITY);
Com isso tenho o erro de IllegalArgumentException URI desconhecida. Podesme dizer se configurei corretamente?
Obrigado
Provider no manifest
provider
android:authorities=”br.com.agenda.agendaprovider.agendaprovider”
android:name=”br.com.agenda.agendaprovider.AgendaProvider”
Olá Felipe, parabéns pelo tutorial, muito bom mesmo.
Está dando erro na linha abaixo:
query(QuickNotesProvider.Notes.CONTENT_URI, null, null, null, null);
O erro é: “QuickNotesProvider cannot be resolved to a variable”
Eu coloquei o provider no AndroidManifest.XML manualmente.
Não consigo achar onde está errado.
Obrigado pela atenção
Olá Henrique, tudo bem?
Seguindo os nomes que voce usou, no meu manifest ficou assim:
provider
android:authorities=”br.com.agenda.agendaprovider”
android:name=”.agendaprovider”
Bom dia
Estou fazendo teste utilizando a plataforma Android e surgiram varias duvidas, que na web nao consegui uma resposta clara.
1º Ao criar uma aplicação no eclipse tem como definir se essa aplicação será uma biblioteca. Sendo assim posso usar esse projeto na minha aplicação principal. a pergunta é tem como atualizar so o biblioteca inserida na minha aplicação principal? e como fazer isso.
2º Quais os tipos de atualizações de aplicativos possso fazer?
É notifyChanges ou modifyChanges?
Boa Tarde Felipe,
Estou tentando aplicar esses posts dentro do MotoDev, porém essa situação não está se resolvendo. O seu código está correto nesse ponto abaixo?
private static HashMap mProjection;
static {
mProjection = new HashMap();
Essa string é derivada do Android e o String é o tradicional do Java? Porque não compila desse jeito, só compila no formato abaixo:
private static HashMap mProjection;
static {
mProjection = new HashMap();
O que estou fazendo de errado? Pois depois sigo o próximo post para tentar a inserção e está dando erro.
Obrigado
Oi Marcelo,
Os dois códigos que você postou estão idênticos, e ambos compilam para mim.
Verifique se você fez o import da classe HashMap.
Obrigado!
Não entendi o “Notes.CONTENT_URI” onde esta o Notes que tanto se usa??
Esse banco de dados criado fica em algum local ou pasta?? eu tenho como abrir ele e inserir informações sem ser pelo eclipse??
Ola Felipe,
Sou novato nesta parte de android. Copiei o codigo que vc sugeriu e verifiquei q o o metodo getContext() fica marca do como erro. Pesquisei e nao encontrei no codigo. Poderia me ajudar?
Abraço e parabens pelo trabalho.
Felipe… estou com uma duvida com o HashMap. Eu já inclui ela no codigo, mas a parte:
private static HashMap mProjection;
me o seguinte erro: Erro de sintaxe no token “,”, TypeArgument1 esperado depois desse token
Sendo que se eu mudar para:
private static HashMap mProjection;
não ocorre erros. Mas eu vi pelo site do developer, que HashMap pode ser implementado com HashMap. Agora fiquei confuso… como eu uso corretamente esse HashMap??
Felipe… estou com uma duvida com o HashMap. Eu já inclui ela no codigo, mas a parte:
private static HashMap / mProjection;
me o seguinte erro: Erro de sintaxe no token “,”, TypeArgument1 esperado depois desse token
Sendo que se eu mudar para:
private static HashMap / mProjection;
não ocorre erros. Mas eu vi pelo site do developer, que HashMap pode ser implementado com HashMap. Agora fiquei confuso… como eu uso corretamente esse HashMap??
Galera… quem esta tendo erro com o HashMap do codigo do Felipe, NÃO se desespere. O codigo dele esta correto, o problema e com a interpretação do browser. Então ou copie o codigo dele a partir do codigo-fonte da pagina, ou acesse aqui e pegue o codigo dele sem problemas de navegador. ok?
http://pastebin.com/FAZr9LfS
parabéns pelos artigos Felipe!