segunda-feira, 21 de janeiro de 2013

CodeChef - A Platform for Aspiring Programmers

Depois de um bom tempo longe do blog, quase um ano, estou voltando, agora com força total. Estou terminando meu mestrando em Ciências da Computação e ficarei com o tempo mais livre para o Blog.

E a primeira postagem que faço no meu retorno é sobre o site Code Cheaf , esse como vários outros, é uma plataforma para programadores aprimorarem seus conhecimentos e habilidade em programação. Esse site é bastante usado para quem está participando de maratonas de programação, com ele é possível escolher problemas de diferentes dificuldades, de diferentes maratonas ao redor do mundo. Basicamente você escolhe um problema, cria um algoritmo, escolhe a linguagem e envia para o sistema do site avaliar. Após a avaliação do sistema, as respostas podem ser: Time Limit Exceeded (Todo o problema tem um tempo limite de execução), Wrong Answer (O sistema testa várias entradas), Runtime Error (Divição por zero é um exemplo de erro em tempo de execução), Compilation Error (Erro no código mesmo) ou Accepted (Parabéns seu programa foi aceito). A Figura abaixo mostra a cara do codechef.



No site, existe um rank dos usuários, quanto mais você resolver problemas maior será sua pontuação e mais alto será sua posição no rank, existe um rank local, do seu país de origem, e um rank global, do mundo inteiro. A Figura abaixo mostra como está o rank dos seis primeiros no dia desta postagem. Como é possível observar na lista, a primeira posição é de um chinês. É, eles também dominam o mundo da programação :)


O Codechef possui um fórum bastante ativo, onde os usuários discutem sobre os problemas abordados no site e sobre programação em geral, você pode se registrar ou se logar utilizando sua conta no Facebook. Este site é muito interessante para quem está aprendendo a programar e para quem está aprimorando seus conhecimentos em programação. 

Existem outros sites com o mesmo objetivo como SPOJ e SPOJ_BR, mas acho a interface do Codechef mais amigável.

Outro site bastante interessante é o IDEONE, nele você pode rodar seus algoritmos em diferentes linguagens, atribuir parâmetros de entrada e observar a saída e o tempo de execução de seus códigos. Muitos interessante para quem quer testar seus códigos antes de submeter para o Codechef.

quarta-feira, 5 de outubro de 2011

Utilizando duas ListViews em uma mesma tela

Na grande maioria das vezes você vai precisar de apenas uma lista na tela, por isso os caras do Android fizeram o ListActivity. No entando, se você colocar mais de uma lista na tela, a sua app pode perder usabilidade, ou seja, seu usuário pode ficar confuso com tantas listas para dar scroll, além do que, em celulares com telas pequenas isso pode ser um problema.

Porém, sempre existe aquele caso isolado que você vai precisar utilizar duas ListViews na mesma tela. Foi pensando nisso que fiz esse post.

Neste projeto vamos criar 3 Classes:
  1. ListObjectViewActivity: Esta classe será a tela principal da nossa aplicação.
  2. Contatos: Esta classe é um POJO (Plain Old Java Object) que é uma classe que tem apenas atribudos privados com setter e getters. Cada contato terá um objeto Contatos que define o nome, o id e o telefone do respectivo contato.
  3. MeuAdapter: Esta será a classe adaptador, que vai preencher a ListView com meus objetos Contatos.
E dois arquivos de Layout:
  1. main.xml : Layout principal que conterá 2 TextViews e 2 ListViews
  2. linha.xml: Layout que será utilizado pelo adaptador para preencher as linhas dos ListViews

Vamos começar pelo mais simples que é a classe Contatos.

Contatos.java
public class Contatos {
 
 private int id;
 private String nome;
 private String telefone;
 
 public Contatos(int id, String nome, String telefone) {
  super();
  this.id = id;
  this.nome = nome;
  this.telefone = telefone;
 }

 public int getId() {
  return id;
 }

 public String getNome() {
  return nome;
 }

 public String getTelefone() {
  return telefone;
 }

}

Esta classe pode ter o que você quiser, endereço, email, qualquer informação que você quiser que apareça na lista.

