Desenvolvendo para Android: conheça mais componentes

Quais são os próximos passos para o desenvolvimento Android? Um aplicativo simples nós já fizemos, agora é hora de conhecer outras funcionalidades para criar aplicativos mais elaborados.

A ideia deste post é mostrar como é feita a navegação entre telas de um aplicativo, o uso de banco de dados para Android e a utilização de componentes internos do aparelho como por exemplo utilizar as imagens salvas na galeria.

Para demonstrar essas funcionalidades seguiremos como exemplo a criação de um aplicativo para cadastrar livros e consultar os livros que foram adicionados.

O primeiro passo é criar o projeto. Se tiver em dúvida de como fazer, releia o post anterior Desenvolvendo para Android: Montando um aplicativo simples.

Crie o projeto com o nome “Minha biblioteca”. A estrutura no final do projeto deve ser similar a essa:

estruturaFigura 1 – Estrutura do projeto

Crie a classe “Livro” pois ela será a nossa entidade principal utilizada no aplicativo.

public class Livro implements Serializable {

private static final long serialVersionUID = 1L;

private String titulo;
private String autor;
private String resumo;
private double avaliacao;
private String pathImagem;

//Getters e setters</span>
Listagem 1 – Classe Livro

A primeira tela a ser exibida será uma lista de opções. Para  gerar essa tela é necessário criar o layout “activity_minha_biblioteca.xml”.

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="wrap_content"
android:layout_height="fill_parent"
android:orientation="vertical"
tools:context=".MinhaBibliotecaActivity" >

<ListView
android:id="@+id/lista_menu"
android:layout_width="fill_parent"
android:layout_height="fill_parent" >
</ListView>

</LinearLayout>
Listagem 2 – Layout activity_minha_biblioteca.xml

O componente “ListView” é usado quando se quer criar uma lista. Na classe “MinhaBibliotecaActivity” abaixo,  podemos ver que na linha 10 é instanciado o listView e na próxima linha é definido os itens que vão ser exibidos na lista. O próximo passo é fazer com que ao se clicar em uma das opções, seja aberta a tela correspondente. Para isso é definido no método “onItemClick” o que deve ser chamado conforme a posição que o item estiver na lista, por exemplo, se clicar no primeiro item que corresponde ao índice zero da lista, o aplicativo abrirá a página de coleções, se for escolhida a segunda opção será aberta a página para adicionar um novo livro.

public class MinhaBibliotecaActivity extends Activity {

private ListView listaOpcoesMenu;

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

listaOpcoesMenu = (ListView) findViewById(R.id.lista_menu);
String[] values = new String[] { "Minha coleção", "Adicionar" };

ArrayAdapter<String> adapter = new ArrayAdapter<String>(this,
android.R.layout.simple_list_item_1, android.R.id.text1, values);

listaOpcoesMenu.setAdapter(adapter);</span>
listaOpcoesMenu.setOnItemClickListener(new OnItemClickListener() {

@Override
public void onItemClick(AdapterView<?> parent, View view,
int position, long id) {

int itemPosition = position;

if (itemPosition == 0) {
Intent intent = new Intent(MinhaBibliotecaActivity.this, ColecaoActivity.class);
startActivity(intent);
}

if (itemPosition == 1) {
Intent intent = new Intent(MinhaBibliotecaActivity.this, NovoItemActivity.class);
startActivity(intent);
}
}

});

}

@Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.minha_biblioteca, menu);
return true;
}

}
Listagem 3 – Classe MinhaBibliotecaActivity

Para navegar entre as telas, podemos ver no exemplo que é muito fácil, basta instanciar o objeto “Intent” passando qual é a activity atual e qual é a activity que se deseja abrir.

Agora para criar as outras duas telas é necessário primeiro criar o banco de dados, que armazenará as informações no próprio aparelho. A biblioteca que usaremos para fazer a persistência de dados é o SQLite.

Crie primeiro a classe “Banco” estendendo a classe “SQLiteOpenHelper” que é responsável pela interação com o banco. O método “onCreate” é utilizado para criar a tabela no banco, é nele que deve ser informada as colunas da tabela.

