quarta-feira, 29 de abril de 2015

Como consumir webservice SOAP no Android

Embora não haja suporte nativo para o consumo de webServices SOAP no Android (e também não seja uma prática recomendada pela Google), é possível fazê-lo.

Há uma infinidade de serviços online que utilizam o protocolo SOAP . Também, um grande número de empresas investiram tempo (e dinheiro) construindo conjuntos de serviços baseados nele.

Sendo assim, surgiu a necessidade de consumir SOAP em aplicativos Android. E, para nossa sorte, alguém um dia acordou inspirado e resolveu desenvolver uma biblioteca gratuita que permite fazer exatamente isso. Chama-se:  KSOAP2 Library.

Este tutorial ensina a consumir um webService SOAP em um aplicativo Android.

Para começar, vamos escolher o serviço online que será consumido como exemplo. Utilizaremos um webService simples, de conversão de temperaturas, disponível  no endereço abaixo:




O primeiro passo é descobrir quais os métodos disponíveis nesse webService, isto é, quais as operações que podemos executar a partir do consumo.

A pior maneira de fazer isto é abrindo o endereço acima no navegador e tentando descobrir através da leitura do WSDL. Uma maneira mais fácil é usar o software SoapUI, que já está disponível na pasta "@Android\Ferramentas" do nosso ambiente de desenvolvimento.


Vamos abrir o SoapUI e selecionar o menu "File", opção "New SOAP Project", para criar um novo projeto, conforme a figura:







Surgirá uma caixa de diálogo pedindo o nome do projeto e a localização do arquivo WSDL, que é o descritor do webservice. É exatamente o que vamos precisar colar neste campo:
http://www.w3schools.com/webservices/tempconvert.asmx?wsdl.
O nome do projeto aparecerá automaticamente. Depois, basta pressionar o botão "OK".







O SoapUI interpretará o WSDL para nós, identificando os métodos disponíveis existentes no serviço. Na parte superior esquerda da janela principal, ele desenhará uma árvore representando os serviços e seus métodos que poderemos utilizar:






O que nos interessa para efeito deste tutorial é o método "CelsiusToFarenheit", que converte uma temperatura em graus Celsius em seu valor correspondente em Farenheit. Agora, portanto, vamos clicar duas vezes na opção "Request 1". Abrirá uma janela onde poderemos efetuar um consumo real do serviço. Para isso, precisaremos preencher os argumentos que o método exige como obrigatórios. Neste caso é bastante intuitivo: O método pede que especifiquemos o valor da temperatura em graus Celsius. Vamos digitar "32". Depois, precisaremos clicar no botão de "play", no canto superior esquerdo da janela, para que o SoapUI realize a requisição. O resultado do consumo será mostrado à direita, na janela, que apresentará a temperatura convertida em Farenheit, conforme imagem:








Ok! Cumprimos a primeira tarefa. Selecionamos um serviço online e, com a ajuda do SoapUI, conseguimos determinar o método que nos interessa (CelsiusToFarenheit) e seu argumento (Celsius). Precisaremos ainda do "namespace" do serviço, pois será necessário informá-lo ao KSOAP2. Para obter o namespace, basta, no SoapUI, clicar duas vezes sobre o nome do serviço, então uma janela com o namespace será mostrada, conforme a imagem:









Pronto! Já temos agora todo o necessário para iniciar um projeto de consumo do serviço SOAP pelo Android.

Vamos então criar um projeto no nosso ambiente de desenvolvimento chamado "consumidorSoap". O primeiro passo é incluir no projeto o arquivo JAR da biblioteca KSOAP2, que pode ser baixado clicando-se aqui. Se preferir obter uma versão mais recente, baixe diretamente do site do projeto KSOAP2, citado no início deste post.

Este arquivo deve ser colocado na pasta LIBS do projeto, conforme imagem:







O passo seguinte é criarmos o método que consome o serviço:


   // Método que consome o webService.
   public double converterCelsiusParaFarenheit(double grausCelsius)
   {
      
      // Define variável para armazenar o resultado.
      double resultado=-1;
      
      // Define o namespace, a URL do endpoint, e a ação do webService.
      String NAMESPACE="http://www.w3schools.com/webservices/";
      String URL = "http://www.w3schools.com/webservices/tempconvert.asmx?wsdl";       
      String END_POINT="http://www.w3schools.com/webservices/";     
      String METHOD_NAME="CelsiusToFahrenheit";                                     
      String SOAP_ACTION=END_POINT + METHOD_NAME;                            
            
      // Define quantos milissegundos o KSOAP2 aguardará antes de considerar que a requisição falhou.
      int timeout=20000;
      
      // Declarações das variáveis necessárias para criar a requisição e transportá-la.
      HttpTransportSE ht;
      SoapObject request;
      
      // Cria a requisição SOAP, para consumir o webService.
      request=new SoapObject(NAMESPACE, METHOD_NAME);    
      
      // Cria o envelope.
      SoapSerializationEnvelope envelope=new SoapSerializationEnvelope(SoapEnvelope.VER11);
      envelope.dotNet = true;
      
      // Acrescenta o parâmetro ao argumento do webService.
      request.addProperty("Celsius", String.valueOf(grausCelsius));
            
      // Insere a requisição montada no envelope.
      envelope.setOutputSoapObject(request);
      
      // Define o objeto que efetuará o transporte. Aqui também é definido o timeout.
      ht=new HttpTransportSE(Proxy.NO_PROXY, URL, timeout);

      try
      {
         // Efetivamente chama o consumo do webService.
         ht.call(SOAP_ACTION, envelope);
         
         // Extrai os elementos da resposta do webService.
         String rs = "" + envelope.getResponse(); 
         resultado=Double.parseDouble(rs);

      }
      catch (Exception e)
      {
         // Caso tenha ocorrido algum problema, indica a mensagem de erro no LogCat.
         Log.i("consumidorSoap", "(MainActivity, método converterCelsiusParaFarenheit) erro: " + e.toString());
      }

      // Limpa os objetos instanciados, para liberar memória.
      request=null;
      envelope=null;
      ht=null;

      // Retorna o resultado.
      return resultado;
   }


