quarta-feira, 16 de setembro de 2009

Curso de Android em Recife


Olá povo,

Estou lançando em parceria com a Especializa Treinamentos o curso de desenvolvimento de aplicações para a plataforma Android. As aulas serão ministradas por mim e o conteúdo do curso será baseado no livro do Ricardo Lecheta.
No curso, estudaremos tudo sobre essa revolucionária plataforma de desenvolvimento para smartphones. Os conceitos de Activities, Handles, ContentProvider e Services serão aplicados na prática. Vamos ver como armazenar informações no banco de dados do celular com SQLite. Comunicação com WebServices e com o GoogleMaps. Envio de SMS. E muito mais.

Quem tiver interesse, entre em contato com a Especializa ou comigo através do meu e-mail.

4br4ç05,
nglauber

terça-feira, 15 de setembro de 2009

Google Maps com Android 1.5

Olá povo,

Aqui vai um passo-a-passo pra quem for utilizar a API do GoogleMaps no Android.

Pré requisitos:
Android SDK 1.5
Eclipse Ganymede
Plugin ADT (Android Developer Tools) 0.9.1
JDK 1.5 ou superior com o diretório bin na variável de ambiente PATH.

Passo 1:
Obtenha o código do certificado digital que é usado para assinar as aplicações. Toda vez que o Eclipse executa uma aplicação Android ele gera um APK (Android PacKage) assinado. Essa assinatura é gerada a partir de um certificado digital de testes chamado debug.keystore que fica na pasta home do seu usuário. No meu caso, no Windows XP o caminho foi: C:\Documents and Settings\ngvl\.android\debug.keystore.

Para obter o código do certificado digital, utilizaremos a ferramenta keytool que vem com o JDK. Abra um terminal/prompt de comando e digite:

keytool -list -alias androiddebugkey -keystore "caminho do seu debug.keystore“

Será solicitado usuário e senha, digite "android" para ambos. Será gerado um resultado semelhante a esse:

androiddebugkey, 30/08/2009, PrivateKeyEntry,
Certificate fingerprint (MD5): AB:DB:39:2F:30:FC:7E:28:2B:7F:BF:54:7B:44:DF:C4


Passo 2:
Acesse o site http://code.google.com/android/maps-api-signup.html (é necessário ter uma conta do Google) digite o Certificate fingerprint no local indicado. Clique em "Generate API key". Será gerada uma chave parecida como a de baixo:

0CjoPthXnVvE9Uz3TW1d-ng82vlrdeTVBda4VPw


Pronto! agora você tem uma chave para o GoogleMaps.

Passo 3:
Vamos configurar nossa aplicação. Primeira coisa que devemos fazer é configurar na nossa aplicação o build target como "GoogleAPIs" e criar um AVD para esse target.

Depois, devemos colocar essa linha no arquivo AndroidManifest.xml, dentro da tag <application>


<uses-library
android:name="com.google.android.maps"/>


E essas duas fora da tag <application>, mas dentro da tag <manifest>.


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


Agora só falta nós criarmos a classe que mostrará o mapa na tela:


import android.os.Bundle;
import com.google.android.maps.MapActivity;
import com.google.android.maps.MapView;
public class MapaSimples extends MapActivity {
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
MapView mapView = new MapView(this,
"0CjoPthXnVvE9Uz3TW1d-ng82vlrdeTVBda4VPw");
setContentView(mapView);
}

protected boolean isRouteDisplayed() {
return false;
}
}


Se rodarmos nossa aplicação teremos nossa aplicação exibindo um mapa na tela do aparelho.

Depois pretendo editar esse post ou adicionar novos mostrando como manipular o mapa no Android.

4br4ç05,
nglauber

quinta-feira, 10 de setembro de 2009

domingo, 30 de agosto de 2009

Utilizando Banco de Dados SQLite no Android

Olá povo,

Entre as muitas coisas legais que o Android trouxe, o suporte nativo ao banco de dados SQLite foi uma das mais importantes, comercialmente falando. Com ele podemos utilizar os bons e famosos comandos SQL (SELECT, INSERT, UPDATE, DELETE, etc) no mundo mobile. Quem programou em J2ME sabe o quão complicado é implementar um repositório "digno" que suporte uma boa quantidade de registros nessa plataforma (não me falem de RMS... :)

