03/04/14

As novidades da semana: Google Play Services 4.3, Sliding Tabs e Google Cloud Platform

Olá desenvolvedores brasileiros !

Desde a semana passada até hoje, tivemos algumas novidades publicadas em nossos principais canais do YouTube, Android Developers e Google Developers, e vamos repassar por aqui, caso você tenha perdido.

Google Play Services 4.3




Um vídeo bem diferente e enérgico com uma revisão das principais novidades da biblioteca para aplicativos Android, que incluem as duas novas APIs, a Address e Analytics. Além de atualizações na API Play Games e Google Drive.

Sliding Tabs




Sempre ficou pensando em colocar as abas deslizantes, como as do Google Play em seu aplicativo?
Veja esse vídeo com a +Lisa Wray, acesse os exemplos Slidind Tabs Basic e Sliding Tabs Colors e depois, é só deixar o seu app ainda mais fácil de usar.

Novidades na plataforma Cloud


Na semana passada, mais exatamente no dia 25 de março, um evento transmitido ao vivo trouxe diversas novidades na plataforma Cloud do Google, além de grandes reduções de preço. Deixando assim, ainda mais acessível para todos os desenvolvedores.

Não conseguiu acompanhar o evento?
Sem problemas! Todas as apresentações, inclusive o keynote. Veja abaixo a lista das apresentações disponíveis, são mais de 10!

Ficou querendo mais vídeos?
Então não deixe de se inscrever nos canais Android Developers e Google Developers.

Semana que vem, voltamos com mais um resumo das novidades.

Developer Advocate

28/03/14

Comunicação Web em apps Android - Parte III

Olá desenvolvedores Android,

Chegamos a terceira parte da série de posts sobre comunicação web em apps Android (veja a primeira e segunda partes), onde a idéia é falar sobre um framework que foi apresentado no Google I/O de 2013: Volley.

Nos posts anteriores, a idéia foi mostrar os conceitos e bases da comunicação web em apps Android, para que você compreenda como é feita essa comunicação e pudesse assim, usar da maneira mais adequada para o seu app. Mas como deve ter percebido, talvez até na prática, esses trechos de código para comunicação acabam se repetindo em diversos projeto ou até vários pontos do seu app. O que nos leva a pensar que isso deveria estar em uma biblioteca, não é verdade?

Quando usar Volley ?


É no sentido de poupar tempo e facilitar as operações básicas que foi criada a Volley, que ajuda a realizar requisições, tratar respostas, trabalhar com filas de requisições, prioridades e também oferece cache, assim você pode rapidamente ter dados disponíveis em seu app.
Mas, não é uma biblioteca que se aplica em todas as situações. As respostas são entregues inteiras diretamente na memória, o que torna a Volley uma opção não indicada para grandes quantidades de dados como vídeos e música. Ou seja, é a escolha ideal para requisições menores, como consumo de APIs JSON, XML e arquivos menores como imagens.

Integrando a Volley ao seu projeto Android


Todo o código do framework está disponível juntamente com todo o código do Android Open Source Project. Dessa forma, há diversas maneiras de importar o código e integrá-lo com o seu projeto Android, vamos ver algumas dessas opções:

  • Copiar o código para o seu projeto Android
  • Gerar um JAR do código e importar como biblioteca
  • Se utilizar Git para o controle de versão do seu projeto, pode adicionar o framework Volley como um sub-módulo do seu projeto.
Para todos os casos citados acima, é necessário antes fazer o clone do repositório do projeto e então executar os passos que desejar. Para esse post, vamos considerar que já tem a biblioteca pronta para uso. Caso tenha algum problema, veja essa pergunta no Stackoverflow.

Comunicação com Requests


Na Volley, toda a comunicação web e até o tratamento de cache é através de requisições. E o principal mecanismo para isso, é uma fila de requisições, a RequestQueue. Essa fila é utilizada em todos os pontos da aplicação, como uma forma de centralizar todo o fluxo de comunicação. Inclusive permitindo priorizar requisições dentro dessa fila.

Como a RequestQueue vai ser utilizada em toda a aplicação, uma maneira de ter apenas uma instância da fila e dar fácil acesso a todas os outros componentes do seu app, é criar uma classe que estende de Application e registrá-la no Manifest, veja o exemplo:

VolleySampleApplication
public class VolleySampleApplication extends Application {

    private RequestQueue queue;