A rotina acima consumirá o webService SOAP chamando o método remoto "CelsiusToFarenheit", passando um valor em graus Celsius e recebendo de volta uma resposta com o valor convertido em Farenheit.

Copie e cole o método na classe MainActivity.java.

Agora vamos criar a chamada ao método:

Primeiro vamos definir as variáveis, logo antes do método onCreate():

   // Define as variáveis que guardarão os valores das temperaturas.
   private Double temperaturaEmFarenheit;
   private Double temperaturaEmCelsius;

   private String mensagem="";


Depois, no próprio método onCreate(), logo após o "setContentView", vamos adicionar o código:

    // Chama o método para consumir o webService que converte de Celsius para Farenheit.
    temperaturaEmCelsius=32.0;
    temperaturaEmFarenheit = converterCelsiusParaFarenheit(temperaturaEmCelsius);

    // Define a mensagem de saída.
    if (temperaturaEmFarenheit > 0)
    {
       mensagem=temperaturaEmCelsius + "° Celsius = " + temperaturaEmFarenheit + "° Farenheit.";
    }
    else
    {
       mensagem="Não foi possível efetuar a conversão a partir do webService.";
    }
     
    // Mostra o resultado da conversão no LogCat.
    Log.i("consumidorSoap", mensagem);


O passo seguinte é acrescentar a permissão de uso de Internet ao arquivo AndroidManifest.xml, sem a qual ganharíamos erro:

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

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

    <uses-permission android:name="android.permission.INTERNET" />
    
    <application
        android:allowBackup="true"
        android:icon="@drawable/ic_launcher"
        android:label="@string/app_name"
        android:theme="@style/AppTheme" >
        <activity
            android:name="com.example.consumidorsoap.MainActivity"
            android:label="@string/app_name" >
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    </application>

</manifest>


Também teremos que criar uma entrada no LogCat, a fim de visualizar as mensagens de debug advindas da execução do nosso código, pois não estamos mostrando nada na tela do dispositivo.

Basta selecionar o LogCat, na parte inferior central da janela do Eclipse e primeiro clicar no sinal de "+" verde. Na janela que se abre, digitar "consumidorSoap" nas duas primeiras linhas e depois clicar no botão "OK":





Pronto. Agora é só compilar o projeto e ver o resultado:







Quem preferir poderá baixar o código completo. É claro que este é um exemplo bem simples, consumindo um webService SOAP básico. Se for o caso do WSDL conter objetos complexos (complexTypes), a abordagem muda um pouquinho. Quem precisar de ajuda, estou à disposição. Ficamos por aqui. Espero que tenha sido proveitoso. Até o próximo post!

segunda-feira, 27 de abril de 2015

A importância do embasamento teórico-filosófico no desenvolvimento de aplicativos para celular




Conhecer o fenômeno é imprescindível


Saber programar, somente, não garante o sucesso de um aplicativo de celular. É de fundamental importância, também, entender o fenômeno que está ocorrendo no mundo nos últimos anos, onde a tecnologia faz o papel das engrenagens que dão suporte ao processo, este sim, bem mais profundo.

Aplicativos baseados nas necessidades advindas da compreensão deste fenômeno serão aqueles que farão estrondoso sucesso, em detrimento dos que serão meras migrações de softwares do mundo desktop. Mas... O que está acontecendo no mundo? Que fenômeno é esse, afinal?


Um diagnóstico


No ano de 1999, o filósofo Pierre Levy publicou um livro intitulado "Cibercultura",  no qual discorreu sobre uma teoria segundo a qual algo de inédito estaria surgindo no mundo. O autor fez diversas previsões sobre o futuro que se aproximava, baseando-se em movimentos coletivos que começavam a surgir, diferente de qualquer exemplo anterior.

Sustentava a hipótese que estaria havendo um movimento social espontâneo, um fenômeno de organização de indivíduos em rede, proporcionado pelo avanço das comunicações e da tecnologia digital, com o advento da Internet.

Cinco anos depois, em 2004, nascia o conceito "Web 2.0", descrevendo um ambiente de troca de informações desenhado no topo do que antes era conhecido como "World Wide Web" (WWW), que, na versão original, era meramente um lugar onde se lia de forma passiva páginas com informações sobre determinados assuntos.

A diferença agora era que sua versão evoluída permitia um nível mais sofisticado de interação: escrever comentários, avaliar textos, publicar artigos, etc. De repente o cidadão se deu conta de que ele passou a ser também produtor de conteúdo, deixando de ser um personagem meramente passivo. "Web 2.0" foi como gasolina na fogueira vislumbrada por Pierre Levy.


De "emissor e receptores" a "receptores emissores"


Iniciava ali a migração de um mundo construído após a revolução industrial (onde prosperaram rádio e televisão) em que havia um (ou alguns) transmissores e uma infinidade de receptores passivos (que aceitavam a mensagem como verdade única, sem questioná-la: um monólogo), para uma realidade diametralmente oposta, onde agora havia muitos emissores e muitos receptores (que debatiam: diálogo). O mundo "1 pra N" começava a dar lugar ao mundo "N pra N", onde agora qualquer cidadão comum poderia, além consumir, produzir informação, ou seja, um ambiente onde os papéis eram frequentemente alternados. Agora, todos podiam ter seu próprio canal.


Descontrole de ideias