Nesse POST, vou colocar trechos de código que utilizam esses conceitos e tentarei explicá-los. A parte da interface gráfica, vou explicar apenas o que for relevante para o uso com banco de dados.

Para criarmos um banco de dados SQLite, podemos:
  • utilizar a ferramenta SQLite Expert Personal e colocar o arquivo do banco de dados na pasta /data/data/pacote_da_minha_aplicacao/databases;
  • ou via código, utilizando uma classe "helper" do SQLite.
Utilizaremos a segunda abordagem, pois na vida real não queremos colocar esse arquivo manualmente no aparelho. Pois, caso seja necessária uma atualização, teremos que atualizar N aparelhos.

Mãos à obra! Vamos criar uma classe que herda de android.database.sqlite.SQLiteOpenHelper. Ela será responsável por criar o banco quando a aplicação for instalada (método onCreate) e atualizá-lo para novas versões da aplicação (método onUpgrade).

public class SQLiteHelper extends SQLiteOpenHelper {
  private String scriptCreate;
  private String scriptDelete;

  public SQLiteHelper(Context ctx, String nomeBd, 
      int versaoBanco, String scriptCreate, 
      String scriptDelete) {

      super(ctx, nomeBd, null, versaoBanco);
      this.scriptCreate = scriptCreate;
      this.scriptDelete = scriptDelete;
  }

  public void onCreate(SQLiteDatabase db) {
      db.execSQL(scriptCreate);
  }

  public void onUpgrade(SQLiteDatabase db, 
      int oldVersion, int newVersion) {

      db.execSQL(scriptDelete);
      onCreate(db);
  }
}


Agora vamos criar a classe que realizará as operações de abrir, selecionar, inserir, atualizar e excluir registos no banco de dados:

public class RepositorioCarro {
  private SQLiteDatabase db;
  private SQLiteHelper dbHelper;
  private static final String SCRIPT_DB_DELETE = 
    "DROP TABLE IF EXISTS carros";
  private static final String SCRIPT_DB_CREATE =
    "create table carros (_id integer primary "+
    "key autoincrement, nome text not null, "+
    "placa text not null, ano text not null);";

  public RepositorioCarro (Context ctx){
    dbHelper = new SQLiteHelper(ctx, "curso", 1, 
      SCRIPT_DB_CREATE, SCRIPT_DB_DELETE);
  }

  private long inserir(Carro c){
    ContentValues cv = new ContentValues();
    cv.put("nome", c.getNome())
    cv.put("placa", c.getPlaca());
    cv.put("ano", c.getAno());
    db = dbHelper.getWritableDatabase();
    long id = db.insert("carros", null, cv);
    db.close();
    return id;
  }

  private long atualizar(Carro c){
    ContentValues cv = new ContentValues();
    cv.put("nome", c.getNome());
    cv.put("placa", c.getPlaca());
    cv.put("ano", c.getAno());

    db = dbHelper.getWritableDatabase();
    long rows = db.update("carros", cv, "_id = ?", 
       new String[]{ String.valueOf(c.getId())});
    db.close();
    return rows; // qtde. de linhas afetadas 
  } 

  public int excluir(int id){
    db = dbHelper.getWritableDatabase();
    int rows = db.delete("carros", "_id = ?", 
      new String[]{ String.valueOf(id) });
    return rows; // qtde. de linhas afetadas
  }

  public List<Carro> buscarCarroPorNome(String nome){
    List<Carro> lista = new ArrayList<Carro>();

    String[] columns = new String[]{
       "_id", "nome", "placa", "ano"};
    String[] args = new String[]{nome+"%"};

    db = dbHelper.getWritableDatabase();
    Cursor c = db.query("carros", columns, 
       "nome like ?", args, null, null, "nome");

    c.moveToFirst();
    while(!c.isAfterLast()){
      Carro carro = fillCarro(c);
      lista.add(carro);
      c.moveToNext();
    }
    c.close();
    db.close();
    return lista;
  }