@Override
public void onCreate(SQLiteDatabase db) {

db.execSQL("CREATE TABLE livro ("
+ "id_livro INTEGER PRIMARY KEY autoincrement,"
+ " titulo varchar(45) NOT NULL ,"
+ " autor varchar(45) NOT NULL,"
+ " resumo varchar(125) NOT NULL,"
+ " path_imagem varchar(125) NOT NULL,"
+ " avaliacao double NOT NULL"+ ");");
}
Listagem 4 – Código para criação do banco de dados

Depois crie a classe “BancoService”,  que será responsável por se comunicar com o banco, ou seja, é nela que estão os métodos que acessam o banco, como retornar uma lista de livros através do método “getAllLivros” ou salvar um livro utilizando o método “salvarLivro”, que basicamente cria uma instância da classe “Banco” e da classe “ContentValues” que é a classe que recebe os valores a serem salvos no banco. Usando o “ContentValues” é informado o nome da coluna da tabela e a informação que corresponde a essa coluna. Depois, através do objeto do banco que foi instanciado,  é chamado o método “getWritableDatabase().insert” que recebe o contentValues com os valores para inserir no banco.

public class BancoService {

public List<Livro> getAllLivros(Context context) {

Banco banco = new Banco(context, "banco", null, 1);

Cursor cursor = banco.getWritableDatabase().query(
"livro",
new String[] { "id_livro", "titulo", "autor", "resumo",
"path_imagem", "avaliacao" }, null, null, null, null,
null);

List<Livro> livros = new ArrayList<Livro>();

while (cursor.moveToNext()) {

Livro livro = new Livro();
livro.setTitulo(cursor.getString(1));
livro.setAutor(cursor.getString(2));
livro.setResumo(cursor.getString(3));
livro.setPathImagem(cursor.getString(4));
livro.setAvaliacao(cursor.getDouble(5));
livros.add(livro);
}

cursor.close();
banco.close();
return livros;
}

public void salvarLivro(Livro livro, Context context) {

try {

Banco banco = new Banco(context, "banco", null, 1);

ContentValues contentValues = new ContentValues();
contentValues.put("titulo", livro.getTitulo());
contentValues.put("autor", livro.getAutor());
contentValues.put("resumo", livro.getResumo());
contentValues.put("avaliacao", livro.getAvaliacao());
contentValues.put("path_imagem", livro.getPathImagem());
banco.getWritableDatabase().insert("livro", null, contentValues);

Toast toast = Toast.makeText(context,"Livro cadastrado com sucesso!!", 5);
toast.show();
banco.close();

} catch (Exception e) {
Toast toast = Toast.makeText(context,"Erro ao salvar informações no banco!", 5);
toast.show();
}
}

}
Listagem 5 –  Classe responsável pela interação com o Banco de Dados 

Com o banco criado e retornando os livros salvos é necessário criar as telas que utilizaremos para alimentar o banco.

A primeira tela será a interface responsável por adicionar os livros. Crie o layout “adicionar_item.xml” que conterá os componentes para informar os dados do livro.

A activity que está relacionada a este layout é a “NovoItemActivity”. O primeiro trecho de código importante desta classe é a parte onde é utilizado um Intent que é utilizado para executar uma chamada a algum recurso interno ou externo da aplicação, no exemplo será utilizado para fazer a chamada à seleção de arquivos do aparelho, com filtro de imagens.  Essa chamada é realizada no evento de click do botão adicionar.

btnInserirImagem.setOnClickListener(new OnClickListener() {

@Override
public void onClick(View arg0) {

Intent intent = new Intent();
intent.setType("image/*");
intent.setAction(Intent.ACTION_GET_CONTENT);
startActivityForResult(
Intent.createChooser(intent, "Selecione uma imagem"), 1);
}

});
Listagem 6 – Código para buscar imagens salvas no aparelho.

Depois de escolhida uma imagem o método “onActivityResult” é chamado. Ele é responsável por pegar o caminho da imagem salva no aparelho, exibir ela na tela e salvar seu caminho em um dos atributos do livro.

protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);