Com essa nova configuração onde cada indivíduo podia ser também um emissor, era natural que em pouco tempo o ambiente se tornasse caótico: o descontrole de ideias era a tônica. O antigo conceito de uma entidade ou instituição, privada ou governamental, que controlava a comunicação e por conseguinte divulgava uma "verdade" única, começava a ruir e agora havia muitas verdades sendo propagadas. Com mais personagens produzindo informação, junto com as facilidades tecnológicas, houve uma vertiginosa queda nos custos, pois os receptores estavam ávidos por conteúdo criativo, autêntico, que não obedeciam necessariamente ao "padrão". E logo começaram a consumir essa "programação" ou a utilizar serviços alternativos, que atendiam de forma mais inteligente aos seus anseios. Isso punha em cheque as organizações tradicionais, que pela primeira vez em muitas décadas, estavam sem conseguir entender o que estava acontecendo. E ainda que tivessem muitos recursos financeiros, começaram a não conseguir competir no novo contexto, muito menos controlá-lo.


Empoderamento


Não demorou muito para o cidadão comum perceber que agora tinha um valor político-econômico inédito como pessoa. E que essas ferramentas tecnológicas que lhe permitiam propagar suas ideias, provocaram o surgimento de mais um fenômeno novo: Um aumento de sua auto-estima, mudando a percepção do que era capaz de realizar, e o consequente empoderamento do indivíduo. De repente uma ideia ganhou o poder de quebrar toda uma indústria. Cidadãos se viram capazes de mudar os rumos de governos.


Descentralização


Diversos pólos de conhecimento e opinião foram surgindo aos poucos, tornando-se células independentes, representando alternativas às verdades absolutas que costumavam ser ventiladas no passado recente. Aos poucos, era possível perceber que essas células dariam origem à nós. E que esses nós dariam origem, mais tarde, à uma rede.


Reintermediação


Com a formação das redes de conhecimento, foram surgindo soluções totalmente inéditas para antigos problemas, que já não podiam mais ser atendidos eficazmente pelas organizações tradicionais, com suas ideias enferrujadas (soluções para o mundo pós revolução industrial, mas aquém dos problemas contemporâneos). Diversos aplicativos foram surgindo e modificando totalmente a maneira como as pessoas interagiam com o ambiente. Representaram verdadeira revolução no mercado, a um custo irrisório. Aplicativos que faziam desconhecidos fecharem negócios com segurança. Outros que facilitavam chamar um táxi, unindo passageiro e motorista de uma forma muito mais inteligente. Alguns resolviam a questão da hospedagem para viajantes, definindo um critério de avaliação mútua, que dava a certeza ao viajante de ter onde ficar e garantia a segurança de quem oferecia a hospedagem a um desconhecido. Foram surgindo, enfim, soluções mais inteligentes e baratas para questões que há pouquíssimo tempo eram controladas por grandes organizações, as quais determinavam forma e preço a seu bel prazer. E as organizações sentiram o baque. Afinal, seria mesmo o destino do intermediador a extinção?

A observação inicial deste fenômeno levava mesmo à percepção de que ocorreria uma forte desintermediação (ou seja, a extinção completa dos intermediários nas relações entre as pessoas). O comércio seria substituído, os hotéis desapareceriam, assim como as cooperativas de táxi. Pois os serviços estavam ficando ruins e extremamente caros, em função de vícios advindos do controle absoluto que as organizações tinham sobre os clientes. E agora havia uma promissora alternativa. Um viva os aplicativos!

No entanto, como mostrou a história, não foi o que ocorreu. A imaginada desintermediação, na verdade deu lugar a uma reintermediação, ou seja, as organizações tradicionais foram sendo substituídas por organizações inovadoras, capazes de entender a guinada de direção para onde o mundo estava indo e atender melhor ao exigente cidadão que estava surgindo.

Meritocracia


Nesse novo ambiente com centenas ou milhares de envolvidos, uns provendo serviços ou conteúdo, e outros consumindo, logo se percebeu uma necessidade de classificar o mérito (ou demérito) dos participantes, em prol da confiabilidade e da segurança. Nasceu o conceito de "karma digital", ou seja, a reputação do cidadão em suas participações online. O karma digital tinha como função modular a comunidade, avaliando o comportamento de cada um. Também destacava os melhores, sucumbia os piores e impedia indivíduos mal-intencionados de participar da moderação. Era a versão 3.0 dos antigos "selos de qualidade" ou "garantias de autenticidade", e os "ISOs" das últimas décadas. Surgiam novas moedas de troca nas relações interpessoais: reputação e mérito. 


Uma nova maneira de resolver problemas complexos


Em paralelo, houve, nas ruas, inúmeras manifestações de grupos organizados em prol de mudanças. Na verdade uma explosão de "enxameamentos" (termo de autoria de Augusto de Franco), que tinham em comum o fato de que eram geralmente catalisados por meio das "redes-sociais" digitais.

Assim foram os movimentos "Primavera Árabe" (2010), "Revolução de Jasmin" na Tunísia (2010), Occupy Wall Street" (2011) nos EUA, a "Revolução Egípcia" (2011), "Manifestações de Junho" (2013) no Brasil, Protestos na Turquia (2013), "Revolução dos Guarda-chuvas" em Hong-Kong (2014), "Fora Dilma" (2015) no Brasil, para citar alguns.

Todos com características semelhantes, pautas difusas, ausência de líderes e momentos de vales e picos totalmente espontâneos e descontrolados.

Vários pensadores (entre eles o próprio Pierre Levy), no Brasil Carlos Nepomuceno, Augusto de Franco, na Espanha, Manuel Castells, dentre outros, discorreram suas teorias a respeito e chegaram a conclusão semelhante: Estamos vivendo uma revolução cognitiva do ser humano cujas causas são ainda especulativas, mas com forte influência tecnológica.

Resumidamente, com o advento da comunicação global de massa, somado com o aumento populacional exponencial, escassez de recursos e percepção de falta de competência dos governos (e empresas) atuais para solucionar as questões do dia a dia, houve uma explosão de movimentos reivindicatórios em todo o mundo.

Com a miniaturização dos dispositivos, os velhos computadores desktop acabaram nos bolsos das pessoas e as redes sociais antes consideradas "virtuais", agora as mantém conectadas umas às outras 24 horas por dia e em qualquer lugar.