  private Carro fillCarro(Cursor c) {
    Carro carro = new Carro();
    carro.setId((int)c.getLong(0));
    carro.setNome(c.getString(1));
    carro.setPlaca(c.getString(2));
    carro.setAno(c.getString(3));
    return carro;
  }
}


Como vocês podem ver, estou usando uma classe Carro também. Não vou listá-la aqui por se tratar de um POJO com os campos: id, nome, placa e ano do veículo.

Na classe acima, o construtor recebe uma referência do contexto da aplicação. Ela é repassada para nossa classe SQLHelper, que por sua vez, se encarregará de criar o nosso banco de dados se ele não existir. A classe android.database.sqlite.SQLiteOpenHelper (superclasse do nosso helper) tem o método getWritableDatabase() que retorna uma instância da classe android.database.sqlite.SQLiteDatabase, que será nosso canal de comunicação com o banco de dados.

As operações de inserir e atualizar utilizam: uma string que representa o nome da tabela no banco de dados; e um objeto da classe ContentValues, que nada mais é do que um conjunto par/valor com os parâmetros do comando SQL. Mas notem que o método update recebe ainda uma String que representa a cláusula WHERE do comando UPDATE (do SQL), bem como os parâmetros da mesma, que estão mapeados via caracter '?'.
"Por tabela", o método excluir vocês já devem ter entendido :)

O último método é o buscarCarroPorNome(String). Toda consulta SQL, retorna um objeto do tipo Cursor. Ele é bem parecido com o ResultSet do JDBC. Os parâmetros do método query são, respectivamente: String nome da tabela, String[] colunasDaTabela, String clausulaWhere, String[] paramsWhere, String groupBy, String having, String orderBy.

Para exibir os dados, precisaremos criar um Adapter, que converterá um Carro em uma linha de uma lista. Crie o arquivo de layout list_item.xml e coloque-o na pasta res/layout:

<?xml version="1.0" encoding="utf-8"?>

<LinearLayout android:layout_height="wrap_content" 
xmlns:android="http://schemas.android.com/apk/res/android" 
android:layout_width="fill_parent" 
android:id="@+id/carroRow">

<TextView android:layout_width="wrap_content" 
android:layout_height="wrap_content" 
android:id="@+id/txtNome" 
android:layout_weight="1" 
android:textSize="20dp"/>

<TextView android:layout_width="wrap_content" 
android:layout_height="wrap_content" 
android:id="@+id/txtAno" 
android:layout_marginRight="10px"/>

<TextView android:layout_width="wrap_content" 
android:layout_height="wrap_content" 
android:id="@+id/txtPlaca"  
android:layout_marginRight="10px"/>

</LinearLayout>


E agora, vamos criar nosso adapter.

public class CarroListAdapter extends BaseAdapter {
  private Context context;
  private List<Carro> lista;

  public CarroListAdapter(Context ctx, 
    List<Carro> carros) {

    context = ctx;
    lista = carros;
  }

  public int getCount() {
    return lista.size(); 
  }

  public Object getItem(int arg0) {
    return lista.get(arg0);
  }

  public long getItemId(int arg0) {
    return lista.get(arg0).getId();
  }

  public View getView(int pos, View convertView, 
    ViewGroup parent) {

    Carro c = lista.get(pos);
    LayoutInflater inflater = 
      (LayoutInflater)context.getSystemService(
        Context.LAYOUT_INFLATER_SERVICE);

    View view = inflater.inflate(
      R.layout.list_item, null);

    ((TextView)view.findViewById(R.id.txtNome)).
      setText(c.getNome());

    ((TextView)view.findViewById(R.id.txtAno)).
      setText(c.getAno());

    ((TextView)view.findViewById(R.id.txtPlaca)).
      setText(c.getPlaca());

    return view;
  }
}


Crie uma classe que herde de ListActivity e no onCreate, digite o seguinte código:
RepositorioCarro carrosDB = new RepositorCarro(this);
List<Carro>lista = carrosDB.buscarCarroPorNome("");
setAdapter(new CarroListAdapter(this, lista));