    @Override
    public void onCreate() {
        this.queue = Volley.newRequestQueue(this);
    }

    public RequestQueue getRequestQueue() {
        return queue;
    }
}

AndroidManifest
    <application
        android:name=".VolleySampleApplication"
        android:allowBackup="true"
        ...
    </application>

Criando e enviando uma requisição por POST


Para seguir o exemplo que foi utilizado no post anterior, vamos fazer uma requisição e enviar por POST para consumir o mesmo webservice do exemplo anterior, que irá contar quantas palavras há na frase enviada por parâmetro e devolver um JSON com a quantidade de palavras e a frase original.

No trecho abaixo, está a criação da requisição e a inclusão dos parâmetros, que é feita sobrescrevendo o método getParams(). Depois,  a requisição é adicionada à fila e será executada pela Volley. Veja o trecho completo:
  StringRequest strReq = new StringRequest(Request.Method.POST, url, 
          this, this) {
      @Override
      protected Map getParams(){
          Map params = new HashMap();
          params.put("text", textEditText.getText().toString());

          return params;
      }
  }
  VolleySampleApplication app = (VolleySampleApplication) 
      getApplication();
  app.getRequestQueue().add(strReq);

Como o servidor responde um JSON, a primeira idéia pode ser em utilizar uma JsonObjectRequest, mas esse tipo de requisição não executa o método getParams(), já que utiliza o corpo da requisição para enviar o JSON esperado pela requisição. Assim, caso você tente adicionar parâmetros a requisição, verá que eles nunca irão chegar ao servidor. Por isso, foi escolhido uma StringRequest e o seu retorno será convertido para um objeto JSON.

Na criação da request, o terceiro e quarto parâmetros representam os listeners para sucesso e falha da requisição,  nesse caso a própria Activity será o listener para ambos os casos. Abaixo está o código para tratamento da String recebida, sua conversão para JSON e então, a atualização da interface com o número de palavras na frase:
  @Override
  public void onResponse(String s) {
      if (s != null) {
          try {
              JSONObject jsonObject = new JSONObject(s);
              if (jsonObject != null) {
                  int words = jsonObject.getInt("words");
                  updateWordsCount(words);
              }
          } catch (JSONException e) {
              e.printStackTrace();
          }
      }
  }

  @Override
  public void onErrorResponse(VolleyError volleyError) {
      volleyError.printStackTrace();
  }

Você deve levar em consideração que esse é um código de exemplo, então para que não tenha que sobrescrever o método getParams() todas as vezes, deixando seu código muito extenso e com uma legibilidade ruim, seria uma boa idéia considerar o encapsulamento desse processo em alguma classe auxiliar, e também retirar o código de tratamento do JSON da Activity.

Cache


Uma funcionalidade muito poderosa na Volley é o cache. Para não deixar o post muito grande, não vamos entrar em detalhes, mas o principal ponto é que é possível armazenar o cache de acordo com a requisições. Assim, é possível ter resultados rápidos para casos onde se realizam repetidas requisições ou até, para uma eventual falta de conectividade.
Cada requisição pode ser armazenada ou removida individualmente, e até todo o cache pode ser invalidado de uma só vez, conforme a necessidade. Também é possível tratar a data em que a inclusão no cache foi feita, e baseado na existência ou tempo de vida do cache, tomar a decisão se deve ser feita a requisição ou não.

Prioridade


Quando se trabalha com muitas requisições dentro de um aplicativo, em algum momento pode se desejar que alguma requisição seja tratada com alguma prioridade. Apesar de não ter um método como setPriority(), é possível fazer algo parecido como foi feito para a getParams() e sobrescrever o método getPriority() e setPriority().

Mais detalhes


Para saber mais sobre a Volley, assista o vídeo Volley: Easy, Fast Networking for Android do Google I/O de 2013, de quando a biblioteca foi apresentada.
E para o exemplo completo dos códigos utilizados aqui, veja o projeto VolleySample disponível no GitHub.

Fique a vontade para deixar seu comentário, compartilhar esse post e também, estamos disponíveis através da página +Desenvolvedores Google, onde você pode conversar com outros desenvolvedores Android e trocar experiências sobre comunicação Web em aplicativos Android.

+Neto Marin
Developer Advocate

24/03/14

+Desenvolvedores Google - A +page do Google para o desenvolvedor brasileiro

Olá pessoal,