Aplicativos já resolvem antigos problemas do dia a dia de forma muito mais eficiente. A tecnologia acabou provando que há soluções muito mais baratas e eficazes e isso acabou salientando de forma inequívoca a ineficiência e o peso das governanças tradicionais.

Como exemplo podemos citar os aplicativos de Táxi, que, além de otimizarem o encontro do passageiro com o motorista através da seleção do taxista mais próximo via GPS, também apresentam solução no que diz respeito à reputação do motorista, permitindo que o cidadão faça sua escolha através da avaliação feita por passageiros anteriores. Assim o serviço se auto-regula, tornando-se independente de cooperativa e muito mais confiável, pois é baseado em opiniões isentas.

Aplicativos de compra e venda surgiram, permitindo que cidadãos que não se conhecem fechem negócios de forma segura, através, também, de uma espécie de "karma virtual", em que a reputação é a grande moeda de troca.

Também criaram os de avaliação de restaurantes permitindo que uma pessoa escolha onde fazer sua refeição de acordo com a percepção prévia de outros clientes.

São tantos exemplos focados em diversas áreas, e o que têm em comum é o fato de que escancararam que os governos e as instituições ficaram obsoletos, pois não trabalham com o mesmo nível de inteligência.

Entender o fenômeno, portanto, é essencial para o sucesso do aplicativo


É de fundamental importância entender o contexto por que passa o mundo hoje, de forma a criarmos aplicativos que estejam em consonância com esta nova realidade, para que sejam altamente inovadores, resolvendo radicalmente problemas de formas que ninguém havia pensado antes.

Ao pensar em criar um aplicativo devemos responder as seguintes questões:

* Que serviço mal prestado poderia ser melhor atendido por uma solução digital-colaborativa?

* Como a colaboração do cidadão poderia ajudar a construir esta solução?

* Qual seria o ganho do cidadão ao utilizar esta nova solução, percebendo o retorno de sua participação?

* Por que esta ideia de app é considerada inovadora?

* Como proteger a nova solução da corrosão por vícios do sistema?

Para ilustrar, vamos responder às perguntas considerando um aplicativo de táxi: 1) O serviço mal prestado de uma tradicional cooperativa de táxi pode ser melhor atendido por uma solução digital-colaborativa. 2) O cidadão pode colaborar avaliando o motorista, de forma a deixar uma mensagem utilizável pelos futuros passageiros na escolha do táxi. 3) O ganho do cidadão seria obter um táxi mais rapidamente (GPS) e um motorista mais confiável do que se sob a chancela de uma cooperativa. 4) Esta ideia de app é considerada inovadora porque modifica de forma disruptiva a relação dos passageiros com taxistas e cooperativas. 5) Melhorando continuamente o algoritmo para evitar manipulação das avaliações.


Visualizando a diferença que classifica uma solução como 3.0


Vamos pensar por um momento na figura de um apicultor. Ele depende da produção de mel. Ele o vende e sua família depende disso para o sustento.

Agora vamos imaginar um fazendeiro que ganha a vida com o comércio de leite. Sua atividade é ordenhar vacas. Sua família depende disso para o sustento.

Qual a diferença entre o apicultor e o ordenhador de vacas? O que aconteceria se ambos fossem afastados de suas atividades temporariamente?

Faltaria leite. Mas não faltaria mel!

Isto porque as abelhas continuariam produzindo mel, ainda que com a ausência do apicultor.

Uma solução 3.0 é, portanto, uma maneira de atender a um problema que independe da presença do dono. Ela se auto-regula (ou se auto-gere).

O criador do aplicativo de táxi não é proprietário de nenhum veículo sequer. Não tem atendentes para pôr passageiros em contato com motoristas. Também, o criador do app de hospedagem não é dono de hotéis. O criador do aplicativo de compra e venda não possui um comércio. Todos eles contam com algo imprescindível no novo contexto: A colaboração.

Tipos de colaboração


É fundamental entender que há tipos diversos de colaboração. Quando falamos em colaboração, a ideia é de utilizar um movimento do usuário do aplicativo para facilitar algum processo.

Essa colaboração pode ser consciente (caso em que chamamos de colaboração direta), onde o cidadão sabe que está fazendo algo em prol de uma causa (exemplo: avaliar um motorista).

Há também a colaboração indireta, em que nem sempre o usuário sabe que está ajudando. Um exemplo clássico é a utilização do GPS do celular do indivíduo para obter a uma localização.

Uma terceira forma de colaboração, bem mais sofisticada e difícil de criar é a colaboração induzida (ou cruzada). Como exemplo podemos citar alguns sites que pedem para o usuário digitar alguns caracteres de confirmação para que o sistema saiba que ele é um ser humano e não um robô. Parte dos caracteres digitados têm realmente esta finalidade, mas geralmente é mostrada uma foto de uma página de um livro e o cidadão tem que digitar a palavra ou número visualizado. Pois bem, ao fazê-lo, a pessoa está colaborando na digitalização de um livro, sem saber: Exemplo de colaboração induzida.


Tipos de Moderação


Outro assunto importante é a moderação. Com as possibilidades de comentar, avaliar e denunciar, advindas desse contexto de aplicativos móveis em redes-sociais, não há controle do que se diz e isso se torna um problema altamente complexo.

O mundo 1.0 geralmente vê como solução colocar um algoritmo para detectar palavras inadequadas, mas isso é rapidamente burlado pelo ser humano, que insere espaços entre as letras ou abrevia os palavrões, enfim... O algoritmo também não é capaz de detectar um comentário racista, por exemplo. Fácil! Basta colocarmos um funcionário fazendo moderação dos comentários, pensa o gerente 1.0. Haja hora extra!

Existem tipos diversos de moderação. Alguns são mais apropriados do que outros. Alguns são inovações incrementais, outros inovações disruptivas. É importante entender a diferença:

