domingo, 16 de fevereiro de 2014

The X Java Platform android A plataforma ndroid X Java

Resumo textual do que foi dito na palestra "Android X Java ME: o que é possível com a nova plataforma", apresentada no FISL 12
Ricardo Ogliari
No dia primeiro de Julho estive em Porto Alegre, apresentando a palestra “Android X Java ME: o que é possível com a nova plataforma” no Fórum Internacional do Software Livre. Neste pequeno artigo vou apresentar esta mesma palestra de forma escrita. O objetivo é apresentar oque é possível fazer com Android que era impossível com Java ME, ou, que demandava um esforço tremendo, contrastando com a simplicidade do Android.
Primeiramente é importante falar o porquê do Java ME. Nós estamos vivendo uma época onde só Android e iPhoone tem vez, onde todas as outras plataformas estão renegadas e extintas. Na verdade, essa história não é bem assim.
O Java ME teve seu auge quando a Nokia também estava no topo, quando o Symbian liderava o mercado com uma grande margem de diferença para as concorrentes. Hoje, o sistema operacional ainda lidera, mas com uma pequena margem de diferença. E este é exatamente o ponto chave, o Symbian ainda lidera e tem uma grande base de telefones celulares instalada no mundo inteiro.
Flávio Ferreira, gerente de serviços de valor agregado da TIM, disse o seguinte: O iPhone é um celular que todo mundo quer. O Java é o que todo mundo tem. O livro Mobile Developer’s Guide to the Galaxy traz um dado muito importante: 80% de todos mobile handsets no mundo suportam o padrão Java.
Bem, falar do por que citei Android acredito ser trivial, mas vamos lá. Todas as pesquisas publicadas da metade de 2010 para cá, apontam a plataforma do Google como a líder de mercado nos quatro cantos do mundo. Além disso, inúmeras pesquisas ditam que este domínio só tende a crescer. Andy Rubin afirmou em seu Twitter que “há agora mais de 500.000 aparelhos Android sendo ativados por dia”.
Hardware
A primeira grande diferença é em relação ao hardware. Um dos últimos aparelhos Nokia lançados, já com o Symbian Anna, apresenta as seguintes configurações de hardware:
  • Processador 720 MHZ
  • Memória ROM: 1GB
  • Memória RAM: 256MB
Já o Motorola Atrix, apresenta as seguintes configurações:
  • Processador dual core de 1GHz
  • Memória de até 16GB
  • Memória removível de até 32GB
E isso que estamos falando de um dos últimos lançamentos da Nokia, imagine se comparássemos com os aparelhos Java ME-enabled mais vistos no mercado, como o Motorola V3 por exemplo.
Quando pensamos em aplicativos Java ME, sabemos que temos que trabalhar com aparelhos mais restritos, onde a presença de Bluetooth, GPS, RTSP e outras features avançadas são uma incógnita. Em contrapartida, quase todos (senão todos) aparelhos Android possuem Bluetooth, GPS, A-GPS, suporte a grande quantidade de sensores, dentre outros.
Interface de Usuário
Quem trabalha com Java ME a um bom tempo sabe do que estou falando, as opções para criar a UI dos aplicativos são escassas e ineficazes no mundo atual:
  • Itens prontos: existem quase duas dezenas deles, como o LabelField, o DateField e o TextField por exemplo. Quem define o comportamento gráfico dos componentes é a fabricante do aparelho, ou seja, quem realmente implementa o suporte a Java ME no hardware. Resumindo, o programador não pode exigir que o DateFieldtenha um fundo azul por exemplo, ou que a o texto tenha uma borda pontilhada, esta totalmente amarrado.
  • Canvas: o programador pode fugir do problema relatado anteriormente muito fácil, utilizando o Canvas e suas diretivas gráficas. Ou seja, é o programador quem fica responsável por toda a interface de usuário. Quer um retângulo? Use o método drawRect. Quer um círculo? Use o método drawArc. Fica a cargo também do programador, as respostas a interação do usuário, como toque na tela, rolagem e tela, scroll horizontal e vertical. Utilizando o Canvas o tempo de desenvolvimento aumenta e muito. Claro, o programador fica livre para criar a UI que bem entender.
  • Frameworks e APIs extras: Outra possibilidade é utilizar alguns frameworks, como o LWUIT, ou, algumas APIs de terceiros, como o MEReport ou o MEChart. Mas isso nem sempre é possível, em alguns casos por aumentar demais o tamanho do .jar final da aplicação, as vezes porque o framework não atende suas expectativas. Existem ainda as APIs das próprias fabricantes, mas isso é uma execução sumária da portabilidade.
O Android, em contrapartida, apresenta uma quantidade muito maior de componentes de interface gráfica com uma qualidade imensamente superior. Além disso, o Eclipse para Android permite a criação de suas telas com clique-e-arraste, ou, com a definição de um arquivo .xml.
Banco de dados
O banco de dados do Java ME é o RMS (Record Management System). Na verdade é um banco de dados orientado a registros, ou seja, esqueça chaves, linhas, colunas, tabelas, índices e todas as propriedades do banco de dados relacional. O que o programador tem em mãos é um inteiro que representa a identificação única do registro e, um vetor de bytes. Veja a Figura abaixo.
  