if (requestCode == 1 && resultCode == RESULT_OK && null != data) {

Uri selectedImage = data.getData();
String[] filePathColumn = { MediaStore.Images.Media.DATA };

Cursor cursor = getContentResolver().query(selectedImage,
filePathColumn, null, null, null);
cursor.moveToFirst();

int columnIndex = cursor.getColumnIndex(filePathColumn[0]);
String picturePath = cursor.getString(columnIndex);
cursor.close();
imagemLivro.setImageBitmap(BitmapFactory.decodeFile(picturePath));
pathImagem = picturePath;
}
}
Listagem 7 –  Código que obtém o caminho da imagem. 

Outra parte importante a ser comentada desta classe é o que acontece quando se clica no botão “Adicionar”. O clique no botão chama o método “onClick” que preenche os atributos da classe “Livro” com as informações passadas na tela e através da classe Banco Service é chamado o método que é responsável por salvar os dados do livro no aparelho. 

private BancoService bancoService;
bancoService = new BancoService();

btnAdicionar.setOnClickListener(new OnClickListener() {

@Override
public void onClick(View arg0) {

Livro livro = new Livro();
livro.setTitulo(txtTitulo.getText().toString());
livro.setAutor(txtAutor.getText().toString());
livro.setResumo(txtResumo.getText().toString());
livro.setAvaliacao(avalicoesLivro.getRating());
livro.setPathImagem(pathImagem);

bancoService.salvarLivro(livro, getApplicationContext());

txtTitulo.setText("");
txtAutor.setText("");
txtResumo.setText("");
avalicoesLivro.setRating(1);
pathImagem = "";
imagemLivro.setBackgroundResource(R.drawable.ic_launcher);
imagemLivro.setImageBitmap(null);

}

});
Listagem 8 – Código usado para salvar os dados informados no banco de dados.

Pronto! A primeira tela que insere os dados no banco está pronta. O próximo passo é criar a tela que listará os livros já criados. Para isso é necessário criar a o layout “lista_livros.xml”. Nesse layout deve conter um elemento “ImageView” e um “TextView” que exibirá o título e a imagem de cada livro salvo no banco.

Crie a activity “ColecaoActivity” estendendo a classe “ListActivity”. “A ListActivity é uma classe filha da Activity cujo objetivo é mostrar ao usuário uma Lista (uma ListView). Em suma, é uma Activity com alguns métodos para gerenciamento de listas, criada com o intuito de facilitar a criação de telas com essa configuração, muito comuns nas aplicações Android.” [3].

No método “onCreate” é criada uma instância da classe “BancoService” que possui o método que retorna todos os livros cadastrados para a lista de livros instanciada na classe. Depois é adicionado no método “setListAdapter” uma nova instância da classe “LivroAdapter”. Outro método que essa classe possui é o “onListItemClick” que é chamado toda vez que se clica em um item da lista de livros, abrindo a classe “DetalheItemActivity” que exibe os dados do livro escolhido.

public class ColecaoActivity extends ListActivity {

private List<Livro> livros;

@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);

BancoService bancoService = new BancoService();
livros = bancoService.getAllLivros(getApplicationContext());
setListAdapter(new LivroAdapter(this, livros));
}

@Override
protected void onListItemClick(ListView l, View v, int position, long id) {
super.onListItemClick(l, v, position, id);

Livro livro = livros.get(position);

Intent intent = new Intent(this, DetalheItemActivity.class);
intent.putExtra("livro", livro);
startActivity(intent);
}

}
Listagem 9 – Código usado para exibir os dados de um livro escolhido.

A classe “LivroAdapter” nada mais é que uma classe que representa cada elemento que se deseja exibir em um “ListView”. O principal método é o “getView” que é o responsável por passar as informações para o layout “lista_livros.xml” criado anteriormente.

@Override
public View getView(int position, View convertView, ViewGroup parent) {

Livro livro = livros.get(position);

LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
View view = inflater.inflate(R.layout.lista_livros, null);

TextView txttitulo = (TextView) view.findViewById(R.id.txtTituloLivro);
txttitulo.setText(livro.getTitulo());

ImageView imagemLivro = (ImageView) view.findViewById(R.id.imagemLivro);
imagemLivro.setImageBitmap(BitmapFactory.decodeFile(livro.getPathImagem()));

return view;
}
Listagem 10 – Código que é usado para montar cada item da lista de livros salvos.