"Pré-moderação": é quando se filtra um conteúdo antes de sua publicação. Pressupõe o aval de alguém, que libera a informação segundo critério próprio.   

"Pós-moderação": ao contrário, permite que qualquer um publique a informação, sem filtro. Depois de publicada, será analisada segundo um critério, por alguém que decidirá se será mantida ou não.

"Auto-moderação" (ou auto-regulação): é inovação disruptiva, pois retira do modelo a figura do censor. A auto-moderação pressupõe ferramentas que permitam aos usuários da própria rede denunciar uma publicação como imprópria (o que, por conseguinte, faz dela pós-moderada também). A decisão de remover o conteúdo é critério do algoritmo (por exemplo: Caso haja 10 denúncias de uma determinada publicação, ela será removida automaticamente).


Conclusões


As conclusões a que chegamos com este longo post é que a inovação é, sem dúvida, uma atividade social. Reside na interseção entre a invenção e o insight. É multidisciplinar. Deve ser relevante e criativa. Constitui um processo sistemático e não resolve nada sozinha.

O embasamento filosófico permite criar uma teoria. Daí surge um diagnóstico, que possibilita a implementação de uma metodologia.

O mundo mudou, há um crescimento exponencial da população. Os recursos permanecem os mesmos e não está havendo um planejamento adequado para atender a todos os anseios. Há cada vez mais diversidade na sociedade e os governos e as organizações são cada vez menos capazes de representar e atender todos os cidadãos.

A tecnologia, o empoderamento do indivíduo, a reintermediação dos serviços e a forma de representação política, serão a tônica dos debates nos próximos anos.

Assistimos, diante de nossos olhos, ao desenrolar de uma época ao mesmo tempo incerta e fascinante, mas repleta de oportunidades para quem fizer o dever de casa.

Portanto, estar bem embasado filosoficamente é condição primordial antes de cogitarmos produzir aplicativos de celulares.


sexta-feira, 24 de abril de 2015

Dez considerações sobre performance no ambiente mobile

É muito comum que desenvolvedores de sistemas extremamente competentes se aventurem pelo mundo dos apps para dispositivos móveis com alta taxa de frustração. Geralmente o motivo é que não adequam corretamente as suas criações ao contexto móvel.

Desenvolver aplicativos para celulares pressupõe o conhecimento de algumas questões bastante peculiares.

Este artigo visa explicitá-las, de forma a orientar desenvolvedores sobre pontos fundamentais do contexto mobile, que influenciarão na qualidade da experiência do usuário final.

1.  A Rede

A primeira observação diz respeito à rede móvel. Nem sempre o aplicativo terá acesso à rede para realizar uma comunicação. Isso deve ser a premissa número 1 ao desenvolver aplicativos. Os fatores podem ser os mais diversos: Falha das operadoras, zonas de sombra, condições climáticas desfavoráveis, sabotagem, interferências, interrupção do serviço devido ao limite do plano de dados, ausência de plano de dados, enfim, vários motivos podem deixar um aplicativo sem comunicação com a Internet. Isso deve ser tomado como uma realidade e o desenvolvedor deve preparar o aplicativo para responder corretamente. Um app que exija autenticação, por exemplo, pode usar uma técnica de guardar o estado, de forma a não precisar mais da rede uma vez autenticado o usuário.

2.  Integração

Um sistema desenvolvido para ambiente móvel geralmente é composto por duas partes distintas, conhecidas formalmente como "front-end" e "back-end". A primeira é o aplicativo propriamente dito, que é executado no aparelho celular do usuário. A segunda é uma API, um programa que existe hospedado em um servidor remoto, à espera de requisições. O trabalho é dividido entre essas duas partes, cabendo ao desenvolvedor determinar o que é papel do front-end e o que é papel do back-end. Geralmente o aplicativo tem o objetivo de expor as informações de forma que possam ser visualizadas fácil e rapidamente pelo usuário (por exemplo, em um mapa). E a API é onde ocorre o processamento mais pesado e as buscas nos bancos de dados. As duas partes devem conversar da maneira mais otimizada possível, trafegando o mínimo de dados pela rede. Também, de acordo com o que vimos no item 1, é preciso fornecer uma alternativa à rede, garantindo as funcionalidades do aplicativo na sua ausência.

3.  Escassez de recursos

Embora a cada dia os celulares tenham mais memória e poder de processamento, é muito comum que eles estejam sempre entupidos de aplicativos, videos, músicas, etc. Em outras palavras, o desperdício de recursos aumenta exponencialmente junto com o poder tecnológico dos aparelhos. Como se não bastasse, o Android tem uma questão séria em relação à distinção da memória interna do aparelho e da memória externa (o cartão SD). Na grande maioria das vezes os aplicativos e seus bancos de dados locais são armazenados nessa memória interna (na pasta "/data/data"), que geralmente é menor e quando cheia, torna o celular lento e causa travamentos. Portanto, os recursos são escassos. Isso exige que o desenvolvedor otimize o máximo que puder, reutilize código, mantenha arquivos de imagens o menor possível, use o menos possível da rede, libere memória sempre que puder. No Android, é tarefa do desenvolvedor, por exemplo, retirar as activities (telas) da memória, (com finish())quando não são mais utilizadas. Antes de publicar um APP na loja, é imprescindível passar um pente fino no código-fonte e nas pastas do projeto, a fim de verificar o que pode ser excluído, diminuído ou otimizado.

4.  Assincronia