Para utilizar os demais métodos é facinho, não é? Basta criar objetos do tipo Carro, no qual os valores serão preenchidos por widgets (componentes de UI) e passá-los como parâmetros para os métodos do RepositorioCarro.

Espero que tenham entendido e gostado :)

Editado em 03/11/2011
Sempre que fizermos uma operação no banco de dados é importante que encerremos a conexão com ele. Tinha faltado isso nesse post, e agora lembrei de corrirgir.

4br4ç05
nglauber

sábado, 8 de agosto de 2009

JUnit no Eclipse


Olá povo,

Voltando a postar aqui no blog, vou mostrar rapidinho como usar o JUnit no Eclipse. Para quem não conhece, o JUnit é uma ferramenta freee de automação de testes unitários para Java. Esses testes unitários, visam validar o código que foi desenvolvido.

Vamos utilizar uma classe Calculadora abaixo:


public class Calculadora {

public int soma(int a, int b){
return a + b;
}

public int multiplica(int x, int y){
return x * y;
}
}


Seria muito simples testarmos essa classe não é? Para testar UMA classe sim, mas quando são CENTENAS?
Sendo assim, a idéia do JUnit é validar se os resultados de operações estão sendo satisfeitas, evitando que modificações acidentais causem um mal funcionamento no sistema.

Para utilizar o JUnit no Eclipse é bem simples. A versão Ganymede já vem com um plugin integrado. Então, vamos fazer o teste pra essa classe? No Eclipse, selecione File | New... | JUnit Test Case. Informe o nome da classe de teste, por convenção, utiliza-se o nome da classe mais a palavra "Test" no final. Então, colocaremos o nome de CalculadoraTest. Selecione a classe que estamos testando, e clique em finish.

Vamos deixar nossa classe como abaixo:


import junit.framework.TestCase;

public class CalculadoraTest2 extends TestCase {

Calculadora calc = new Calculadora();

public void testSoma() {
assertEquals(3, calc.soma(1, 2));
}

public void testMultiplica() {
assertEquals(12, calc.multiplica(4,3));
}
}


Agora vamos rodar nossos testes. Clique com o botão direito no projeto, selecione "Run as... | JUnit Test". Será exibida uma janela com o resultado dos testes. No nosso caso, os dois testes devem passar.

Como podemos notar, na classe de testes, estamos usando a classe junit.framework.TestCase que é do JUnit. A importação do JAR do JUnit é feito pelo próprio Eclipse.

Isso pode parecer muito trivial, mas imagine se acidentalmente, você muda o sinal do método multiplica? Se isso acontecer e o teste for executado novamente, você verificará que o teste do método de multipicação falhará. Alguns projetos reias realizam a execução dos testes junto com o build, para garantir que a versão gerada está funcionando corretamente.

É isso pessoal, vou tentar publicar mais posts como esse. Simples e pequenos :)

Mais informações sobre o JUnit clique aqui e acesse o site do produto.

4br4ç05,
nglauber

quarta-feira, 15 de julho de 2009

Ausência

Olá povo,

Esse post é só pra dar uma satisfação para quem acessa o blog. Estou sem postar desde Maio porque estou no mestrado e ele está sugando toda minha vida :)

No entanto, venho informar que a partir de agosto virão muitas novidades aqui no blog, nas quais, a maioria será sobre Engenharia de Software, Android e padrões de projeto e arquiteturais.

Meio estranho a combinação? Vou tentar provar que não.

Esperem, e em breve teremos novidades por aqui.

4br4ç05,
nglauber

quarta-feira, 6 de maio de 2009

Impressora 3D

Olá povo,

Estava lembrando no trabalho hoje de um conceito que eu já estava até esquecido e que muita gente não conhece. As impressoras 3D. Isso mesmo...
São impressoras que "imprimem" objetos tridimensionais a partir de um arquivo criado em uma ferramenta CAD. Vocês sabiam que já existem impressoras 3D pela "bagatela" de U$15k?

Bem, segue abaixo um vídeo de uma impressora 3D profissional.




4br4ç05,
nglauber