Com o objetivo de se aproximar ainda mais dos desenvolvedores brasileiros, está indo ao ar essa semana a nova +Page oficial do Google para desenvolvedores brasileiros, a +Desenvolvedores Google.



Através dessa +Page iremos trazer as novidades para o mercado brasileiro, casos de sucesso, divulgar eventos e qualquer outro assunto que seja do interesse dos desenvolvedores brasileiros. Será também um canal de interação entre a comunidade técnica e a equipe de Developer Relations do Google no Brasil, pois faremos o melhor possível pra responder a todos comentários e interações.
Não perca a chance de saber o que está acontecendo e interagir com outros desenvolvedores que gostam e utilizam as tecnologias Google.

E além da +Desenvolvedores Google, também temos a comunidade Desenvolvimento Android - Brasil, onde o debate é ainda mais aberto, com todos podendo postar sobre a tecnologia Android. Seja para tirar suas dúvidas, divulgar seu app e até conseguir aquela ajuda no seu projeto.
Mas, se o seu negócio é algum produto ou tecnologia do Google, você tem a comunidade Código Google, onde também pode postar a sua dúvida, mensagem, recado e etc.

O que não falta é ferramenta para se comunicar com outros desenvolvedores e com a equipe de Developer Relations do Google!


Comece agora mesmo a seguir +Desenvolvedores Google, compartilhe e faça seus comentários ! 
Esperamos você lá!



27/02/14

Comunicação Web em apps Android - Parte II

Olá pessoal,

Dando continuidade a série sobre comunicação web em apps Android (veja a parte I), vamos abordar nesse post outras maneiras de se realizar requests HTTP e também algumas práticas em relação a utilização de serviços e comunicação entre serviços e activities.

Usando HttpURLConnection


No post anterior, o exemplo utilizado foi baseado na biblioteca Apache HttpClient, por considerar como uma biblioteca mais extensiva e também mais didática, quando apresentando os conceitos de GET e POST, pois possui objetos e classes separadas para ambas as ações.
Mas como podem ler no post Android’s HTTP Clients, se estiver escrevendo um app a partir da versão Froyo (2.2) é recomendado que utilize a classe HttpURLConnection.

Para maiores detalhes de como utilizar a o HttpURLConnection e suas configurações possíveis, há uma vasta documentação em nosso site oficial para desenvolvedores. Seguem alguns links:


Para uma referência rápida, segue abaixo um exemplo de como seria executado um simples GET, no mesmo endereço utilizado no código de demonstração do post anterior.

  URL url = null;
  HttpURLConnection con = null;
  InputStream is = null;
  try {
      url = new URL("http://codigogdemos.appspot.com/simpleGetPost");
      con = (HttpURLConnection) url.openConnection();
      con.setRequestMethod("GET");
      con.connect();

      if (con.getResponseCode() == HttpURLConnection.HTTP_OK) {
          is = con.getInputStream();
          return getStringFromInputStream(is);
      } else {
          return null;
      }

  } catch (MalformedURLException e) {
      e.printStackTrace();
  } catch (IOException e) {
      e.printStackTrace();
  }

Esse foi um exemplo bem básico de como utilizar a HttpURLConnection, mas consultando a documentação é possível encontrar facilmente os métodos para configurar o método a ser executado ou como obter o OutputStream para envio de informações e até um arquivo todo. Além de ser possível encontrar vários exemplos e posts em blogs e também no Stackoverflow.

Comunicação Web e Services


Como falamos no post anterior, a regra de ouro é sempre executar as operações de rede fora da thread principal. O que nos levou ao exemplo de utilização da AsyncTask, e é o que normalmente leva a maioria dos desenvolvedores a fazerem a utilização do AsyncTask, diretamente de suas activities ou fragments.

E a pergunta que vem é, isso está certo?
Errado não está, mas não podemos considerar como uma das melhores práticas quando estamos falando de comunicação Web em apps Android. Isso porque o ideal é que nessas classes (Activity e Fragment), fique apenas código relativo a interface com o usuário. Deve-se evitar ao máximo colocar código de lógica de negócio, persistência ou comunicação.

Uma das principais razões é organização e reúso de código. Mesmo que o código que faça a chamada de rede em si, esteja em uma classe separada, fazer todo o setup antes e depois fazer o tratamento das informações (parse, validação e etc) no código da Activity continua não sendo uma boa idéia. Até porque, você provavelmente vai ter as mesmas chamadas de diferentes pontos do seu aplicativo.