Agora que criamos nossa classe Contatos, vamos criar um adaptador para esta classe. Um adaptador utiliza o Padrão de Projeto ADAPTER que é muito útil para transformar um objeto em outro. Ou melhor adaptar um objeto para uma determinada situação.

Para criar um adaptador você pode herdar da classe BaseAdapter. Depois disso você vai precisar implementar alguns métodos, são estes:


  1. int getCount(): Retorna o tamanho da lista que você vai adaptar 
  2. Object getItem(int position): Retorna um item da lista na posição "position".
  3. long getItemId: Retorna o id do item, não vamos utilizar este, pode retornar zero;
  4. View getView: É o método mais importante, é aqui que a ListView vai ser preenchida com objetos Contatos.

Veja como fica nosso adaptador.
MeuAdapter.java
public class MeuAdapter extends BaseAdapter {

 Context contexto;
 List lista;

 public MeuAdapter(Context contexto,List lista) {
  super();
  this.contexto = contexto;
  this.lista = lista;
 }

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

 @Override
 public Object getItem(int position) {
  return lista.get(position);
 }

 @Override
 public long getItemId(int arg0) {
  return 0;
 }

 @Override
 public View getView(int position, View convertView, ViewGroup parent) {
  
  Contatos contato = (Contatos)getItem(position);
  /**Utiliza o conceito de Adaptador Eficiente.
   * usando o convertView da forma que é feita é mais eficiente do que
   * usar View v = LayoutInflater.from ... porque dessa forma toda fez que
   * o usuário der scroll novas linhas vão ser criadas. E com o convertView
   * isso não acontece.
  **/
  if(convertView == null){
   
   convertView = LayoutInflater.from(contexto).inflate(R.layout.linha, null);
  }
  
  TextView tvNome = (TextView) convertView.findViewById(R.id.tvNome);
  TextView tvTelefone = (TextView) convertView.findViewById(R.id.tvTelefone);
  
  tvNome.setText(contato.getNome());
  tvTelefone.setText("Tel: "+contato.getTelefone());

  return convertView;
 }

}

A maioria dos adaptadores personalizados tem esta cara ai. o que vai mudar é o método getView. Nele cada linha é preenchida do jeito que o programador quiser. O importante detalhe é que o adaptador precisa de Layout que representada uma linha.

No nosso caso o layout tem apenas dois TextViews, um que irá preencher o nome e o outro o telefone. Mas poderia ter um icone, ter 3 textviews, só depende da necessidade do programador.
O Layout utilizado pelo nosso "Adapter" é:

linha.xml

 
 



Veja que em linha.xml tem apenas dois TextViews, caso você queira colocar uma imagem em cada linha da ListView basta colocar um ImageView no layout, e no método getView do adapter setar a imagem desejada para aquele objeto.

Agora vamos para nossa classe principal.
Primeiramente o main.xml para entendermos como ficará nossa tela:

main.xml

 
 
 
 


O código XML não fica tão legível devido a formatação. Cole esse código no layout/main.xml do seu projeto e dê um ctrl+shift+f para melhorar.

Bom este layout, como falei anteriormente, tem apenas 2 textViews e 2 ListViews.

Agora vamos ver a classe principal.