A maioria dos acessos de um aplicativo à rede deve ser assíncrona. Senão, o usuário permaneceria esperando o app terminar uma consulta antes de mostrar o resultado. Neste ínterim, o aplicativo ficaria travado. Se o usuário estivesse olhando para um mapa, por exemplo, e fosse feito um acesso síncrono, a navegação pelo mapa ficaria interrompida até que a requisição tivesse sido respondida. Imagine, também, rotinas que atuem em background, sem que o usuário saiba. Todas devem ser assíncronas. Não fosse assim, travariam o aplicativo até o término da operação. É claro que cada caso é um caso. Há rotinas onde a sincronia é necessária, como por exemplo uma autenticação de usuário, que depende do resultado para prosseguir, ou a obtenção de dados que serão utilizados à frente. Mas é possível criar acessos assíncronos de forma que os resultados obtidos via rede vão sendo mostrados pouco à pouco, à medida que são recebidos, e não apenas ao final do processo. Isso melhora substancialmente a experiência do usuário.

5.  Gravação local

Um dos maiores segredos de sucesso de aplicativos famosos é justamente a gravação local de dados. É uma técnica que permite oferecer ao usuário uma experiência de fluidez incrível no uso do app. Toda operação de gravação tem resposta imediata, causando uma percepção de que o aplicativo é incrivelmente rápido. Isso é feito com algo extremamente simples: a gravação dos dados num banco local SQLite, que reside no próprio celular. Esses dados serão sincronizados mais tarde, via rede (geralmente no método onPause() do aplicativo). Essa técnica permite até mesmo criar aplicativos que não precisam de rede. Imagine um aplicativo de avaliação de restaurantes onde você possa ver e avaliar os estabelecimentos, mesmo sem sinal de Internet presente. Isso é possível se o aplicativo guarda tudo num banco de dados local. Depois, quando o app perceber em algum momento que retornou o sinal de Internet, então ele faz o upload para o servidor, daquilo que ainda não tenha sido sincronizado.


6. Antecipação

Antecipação é outra técnica muito interessante que muda completamente a experiência de fluidez do usuário e aproveita melhor o tempo de "inatividade". Imagine que você criou um app que permite que o usuário tire fotos e depois as publique na Internet. Logo depois que o cidadão tira uma foto, o app exibe uma caixa de diálogo perguntando: "Você deseja publicar a foto neste momento?". A técnica de antecipação consiste em, antes de jogar na tela a pergunta ao usuário, já iniciar um processo assíncrono de upload da foto, ou seja, o app já estará enviando a foto para o servidor enquanto o usuário vê a mensagem e pensa se quer publicá-la ou não. Se o usuário levar 3 segundos para pensar, pode ser suficiente para que a foto seja transferida. A decisão do usuário, então, confirmará (ou não) a publicação da foto.

7. Cache

Eis uma técnica que pode ser vista sob vários aspectos. Mas, é inquestionável que o uso de cache é o que torna possível o que fazemos hoje com nossos aparelhos celulares. Para aqueles que não sabem, o cache é uma forma de armazenar dados que permite sua recuperação de maneira muito rápida, praticamente instantânea, se comparado aos métodos tradicionais. Explicando muito superficialmente, os dados que buscamos quando efetuamos uma requisição, via de regra estão gravados em discos, que são dispositivos físicos, cujo acesso depende de deslocamentos de braços mecânicos sobre superfícies magnéticas. Essas buscas geralmente ocorrem na casa dos segundos, o que, embora pareça pouco no contexto humano, no contexto das máquinas é uma eternidade. Então, foi inventado o cache, que nada mais é do que a reprodução de parte dos dados em memória eletrônica. Dessa forma, o tempo para obter as respostas cai para a casa dos milissegundos, permitindo a experiência que temos hoje em nossos smartphones. Acontece que a maneira de aplicação de um cache é também bastante subjetiva. Mas o conceito e a intenção permanecem os mesmos. Uma das formas de implementar cache é na API remota, que é consumida pelo app. Cria-se uma tarefa agendada que extrai a informação de um banco de dados de tempos em tempos e a armazena em memória real. Esta memória (o cache) é, então, exposta via webService. Isso garante um acesso praticamente imediato do app aos dados remotos, pois a consulta ao banco de dados remoto foi antecipada pela API. Outra maneira de implementar cache é no próprio aplicativo. Por exemplo: Na primeira vez que o aplicativo é acionado, é feita uma consulta à API que traz todos os itens disponíveis numa determinada tabela do banco de dados remoto (por exemplo: uma lista de restaurantes). Esses itens são, então, armazenados em um banco de dados local, dentro do aparelho celular, o que constitui um cache local de dados). Esse tipo de cache vai permitir que, mesmo sem acesso à Internet, o aplicativo possa mostrar ao usuário os restaurantes para que sejam avaliados. Cache é essencial.


8. Compatibilidade

Sempre que você tiver aquela vontade irresistível de usar aquele novo recurso fantástico disponível apenas na versão recém-lançada do sistema operacional Android, pense duas vezes. Qual o seu público-alvo? A quantas pessoas deseja que seu aplicativo atenda? Num país como o nosso, embora as estatísticas mostrem que já existem mais celulares do que pessoas, é pouco provável que a maior parte deles sejam aparelhos modernos. Então, compensa utilizar um recurso que vai restringir o uso do seu app apenas aos dispositivos mais novos? Particularmente acho que não. Essa é uma discussão importante, pois durante o desenvolvimento de aplicativos Android, é preciso especificar para qual versão você está programando, o que vai provocar uma limitação no número de aparelhos que suportam o seu app.  O resultado é que, se uma pessoa com um celular mais antigo pesquisar o seu app na Google Play Store, se ele não for compatível com o aparelho dela, o app nem ao menos aparece na pesquisa. Eu tenho como filosofia criar apps que funcionem na maior parte possível de aparelhos Android. No uso de mapas, por exemplo, é preciso baixar o "Google Play Services for Froyo", biblioteca que (embora considerada deprecated) é compatível com qualquer modelo de aparelho Android. Aplicativos com mapas produzidos com esta biblioteca funcionarão no mais básico Android (essa biblioteca está incluída em nosso ambiente de desenvolvimento disponível aqui no blog). No momento que se publica o APK na loja, o desenvolvedor recebe um relatório informando o número de dispositivos compatíveis. Recomendo levar este quesito com seriedade. É muito frustrante não poder usar um app por ser incompatível com nosso modelo de celular. Seu usuário também pensará desta forma.