Uma prática muito utilizada, é realizar a parte de comunicação Web com Services. Assim, quando se deseja consumir/enviar algum dado, um serviço é inicializado e após a tarefa concluída ele notifica quem tiver feito a chamada, ou realiza um broadcast para avisar a todos os possíveis interessados.
Há varias maneiras de se fazer a comunicação entre o Service e quem fez a chamada, mas para o exemplo desse post, vamos utilizar um ResultReceiver. Também é possível deixar o parse e validação dos dados por conta de um Service (ou até o mesmo), que após realizar a persistência irá notificar a conclusão da tarefa.

E para o tratamento de requisições, pode-se utilizar um tipo específico de serviço, que é o IntentService. Assim é possível verificar se aquela request já está sendo executada ou também gerenciar um pool de requests. Isso é possível pois o IntentService trata suas chamadas de forma síncrona e em uma única instância.
Assim, por exemplo, após determinar se é realmente necessário iniciar uma nova request para a busca dos dados, isso pode ser feito utilizando uma nova Thread, liberando o IntentService para atender a próxima request.

Criando e executando um IntentService


Um IntentService é criado de forma muito parecida a de um serviço "convencional". A diferença é que na hora de definir no manifesto, não é necessário definir filtros para a Intent. Como ele vai ser chamado diretamente pela sua classe, não vai é necessário haver filtro.
Veja a declaração do HttpIntentService que foi criado para o exemplo desse post:
  <service android:name=".HttpIntentService">
No exemplo, vamos passar uma frase para o serviço, que o enviará para um web service.  Então, no código da Activity (ou Fragment) não vamos ter nenhum código referente a lógica da conexão com rede ou tratamento da resposta. Veja o código para a chamada do serviço, quando o usuário aperta o botão para contar as palavras:
  Intent serviceIntent = new Intent(this, HttpIntentService.class);
  serviceIntent.putExtra(HttpIntentService.RESULT_RECEIVER_EXTRA,
          resultReceiver);
  serviceIntent.putExtra(HttpIntentService.STR_EXTRA_TEXT,
          textEditText.getText().toString());
  startService(serviceIntent);
Depois disso então, o HttpIntentService é chamado, e outra diferença é que ao invés de se sobrescrever os métodos onStartCommand() ou onBind(), o método com o qual você deve se preocupar é o onHandleIntent().

Nesse exemplo, no onHandleIntent() vamos obter um texto que vai ser passado através da Intent e que deve ser enviado a um webservice para que o número de palavras nesse texto seja contado.
E para que o resultado seja retornado para a Activity que fez a chamada, vamos utilizar um ResultReceiver. Ele é criado na Activity e passado na Intent para o serviço, que após ter a resposta envia de volta através da mesma instância.

E para que esse resultado seja recebido e atualizado corretamente na Activity, o ResultReceiver que foi passado como parâmetro deve ser corretamente implementado:


Para quem quiser ter acesso ao código completo, o aplicativo exemplo desse post já está disponível no Github, como o projeto HttpIntentService.

Para saber mais


Alguns guias e tutoriais que podem ajudar a entender melhor os serviços e outros tópicos:


E no próximo post


E no próximo post vamos falar da biblioteca Volley, que facilita em muitos aspectos alguns dos passos apresentados nesse post. Essa biblioteca é mantida pelo Google e que ajuda na hora de realizar comunicação Web, possibilitando até a criação de uma fila de request e também abstrai vários aspectos da comunicação no seu aplicativo.

+Neto Marin
Android Developer Advocate

11/02/14

Comunicação Web em apps Android - Parte I

Olá desenvolvedor Android !

Quando um novo projeto Android se inicia, de nada poucas coisas temos certeza, mas posso com segurança afirmar que há uma chance de uns 90% (ou mais), de que seja necessária alguma interação com um serviço web.
E nesse momento, muitos desenvolvedores acabam ficando em dúvida, seja porque estão começando agora na plataforma ou porque querem fazer isso da maneira mais eficiente. E essa segunda razão é muito importante, pois um consumo de dados da forma errada, pode tornar o seu app em um sugador de bateria e que pode ser o motivo de um usuário remover o seu aplicativo.

A regra de ouro