ListObjectViewActivity.java
public class ListObjectViewActivity extends Activity implements
  OnItemClickListener {

 @Override
 public void onCreate(Bundle savedInstanceState) {
  super.onCreate(savedInstanceState);
  setContentView(R.layout.main);

  // Criando lista de objetos para preenhcer ListView 1
  List contatos1 = new ArrayList();
  contatos1.add(new Contatos(1, "Androiano", "123456"));
  contatos1.add(new Contatos(2, "Renata", "12456"));
  contatos1.add(new Contatos(3, "Rodrigo", "1277856"));
  contatos1.add(new Contatos(4, "Robson", "152876"));
  contatos1.add(new Contatos(5, "Portal Android", "12345"));

  // Criando e setando o adaptador personalizado para Lista 1
  MeuAdapter adapter1 = new MeuAdapter(this, contatos1);
  ListView lista1 = (ListView) findViewById(R.id.listView1);
  lista1.setAdapter(adapter1);

  // Criando lista de objetos para preenhcer ListView 2
  List contatos2 = new ArrayList();
  contatos2.add(new Contatos(1, "Alex", "456775"));
  contatos2.add(new Contatos(2, "Fulano", "765656"));
  contatos2.add(new Contatos(3, "Pelé", "65556"));
  contatos2.add(new Contatos(4, "Android", "456876"));
  contatos2.add(new Contatos(5, "Linux", "3446"));

  // Criando e setando o adaptador personalizado para Lista 2
  MeuAdapter adapter2 = new MeuAdapter(this, contatos2);
  ListView lista2 = (ListView) findViewById(R.id.listView2);
  lista2.setAdapter(adapter2);

  // Adicionando Listeners aos ListViews
  lista1.setOnItemClickListener(this);
  lista2.setOnItemClickListener(this);

 }

 @Override
 public void onItemClick(AdapterView parent, View v, int position, long id) {
  Contatos contato = (Contatos) parent.getAdapter().getItem(position);

  Toast.makeText(this,
    "Nome: " + contato.getNome() + "\nTel:" + contato.getTelefone(),
    Toast.LENGTH_SHORT).show();

 }
}

Vamos analisar um pouco esse código.
O trecho abaixo é o que faz a mágica. A ListView precisa ser preenchida, mas se você passar um objeto Contatos ela não saberá como preencher as linhas com um objeto que ela desconhece. Ai entre o papel do adapter. O ListView não conhece Contatos, mas ele conhece BaseAdapter. Então basta você "transformar" seu objeto Contatos para BaseAdapter.


MeuAdapter adapter1 = new MeuAdapter(this, contatos1);
  ListView lista1 = (ListView) findViewById(R.id.listView1);
  lista1.setAdapter(adapter1);

É desta mesma forma que trabalho o ArrayAdapter do Android, que faz a adaptação de Strings para a ListView.

Para capturar eventos de click das listas eu implementei a interface OnItemClickListener que possui o método onItemClick. Neste método você implementa o comportamento do evento, no meu caso é pegar o objeto (Contatos) referente ao click e mostrar na tela o nome e o telefone do contato clicado.

Vamos ver o resultado final do projeto.


[ ]'s Androiano

sexta-feira, 30 de setembro de 2011

Criando uma Notificação a partir do BroadcastReceiver

Olá a todas,
Não é recomendado abrir uma tela quando o BroadcastReceiver recebe uma notificação. Isso porque o usuário pode estar lendo um e-mail importante, vendo um site ou estar na ultima fase de um jogo lutando contra o chefão. Abrir uma tela no meio destas atividades poderia deixar o usuário extremamente irritado. Com isso, as aplicações precisam interagem com o usuário por meio de notificações.

Um dia um amigo meu perguntou: como criar uma notificação a partir de um evento capturado pelo broadcast receiver?
A resposta é simples, é só criar a notificação dentro do método "onReceive" de BroadcastReceiver. Vou mostrar um exemplo.

A Figura abaixo mostra a arquitetura do exemplo e como as mensagens são trocadas.


A classe SendBroadNotifyActivity é uma classe de teste, ela gera um evento que será capturado pela classe BroadcastCallingNotification. Ao capturar este evento o BroadcastCallingNotification cria uma notificação que será apresentado na parte superior do dispositivo do usuário. Cade a ele a decisão de abrir ou não esta notificação.
Caso ele resolva abrir, a activity/tela NotificacaoActivity é exibida na tela.

Neste exemplo as classes NotificacaoActivity e BroadcastCallingNotification estão no mesmo pacote. Abaixo, é exibido o manifest deste pacote. Perceba que existe uma permissão para que a aplicação possa vibrar o celular.


 
 
  
   
    
    
   
  
  
 
 
 



Para criar um evento a ser capturado pela classe BroadcastCallingNotification basta dar um sendBroadcast com a ação BROADCAST_NOTIFY, que foi configurada no manifest. O nome da ação foi eu que escolhi, poderia ser qualquer nome. Abaixo o comando completo.