9. Agilidade

Chamamos os aparelhos celulares de "dispositivos móveis" não é à toa. As pessoas usam seus smartphones na rua, à caminho do trabalho, ou no supermercado, enfim, é preciso entender o contexto em que acontece o uso do aplicativo. O usuário está com pressa, fora de casa, no meio do caminho para algum lugar, as condições de iluminação podem variar (o usuário pode estar na praia, com sol à pino, ou dentro de um vagão do metrô mal iluminado). Portanto, para um app ser considerado adequado, as respostas precisam ser rápidas. Mantenha o foco em responder ao usuário imediatamente.


10. Simplicidade

Alguns desenvolvedores sustentam uma regra de que no contexto mobile, o número de cliques (toques na tela) não deve passar de três, desde a primeira interação do usuário até a obtenção daquilo que ele procura. De fato, existe uma infinidade de aplicativos altamente complexos que não fazem sucesso porque não é o que o usuário quer. Num aplicativo de ônibus, por exemplo, talvez o usuário não queira traçar rotas especificando origem e destino dos veículos que tem ar-condicionado e rodas de liga leve e teto solar, mas, simplesmente, querem saber onde o ônibus está. Portanto, tenha isso em mente. Mantenha as coisas básicas o máximo que puder. Pense nos aplicativos mais famosos (que têm bilhões de downloads na loja) e confira como são, de fato, simples.



Embora alguns dos itens expostos acima possam parecer não ter relação com performance, no meu entender há vários tipos de "performance". O conceito está sim, sempre ligado a desempenho, o que não significa apenas que o aplicativo é rápido, mas sim que toda uma experiência do usuário tem uma prazerosa fluidez.

Há também alguns aspectos importantes no desenvolvimento de aplicativos que consiste em ter um bom embasamento teórico-filosófico, o que funciona como os alicerces da própria ideia do aplicativo, o que dá sentido a ele.

Este será o tema de nosso próximo post. Não perca!

quarta-feira, 22 de abril de 2015

Como carregar um projeto Android no workspace do ambiente de desenvolvimento

Como carregar um projeto Android no workspace do ambiente de desenvolvimento:

1) Baixe o projeto.
2) Descompacte em uma pasta diferente da pasta do workspace (!).
3) Clique com o botão direito do mouse sobre o "Package Explorer" e selecione "import":






4) Selecione a opção "Existing Android Code Into Workspace":





5) Clique no botão "browse" e navegue até a pasta raiz onde descompactou o projeto. Marque a opção "Copy projects into workspace":






6) Pronto!



Traduzindo aplicativos Android

Muita gente me pergunta como se traduz aplicativos Android, fazendo com que os textos apareçam na língua configurada pelo usuário no dispositivo.


Exemplo de aplicativo traduzido (tradeTeller) que se adapta
automaticamente à língua configurada no dispositivo.

Neste post aprenderemos exatamente como fazê-lo. Veremos que é algo bastante simples (embora um pouco trabalhoso), pois o framework já previa um ambiente internacionalizado desde sua concepção.

A abordagem é análoga à adotada na questão da parametrização para resolver a aparência do aplicativo em tamanhos de tela diferentes, quando fizemos (por ocasião do post: Como garantir a mesma aparência em qualquer tamanho de tela) uso dos arquivos "dimens.xml" para definir os tamanhos de fonte proporcionais a cada dimensão.

Na tradução de aplicativos, devemos pensar em duas situações. A primeira diz respeito aos textos fixos que aparecerão nas telas do aplicativo. Para que estejam na língua correta,  é preciso criar várias versões do arquivo "strings.xml", uma para cada língua em que desejamos disponibilizar nosso app. Esse arquivo está localizado na pasta "res/layout/values" e sua função é armazenar todos os textos que aparecem em nosso aplicativo. A segunda situação é que o aplicativo certamente precisará ter mensagens de alerta ou de erro, que precisarão de alguma intervenção, apresentando uma afirmação ou questionamento e pedindo uma ação do usuário. Para que, também, esses alertas apareçam na língua correta, devemos recuperar em tempo de execução os textos parametrizados.

Strings.xml

O framework do Android pressupõe que todas as frases que aparecem em uma tela de um app estejam parametrizadas, isto é, no design da tela (arquivos xml do diretório "res/layout") jamais deve haver um texto "hard-coded" (a frase propriamente dita, escrita por extenso dentro de um "android:text="). Vejamos um exemplo, para entender melhor:

Errado (hard-coded):

<TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Olá mundo!" />


Certo:

activity_mail.xml:

<TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="@string/textoOlaMundo" />

strings.xml:

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <string name="app_name">meuPrimeiroApp</string>
    <string name="action_settings">Configurações</string>
    <string name="textoOlaMundo">Olá mundo!</string>
</resources>


Os textos que especificamos nos desenhos de tela (arquivos xml da res/layout) devem ser, todos, parametrizados (conforme o exemplo) apontando sempre para um valor no arquivo "res/values/strings.xml".

A razão desta pequena regra, que à princípio mais nos parece um mero aborrecimento, é justamente para que possamos traduzir o aplicativo.

Vamos ver então, como faríamos para disponibilizar um app em inglês, por exemplo. Para isto, precisaremos criar uma pasta embaixo de "res", conforme ilustrado na figura:




Vamos abrir o projeto "meuPrimeiroApp"  e clicar com o botão direito do mouse sobre a pasta "res". Depois selecionemos a opção "New->Folder". Na tela seguinte, digite, no campo folder name: "values-en".

Esta pasta é o local onde o framework do Android espera que seja colocado o arquivo strings.xml com os textos traduzidos para a língua inglesa (analogamente, se quiséssemos traduzir para o francês, criaríamos a pasta values-fr ou values-es para o espanhol).