Primeira coisa que se deve ter em mente, é que qualquer operação de rede deve ser executada fora da UI thread (ou main thread). Pois como a operação de rede é bloqueante, poderia causar um travamento do app e acabar gerando um ANR (Application Not Responding), e mesmo que não haja nenhum bug, o app poderá ser encerrado.
Ps.: Para evitar surpresas quando publicar o seu app, durante o desenvolvimento você pode trabalhar com o StrictMode, que está presente desde a versão 2.3.

Uma maneira de se fazer isso de forma bem simples, é utilizando a AsyncTask (assista ao vídeo Next Level Tips: Usando AsyncTask) que facilita o mecanismo de criação de tarefas em background, bem como a comunicação com a UI thread antes e depois da tarefa em segundo plano.
Você também pode utilizar um Service para fazer a comunicação Web, mas lembre-se que simplesmente executar uma tarefa em um serviço não significa necessariamente que a tarefa está sendo executada em uma nova thread.
E claro, é possível utilizar o conceito de worker thread com a criação direta de uma thread para executar a tarefa. O único ponto que se deve ter em mente nessa técnica é que uma thread não pode manipular diretamente objetos que causem uma modicação na Activity ou algo que esteja sendo exibido na tela.

Para mais detalhes sobre o uso de AsyncTasks e threads é recomendado a leitura do guia sobre Processos e Threads. Em outro post dessa série iremos abordar o uso de Services para a comunicação Web.

Começando pelo básico


Essa série de posts vai abordar as diversas maneiras de se fazer a comunicação Web a partir de apps Android. Mas antes de explorar técnicas mais avançadas, vamos partir do entendimento básico das operações HTTP e como isso pode ser feito de forma bem simples utilizando a biblioteca HttpClient, que já acompanha o core do Android.
Como exemplo, vamos ver como executar uma operação de GET e outra de POST. Mas, com base no código, é possível entender com a biblioteca funciona e facilmente realizar outros tipos de requisições como PUT e DELETE, além de ser fácil encontrar exemplos de envio de arquivos, formulários e etc.

GET