E por último falta criar o layout “detalhes_item.xml” que é a tela exibida depois que é selecionado um item da lista de livros. Basicamente este layout utiliza componentes de texto e imagem para exibir as informações do livro escolhido.

Para exibir as informações no layout é necessário criar a classe “DetalheItemActivity” que instanciará os componentes do layout e setará as informações do livro escolhido.

public class DetalheItemActivity extends Activity{

private ImageView imagemLivro;
private TextView txtTitulo;
private TextView txtAutor;
private TextView txtResumo;
private RatingBar avalicoesLivro;
private Livro livro;

@SuppressLint("UseValueOf")
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);

setContentView(R.layout.detalhes_item);
livro = (Livro) getIntent().getSerializableExtra("livro");

imagemLivro = (ImageView) findViewById(R.id.imagem_livro);
txtTitulo = (TextView) findViewById(R.id.txtTitulo);
txtAutor = (TextView) findViewById(R.id.txtAutor);
txtResumo = (TextView) findViewById(R.id.txtResumo);
avalicoesLivro = (RatingBar) findViewById(R.id.avaliacaoLivro);

imagemLivro.setImageBitmap(BitmapFactory.decodeFile(livro.getPathImagem()));
txtTitulo.setText(livro.getTitulo());
txtAutor.setText(livro.getAutor());
txtResumo.setText(livro.getResumo());
avalicoesLivro.setRating(new Float(livro.getAvaliacao()));
}

}
Listagem 11 – Código que é usado exibir os detalhes do livro selecionado

Por último é necessário declarar todas as activitys criadas no arquivo “AndroidManifest.xml” e também definir a permissão para escrever na memória do aparelho, para que possamos armazenar  os dados da aplicação  no banco.

<?xml version="1.0" encoding="UTF-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.minhabiblioteca"
android:versionCode="1"
android:versionName="1.0" >

<uses-sdk
android:minSdkVersion="8"
android:targetSdkVersion="8" />

<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />

<application
android:allowBackup="true"
android:icon="@drawable/ic_launcher"
android:label="@string/app_name"
android:theme="@style/AppTheme" >
<activity
android:name=".ui.MinhaBibliotecaActivity"
android:label="@string/app_name" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity android:name=".ui.ColecaoActivity" />
<activity android:name=".ui.NovoItemActivity" />
<activity android:name=".ui.DetalheItemActivity" />

</application>

</manifest>

Listagem 12 – AndroidManifest.xml

Pronto! Mais um aplicativo feito na plataforma Android!! Não é difícil, basta apenas entender como funciona a estrutura da linguagem e como é a sua interação, porque de resto é só usar a imaginação para criar vários aplicativos legais.

O projeto completo utilizado como exemplo no post está disponibilizado em: https://sourceforge.net/projects/minhabibliotecaandroid/files/

Abaixo algumas imagens de como ficou o aplicativo.

Untitled 1

Figura 2 – Telas do aplicativo

Untitled 2

Figura 3 – Telas do Aplicativo


No próximo post da sequência “Desenvolvendo para Android”, será mostrado como automatizar os testes de um aplicativo Android.

Referências

[1] http://romarconsultoria.blogspot.com.br/2011/03/criando-um-listadapter-customizado-para.html

[2] http://blog.chrisblunt.com/android-getting-started-with-databases-and-contentproviders-part-1/

[3] http://www.felipesilveira.com.br/2010/11/criando-uma-listactivity/

Por MONISE COSTA

Formada em Sistemas de Informação pela PUC Campinas, MATERANA desde 2011. Apaixonada pela área de TI, Analista de Requisitos na maior parte do tempo e desenvolvedora Java/Android por lazer.

Postado em: 17 de março de 2014

Confira outros artigos do nosso blog

[Webinar] Profile de aplicações Java com Oracle Mission Control e Flight Recorder

24 de julho de 2017

Danival Calegari

Criando Mocks de serviços REST com SoapUI

27 de junho de 2017

Monise Costa

Three laws that enable agile software development

09 de março de 2017

Celso Gonçalves Junior

Medindo performance de uma API REST

21 de fevereiro de 2017

Monise Costa

Deixe seu comentário