Agora o segundo passo: Abrirmos a pasta "values" e localizarmos o arquivo "strings.xml". Selecionando-o através de um clique com o botão esquerdo do mouse. Digitando CTRL+C copiamos o arquivo. Depois selecionemos a pasta "values-en" recém criada. Digitando CTRL+V colamos ali o arquivo.

Temos agora uma cópia idêntica do strings.xml na pasta values-en. Vamos modificá-lo para que fique assim:

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <string name="app_name">myFirstApp</string>
    <string name="action_settings">Settings</string>
    <string name="textoOlaMundo">Hello world!</string>
</resources>

Ou seja, com os parâmetros traduzidos para o inglês.

Verifique o arquivo original. Ele deve estar com os parâmetros em português, assim:

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <string name="app_name">meuPrimeiroApp</string>
    <string name="action_settings">Configurações</string>
    <string name="textoOlaMundo">Olá mundo!</string>
</resources>

Cuidado para não confundir os dois. É um erro muito comum, visto que as duas abas ficam lado a lado no topo da tela de edição do código fonte.

Note também, que o strings.xml da pasta "values" principal, é o arquivo default. Portanto, caso o dispositivo Android não encontre o arquivo correspondente à língua configurada no aparelho, assumirá o "res/values/strings.xml" como o padrão.

O arquivo "res/layout/activity_main.xml" deve ficar assim:

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:paddingBottom="@dimen/activity_vertical_margin"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    tools:context=".MainActivity" >

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="@string/textoOlaMundo" />

</RelativeLayout>

Grave tudo com CTRL+S. Depois compile o projeto e veja o que aparece no seu celular:





Agora começa a brincadeira. Sem fazer nenhuma alteração no código-fonte e nem compilar novamente, configure o seu celular para funcionar na língua inglesa. Desta forma:




Após a alteração, perceba que o nome do aplicativo já aparece em inglês. Abrindo a aplicação, já será possível ver as mudanças:




Entretanto, apesar da tradução dos textos fixos ter funcionado corretamente, podemos ver que as mensagens de alerta que mostramos nos eventos (onCreate(), onStart(), etc.) ainda estão em português!

Isso acontece porque elas são geradas em tempo de execução. E as instruções que as imprime estão na classe que corresponde à tela (MainActivity.java).

É esta a segunda situação que mencionei no início do post.

Para resolver, não é complicado. Primeiro, vamos abrir os dois arquivos strings.xml: o da pasta values padrão e o da pasta values-en (português e inglês) e acrescentar, respectivamente,  as linhas abaixo entre os tags <resources>...</resources>:

res/values/strings.xml:

<string name="mensagemOnCreate">Passei no onCreate()</string>

res/values-en/strings.xml:

<string name="mensagemOnCreate">onCreate() was called!</string>


Agora, vamos abrir a classe "MainActivity.java" da pasta "src". Vamos alterar apenas o método onCreate(), para exemplificar o funcionamento:

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

      // Envia SMS
      //SmsManager smsManager=SmsManager.getDefault();
      //smsManager.sendTextMessage("99999-9999", null, "Este texto foi enviado por SMS", null, null);
      
      String textoOnCreate = getResources().getString(R.string.mensagemOnCreate);
      Toast.makeText(getApplicationContext(), textoOnCreate, Toast.LENGTH_SHORT).show();     
   }

A linha destacada em azul, obtém a frase correta, a partir dos recursos (resources), mas em tempo de execução. Assim, a mensagem de alerta também aparecerá traduzida, pois está, agora, parametrizada.

Será necessário recompilar o código para verificar as alterações. Grave tudo com CTRL+S, compile e veja que, a partir de agora, a mensagem inicial, chamada no onCreate() já aparece em inglês!

Para quem preferir baixar o código-fonte pronto, ao invés de digitar, disponibilizo-o aqui para download. Instruções para carregar o projeto no workspace do Eclipse aqui.

É claro, a tradução do app para outra língua pressupõe que nós a conheçamos. Mas a Google também pensou no caso em que desejemos traduzi-lo para uma língua que não falamos. Aí entra a brilhante solução do trabalho colaborativo.

No painel do desenvolvedor da Google, há uma opção para requisitar a tradução do arquivo strings.xml por parceiros, através de trabalho colaborativo (mas pago). Assim, se quisermos traduzir o aplicativo para, digamos, russo, isto é possível, através desta ferramenta:





Depois é preciso enviar o arquivo xml e escolher para qual língua iremos traduzir e também qual o parceiro que fará o trabalho, de acordo com o prazo (cerca de 10 dias) e o preço (cerca de 30 dólares):





Ufa! Este foi um post extenso. Mas acredito ter sido bem esclarecedor para quem sempre se perguntou como um app pode se adaptar ao idioma configurado em um aparelho Android. Como vimos, é mais simples do que se imagina, embora um pouco trabalhoso.

Com a prática no desenvolvimento de aplicativos, isso se torna rotineiro. Normalmente deixa-se a tradução para o final, quando os arquivos de parâmetros já estão fechados. O mais importante é tomar o cuidado para só usar, tanto nos layouts de tela, quanto nas classes, sempre referências aos parâmetros e nunca os textos escritos por extenso.

Ficamos por aqui. Até a próxima!

------------------------------------------------------



Atualização do post:

Informação adicional, a respeito dos códigos acrescentados ao nome das pastas "values", para guardar o arquivo "strings.xml" relativo a cada idioma: as duas letras acrescentadas após o hífen são um código de idioma definido no padrão ISO 639-1. Opcionalmente, pode-se acrescentar ainda mais um hífen e a letra "r" (minúscula) representando uma região, seguida pelo seu código, no padrão ISO 3166-1-alpha-2.

Para português brasileiro, por exemplo, o nome da pasta ficaria "values-pt-rBR".