Uma requisição GET, normalmente é executada com alguns parâmetros na própria URL ou sem parâmetro algum. No caso de não haver necessidade de parâmetros, uma request GET poder ser criada diretamente com a URL do serviço:
HttpGet get = new HttpGet("http://www.seuservidor.com/metodoApi");
Se tiver algum parâmetro ou se simplesmente quiser tornar a chamada mais genérica, a montagem da URL pode ser feita com o método URIUtils.createURI. Vamos começar como seria a montagem dos parâmetros, utilizando um List:
List params = new ArrayList();
params.add(new BasicNameValuePair("param1", varParam1);
params.add(new BasicNameValuePair("param2", varParam2);
Depois é só usar a variável params na criação da URI e em seguida criar o HttpGet:
URI url = URIUtils.createURI("http", "www.seuservidor.com", 80,
        "/metodoApi", URLEncodedUtils.format(params, "UTF-8"), null);  
HttpGet get = new HttpGet(url);
E o próximo passo é criar um HttpClient e executar o método que se deseja, no caso um GET.
DefaultHttpClient hc = new DefaultHttpClient(); 
HttpResponse response = hc.execute(get);
E caso a resposta que está esperando seja algo com uma String, ou que precisa fazer o parse, basta transformar a resposta em String e dar o tratamento que seja necessário:
String responseString = EntityUtils.toString(response.getEntity());

POST


Simplificando um pouco, o POST tem como principal característica enviar os dados encapsulados em uma entidade, ao invés de utilizar a URL como é feito no método GET. Por isso o código é bem similar:
HttpPost post = new HttpPost("http://www.serservidor.com/metodoPOST");
Ou, pode usar a mesma lógica do exemplo dados anteriormente para construir a URL. Mas, como no POST não são enviados parâmetros na URL, o comando fica ainda mais simples:
URI url = URIUtils.createURI("http", "www.seuservidor.com", 80,
        "/metodoPOST", null, null);  
HttpPost post = new HttpPost(url);
Agora vamos criar a lista com os parâmetros, mas dessa vez adicioná-los a entidade do POST que fará o transporte:
List params = new ArrayList();
params.add(new BasicNameValuePair("param1", varParam1);
params.add(new BasicNameValuePair("param2", varParam2);
post.setEntity(new UrlEncodedFormEntity(params));
E então, seguindo a mesma lógica, vamos criar o HttpClient e executar o método:
DefaultHttpClient hc = new DefaultHttpClient(); 
HttpResponse response = hc.execute(post);
E por último, transforme a resposta em uma String, caso queira fazer algum processamento:
String responseString = EntityUtils.toString(response.getEntity());

Juntando as peças


Então, se você vai fazer um app que irá executar diversas operações HTTP, um caminho é criar métodos que encapsulem esse comportamento para que sejam facilmente invocados a partir de uma AsyncTask ou IntentService.
E nesse ponto, cada desenvolvedor acaba usando a prática que está mais acostumado, como por exemplo colocar como métodos estáticos em uma classe com construtor privado, implementar um pattern builder ou da forma que preferir.
Como um exemplo de integração, está disponível no GitHub o projeto SimpleGetPostClient que demonstra as chamadas de métodos GET e POST para serviços Web. Para uma consulta rápida, abaixo estará a classe que contém os métodos e também a Activity de onde é feita a chamada.

To Be Continued...


Agora que você já sabe o básico do funcionamento da comunicação Web em aplicativos Android, nos próximos posts vamos discutir as técnicas utilizadas na hora de fazer a comunicação Web, alguns desafios muito comuns em apps que fazem muitas requisições, boas práticas e até sobre frameworks para facilitar a sua vida. Fique ligado!

Abraços e até a próxima

+Neto Marin
Android Developer Advocate


Códigos de exemplo:


04/02/14

Curso "Discover DevTools" atualizado e com legendas em Português

Ano passado nós lançamos, em parceria com a Code School, um curso interativo que ensina como você pode aproveitar os recursos disponíveis no Chrome DevTools para acelerar o desenvolvimento de suas aplicações web.

Agora nós atualizamos o curso com novos vídeos que refletem a interface e as funcionalidades mais recentes do Chrome DevTools e uma novidade especial para desenvolvedores brasileiros: legendas em Português!


O curso Discover DevTools continua gratuito e inclui lições sobre DOM e estilos, como trabalhar com o console JavaScript, como depurar e como identificar problemas de performance. Ao adicionar legendas em Espanhol e Português para o curso, esperamos ver mais desenvolvedores talentosos aprofundando seus conhecimentos no Chrome DevTools e como ele pode acelerar seu workflow de desenvolvimento.

Dê uma olhada no curso Discover DevTools e veja como ele pode te ajudar a ser um desenvolvedor mais produtivo.


Artigo original escrito por Peter Lubbers, Program Manager e MOOC Manufacturer do Chrome. Traduzido para Português por Zeno Rocha, Google Developers Expert.

12/12/13

O primeiro Google Developers Expert do Brasil




No mês passado mais de sessenta desenvolvedores de todo o mundo se reuniram na sede do Google em Mountain View, Califórnia, para dois dias de sessões técnicas aprofundadas com os principais engenheiros do Google. Neste ano, porém, tivemos pela primeira vez um brasileiro entre eles: Zeno Rocha acabou de se juntar aos Google Developers Experts a tempo de participar do encontro anual e teve a oportunidade de compartilhar conhecimento e idéias com vários engenheiros, product managers e developer relations do Chrome.

Mas afinal, o que são Google Developers Experts?

São pessoas da comunidade de desenvolvedores com ampla e reconhecida capacidade técnica em uma tecnologia específica e que, assim como nós, Googlers, demonstram paixão por esta tecnologia e se preocupam em compartilhar seu conhecimento e sua paixão com a comunidade. Com o programa de GDEs, o Google tenta potencializar o papel que estas pessoas têm na comunidade, oferecendo ferramentas e recursos e estimulando a troca de conhecimento.

Na prática, GDEs são pessoas que se tornam referência na comunidade: escrevem código open-source, compartilham conhecimento através de blogs, escrevem para revistas e sites especializados e palestram em eventos relevantes. Os GDEs são divididos por áreas, como por exemplo Android, Chrome/HTML5, Google+ e Dart.

Zeno, nosso primeiro GDE brasileiro, escreve sobre HTML5 para diversos blogs, participa do podcast Zone of Front-enders, palestra em dezenas de eventos globais e é co-fundador da BrazilJS Foundation. Sua conta no GitHub registra dezenas de projetos e contribuições open-source.

Apoiamos os GDEs com a certeza que essa dedicação e paixão continue inspirando outros desenvolvedores. É com esse espírito que damos boas-vindas ao Zeno como representante da comunidade Chrome/HTML5 no programa Google Developers Experts!


+Renato Mangini, engenheiro de Chrome Developer Relations.