Uma forma de amenizar a complexidade é utilizar o excelente Framework Floggy. Um projeto open-source criado por brasileiros, que mascara o trabalho do RMS, permitindo o uso de um banco de dados orientado a objetos no seu aplicativo.
O Android, por sua vez, apresenta quatro opções de persistência de dados:
  • Internal Storage;
  • External Storage;
  • Shared Preferences;
  • SQLite.
Além da possibilidade de utilizar um banco de dados “de verdade” com o SQLite, o SharedPreferences pode ser de grande utilidade para os programadores. Leia o artigo “Criando Telas de Preferências em Android”, disponível aquihttp://issuu.com/ricardoogliari/docs/android_prefer_ncias.
Para que o leitor tenha uma noção exata da importância do SharedPreferences, imagine um aplicativo que tenha como configurações básicas nome, sobrenome e sexo. No Java ME, será necessário criar uma classe que gerencia a persistência e recuperação destas informações, algo como a listagem de código mostrada abaixo:
public class DataBase {

    private final static String PREFS = “dbMyPrefs”;
  public String[] getP()
    {
        try
        {
            RecordStore rsPush = RecordStore.openRecordStore(PREFS, true);
            String[] retorno = null;

            if (rsPush.getNumRecords() > 0)
            {
                retorno = new String[3];
                byte[] recData = new byte[rsPush.getRecordSize(1)];
                rsPush.getRecord(1, recData, 0);

                ByteArrayInputStream strmBytes = new ByteArrayInputStream(recData);
                DataInputStream strmDataTypes = new DataInputStream(strmBytes);

                retorno[0] = strmDataTypes.readUTF();
                retorno[1] = strmDataTypes.readUTF();
                retorno[2] = “”+strmDataTypes.readInt();

                strmBytes.close();
                strmDataTypes.close();
            }

            rsPush.closeRecordStore();
            return retorno;
        }
        catch (Exception e)
        {
            return null;
        }
    }

    public boolean insereP(String nome, String senha, int sexo) {
        try
        {
            ByteArrayOutputStream strmOutBytes = new ByteArrayOutputStream();
            DataOutputStream strmOutDataTypes = new DataOutputStream(strmOutBytes);

            byte[] record;
            strmOutDataTypes.writeUTF(nome);
            strmOutDataTypes.writeUTF(senha);
            strmOutDataTypes.writeInt(sexo);
            strmOutDataTypes.flush();
            record = strmOutBytes.toByteArray();
  RecordStore rsPush = RecordStore.openRecordStore(PREFS, true);

            if (rsPush.getNumRecords() == 0)
                rsPush.addRecord(record, 0, record.length);
            else
                rsPush.setRecord(1, record, 0, record.length);

            strmOutBytes.close();
            strmOutDataTypes.close();
 rsPush.closeRecordStore();
            return true;
        }
        catch (Exception e)
        {
            return false;
        }
    }
}
 No SharedPrefence toda a lógica de persistência e recuperação dos dados é feita automaticamente. O programador precisa apenas criar a tela com os itens a serem persistidos e pronto.
Algo muito perto disso:
  • Definição da interface:
 <?xml version=“1.0″ encoding=“utf-8″?>
<PreferenceScreen xmlns:android=“http://schemas.android.com/apk/res/android”>
<PreferenceCategory android:title=“Principal”>
      <EditTextPreference android:title=“Nome”
            android:key=“nome” android:summary=“@string/informeNome”
            android:dialogTitle=“@string/informeNome” />
      <EditTextPreference android:title=“Senha”
            android:key=“senha” android:summary=“Informe a sua senha”
            android:dialogTitle=“Informe a sua senha” android:password=“true” />
</PreferenceCategory>
<PreferenceCategory android:title=“Outras Preferências”>
      <ListPreference android:title=“Sexo”
            android:key=“sexo”
            android:summary=“Selecione:” android:entries=“@array/sexos”
            android:entryValues=“@array/sexosValues” />
</PreferenceCategory>
</PreferenceScreen>
 Classe que herda de PreferenceActivity

public class Preferencias extends PreferenceActivity {
    @Override
      protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            addPreferencesFromResource(R.layout.preferences);
      }
}
Geolocalização
Para criar um aplicativo de geolocalização em Java ME o programador tem que responder mentalmente algumas questões:
  • O aparelho tem algum método de geolocalização acessível pelo Java?
  • Se sim, o aparelho tem a JSR 179 (Java Location API)?
    • Se tiver o pacote opcional o trabalho se torna menos árduo, senão, uma das possibilidades é utilizar os dados de posição da célula. Para isso, basta recuperar as informações de MNC, MCC e LAC e inseri-las na chamada web para um serviço do OpenCellID, que retorna a posição geográfica da célula onde o aparelho está alocado naquele momento. Para saber mais sobre este processo leia o artigo “Aplicativos LBS para Java ME”, disponível aqui http://infogps.uol.com.br/blog/2010/09/30/aplicativos-lbs-para-java-me/, ou, veja os slides da apresentação “Utilizando o Cell ID para Popularizar os Sistemas LBS”, disponível aqui http://www.slideshare.net/ricardoogliari/utilizando-o-cell-id-para-popularizar-os-sistemas-lbs.