sendBroadcast(new Intent("BROADCAST_NOTIFY"));

O código da classe BroadcastCallingNotification:
public class BroadcastCallingNotification extends BroadcastReceiver {

  @Override
  public void onReceive(Context contexto, Intent intent) {
   
   String textAviso = "Você recebeu uma mensagem";
   CharSequence titulo = "Androiano";
   CharSequence mensagem = "Exemplo de notificação";
  
   //Configurando o gerenciador de notificação.
   NotificationManager nm = (NotificationManager) contexto.getSystemService(Context.NOTIFICATION_SERVICE);
   Notification n = new Notification(android.R.drawable.stat_notify_chat, textAviso,System.currentTimeMillis());
   
   //Se o usuário selecionar a notificação chama uma activity
   PendingIntent p = PendingIntent.getActivity(contexto, 0, new Intent(contexto,NotificacaoActivity.class), 0);
   
   //Vinculando o PedingIntent com a notificação
   n.setLatestEventInfo(contexto, titulo, mensagem, p);
   
   /** Espera 100, vibra 250, espera 100, vibra 500
    *   Não esquecer de colocar, no manifest, a tagt:
    *   uses-permission android:name="android.permission.VIBRATE" 
    **/
   n.vibrate = new long[]{100,250,100,500};
   
   nm.notify(R.string.app_name,n);
  } }

A classe NotificacaoActivity é a tela que é criada quando o usuário clica na notificação.

public class NotificacaoActivity extends Activity {
 
 @Override
 protected void onCreate(Bundle savedInstanceState) {
  // TODO Auto-generated method stub
  super.onCreate(savedInstanceState);
  
  //Fechando a notificação
  NotificationManager nm = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
  nm.cancel(R.string.app_name);
  
  TextView tv = new TextView(this);
  tv.setText("Parabéns você está vendo uma tela que foi gerada por uma notificação");
  setContentView(tv);
  
 }

}

As duas classes acima são as que fazem o trabalho sujo de pegar um evento, criar uma notificação e iniciar uma tela, caso seja o desejo do usuário. Agora vamos ver como fica a classe de teste, ou seja, a classe que cria um evento de broadcast.

Para fazer a classe SendBroadNotifyActivity criei um novo projeto e fiz um layout simples com um botão e um texto. Como você já deve ter imaginado o clique do botão gera o evento de broadcast.

Como é só um botão e um textview, não precisava colocar o layout aqui, porém existe um modo de chamar um botão que nem todos os programadores Android conhecem, é o onClick dentro do XML.


 
 



Verifique a linha android:onClick="buttonClick". Para criar um método que capture o botão é só criar o método:
public void buttonClick(View v){}

Lembrando que buttonClick é o nome que eu dei, você pode dar qualquer nome, mas sempre tem que ter a mesma assinatura no java e no xml, o retorno é void e a proteção é public, com um parâmetro View, senão não funciona.

Por fim a tela de teste:
public class SendBroadNotifyActivity extends Activity {
 @Override
 public void onCreate(Bundle savedInstanceState) {
  super.onCreate(savedInstanceState);
  setContentView(R.layout.main);
 }

 //Define buttonClick em android:onClick do botão no XML
 public void buttonClick(View v) {
  sendBroadcast(new Intent("BROADCAST_NOTIFY"));
 }
}

Abaixo estão alguns screenshots do projeto.


[]'s
Androiano

domingo, 25 de setembro de 2011

O primeiro post a gente nunca esquece. :)

Olá pessoal,


Meu nome é Adriano (por isso o trocadilho Androiano), sou engenheiro de computação e amante da tecnologia, estou ingressando nesse fantástico mundo chamado Android, por isso resolvi criar um blog para compartilhar minha experiência com o mundo. Porém, apesar do nome do blog ter referência ao famoso sistema operacional, vou aproveitar para escrever sobre todo tipo de assunto, mas claro, sempre relacionado ao mundo da tecnologia.

 []’s Androiano