Para o Android, basta dizer que tem integração com o Google Maps. Basta um .xml de 8 linhas e mais 7 linhas de código para criar o mapa da Figura abaixo:

mapa = (MapView) findViewById(R.id.mapa);
controlador = mapa.getController();
controlador.setCenter(new Ponto(-23.550739, -46.634162));
controlador.setZoom(15);
 
Com apenas mais uma linha:
mapa.setBuiltInZoomControls(true);
Adicionamos um controle de zoom estilizado:
 

Podemos mudar facilmente entre os modos street e satellite
mapa.setSatellite(true);
mapa.setStreetView(false);
Para saber mais sobre a utilização de mapas e geolocalização no Android, leia o texto “Aprenda LBS em Android na Prática – Parte 1”, disponível aqui http://issuu.com/ricardoogliari/docs/aprenda_lbs_em_android_na_pr_tica.
Dados do Aparelho
Ler dados no aparelho, como informações sobre contatos, também é incrivelmente mais simples com Android. Indico a leitura do texto citado no parágrafo anterior.
No Java ME teríamos que verificar a existência da PIM API para ter acesso a algumas informações pessoais no aparelho. Mesmo que o aparelho tivesse esta API, a assinatura do .jar seria bem vinda, caso contrário, o usuário receberia diversas vezes um questionamento requisitando a permissão para acesso aos dados do aparelho. Quem já assinou um aplicativo Java ME sabe a tortura que é.
No Android, além do código de leitura, basta a inserção da tag uses-permission dentro do AndroidManifest.xml:
<uses-permission android:name=”android.permission.READ_CONTACTS” />
Com isso, o usuário será questionado apenas uma vez sobre a permissão de leitura dos contatos do seu smartphone na instalação do aplicativo. Além disso, como citado anteriormente, o Android permite a leitura dos dados de diversos eventos e sensores presentes no aparelho, de forma muito fácil.
Internacionalização
Como é feita a internacionalização de um aplicativo Java ME? Muito simples, basta usar a Mobile Internationalization API(JSR-238). Agora tente encontrar esta API disponível em algum telefone celular. Eu fiz esta mesma pesquisa durante horas nos sites da Sony, Nokia e Samsung, e não encontrei.
O LWUIT fornece uma maneira de internacionalizar seu aplicativo, porém, você ficará preso a este framework. Com o Java ME “puro” não existe maneira de conseguir isso, ou seja, é necessária a criação de várias versões do mesmo aplicativo. Um para cada linguagem desejada.
E no Android? Quando criamos um projeto no Eclipse, automaticamente é criada uma pasta res, dentro da mesma, uma pasta values onde encontramos a strings.xml. Neste XML temos todos os textos usados no programa. Para internacionalizar, basta criar versões desta pasta seguidas por um hífen e o código do país. Em algumas IDE, como é o caso do MOTODEV Studio for Android (Figura abaixo) você nem precisa trabalhar com XML, basta editar os textos em uma janela da própria IDE. Veja a aba i18N; logo abaixo temos as versões de values e os textos traduzidos.
 
Só isso já é suficiente. Em tempo de execução o Android verifica qual a linguagem configurada no aparelho e trabalha com os textos especificados no values correspondente. Não é fantástico?
Text to Speech
A tarefa de transformar texto pra voz no Java ME até deve ser possível, mas deve dar um trabalho dantesco. Imagino que devam ser criados inúmeros pedaços de áudio, cada um com um fonema da língua desejada. Posteriormente, faz-se o parser do texto, separando em cada fonema. Por último, utiliza-se a Mobile Media API para juntar e tocar todos os fonemas.
Se o leitor souber o jeito correto, e não for este descrito por mim, fique a vontade para comentar.
E Android? Basta estas linhas de código:

public void fala() {
  Intent checkIntent = new Intent();
  checkIntent.setAction(TextToSpeech.Engine.ACTION_CHECK_TTS_DATA);
  startActivityForResult(checkIntent, 0);
  tts = new TextToSpeech(thisthis);
}

@Override
public void onInit(int status) {
  tts.setLanguage(Locale.US);
  tts.speak(“Android is sensational”, TextToSpeech.QUEUE_FLUSHnull);
}

Perceba que podemos inclusive definir em qual língua o aplicativo vai “falar”, no método setLanguage(). Além disso, sua Activity deve implementar OnInitListener.

public class TTSActivity extends Activity implements OnInitListener {

Para finalizar
Mostrei também as possibilidades do Android, sua presença em automóveis, aparelhos domésticos como microondas e lava-louças. Essa tendência só tende a ficar mais forte, ainda mais com o recente suporte do Android a Arduino.

Nenhum comentário:

Postar um comentário