Portando o Web App Counting Beads para o Android* usando o PhoneGap* e para a loja de aplicativos do Windows 8*

Índice

  1. Introducão

  2. Portando para o Microsoft* Internet Explorer* 9

  3. Tratando o Redimensionamento da Janela do Navegador e Diferentes Tamanhos de Dispositivos

  4. Inicialização de App no PhoneGap

  5. Portando para Dispositivos Android

  6. Portando para a loja de aplicativos do Windows 8

Introdução

O app Counting Beadsé originalmente um app web em HTML5 disponível no site de desenvolvedores do Tizen*. O app foi criado usando HTML5, JavaScript, CSS3 e jQuery*. Ele possui as seguintes características:

  • Funciona apenas no navegador no Google* Chrome*  - Não funciona em dispositivos Android* como um app PhoneGap*
  • Usa CSS media query para diferentes layouts em diferentes dispositivos
  • Posições absolutas são utilizadas para todos os elementos do layout

O app é um jogo educacional simples para crianças, para ensinar como contar. Um "toque" nas bolinhas fará com que elas se movam para o outro lado. Quando o numero de bolinhas daquela cor alcançar o número mostrado do lado esquerdo, ele mostrará uma mensagem de saudação na caixa numérica ou um "*" em telas de dispositivos menores.

Este artigo explica o processo e os problemas encontrados quando a aplicação web original foi portada para uma aplicação móvel.

As metas para o port são:

  • Executar em um dispositivo Google Android: testado em smartphones Samsung* Galaxy* S2  & Google* Nexus*
  • Executar em um tablet com o Windows 8*: testado em um tablet Microsoft* (BUILD)

As imagens abaixo são da tela de introdução antes e depois do port para o Microsoft* Internet Explorer* 9 (IE9).

in IE9 before
Antes do port

 

in IE9 after
Depois do port

 

Abaixo estão as imagens do jogo depois do port para o IE9 (antes do port você não podia chegar a esta parte do jogo, pois o botão [start] não era mostrado):

Counting Beads Ported to IE 9

Portando para o Microsoft* Internet Explorer* 9

Para portar o app Counting Beads para ser um app da loja do Windows 8, a primeira coisa é portar a aplicação para que ela possa ser executada pelo Internet Explorer 9.

Além de trocar todas as posições absolutas por posições relativas, o que é um trabalho tedioso de desenvolvimento e testes, algumas imcompatibilidades importantes foram encontradas:

  1. -webkit-mask-image
    Na tela de abertura, existe um logotipo que é mostrado usando "-webkit-mask-image" originalmente. Ele teve que ser substituído por "background-image". O resultado final não é tão bom quando comparado à versão do Chrome, mas ele mostra o logotipo em vez de mostrar um quadro em branco. 
    Você pode ver as diferenças abaixo:

     

    original logo img

    No Chrome

     

    modified logo img
    No IE9

  2. "z" index
    "z" não é reconhecido pelo IE9, substituíndo-o por "z-index" funcionou.
  3. Suporte a dataset do HTML5
    Dataset HTML5 não é suportado pelo IE9, mas isso não foi detectado por nenhuma ferramenta de validação. Por isso era difícil de isolar. Nós usamos as ferramentas do desenvolvedor do IE9 para identificar o problema. A correção é relativamente simples, como mostrado abaixo:
    Um lugar era na função "populateBars(fromPage)" dentro do arquivo countingBeads.js:
    Código original: 
    		function handleBeadClick(event)
    {
    	var target = event.target;
    	var row = target.dataset.x;
    	var col = target.dataset.y;
        ......
    }
    
    		
    Código modificado:
    		function handleBeadClick(event)
    {
        var target = event.target;
        var row;
        var col;
        if(target.dataset) {
    	    row = target.dataset.x;
    	    col = target.dataset.y;
        } else {
    	    row = target.getAttribute('data-x');
    	    col = target.getAttribute('data-y');
        }
        ......
    }
    
    		

Durante o port, as seguintes ferramentas foram muito úteis:

  • IE9 developer tools

Tratando o Redimensionamento da Janela do Navegador e Diferentes Tamanhos de Dispositivos

O CSS media query é maravilhoso para o ajuste do layout de acordo com diferentes tamanhos de janelas de navegador. Mas as bolinhas são desenhadas dinamicamente no JavaScript. Então nós precisávamos detectar os eventos de redimensionamento de janela e desenhar as bolinhas. Nós só queremos tratar o último evento de redimensionamento da janela do navegador quando ela for redimensionada. Ainda bem que encontramos este excelente pequeno plugin do jQuery chamado jQuery throttle & debounce plugin, criado por Ben Alman. Com este plugin, tudo o que precisamos fazer é tratar o último evento de redimensionamento. Isto é muito simples. O mesmo código funciona quando a orientação do dispositivo é realizada.

Primeiro inclua a biblioteca do plugin no seu "index.html" depois do jquery:

    <script type="text/javascript" src="js/jquery-1.7.2.min.js"></script>
    <script type="text/javascript" src="js/jquery.ba-throttle-debounce.js"></script>


Então, na função de inicialização "init()" defina o handler do evento de redimensionamento usando o debounce, como é mostrado abaixo:

function init() 
{
    if (init_done)
        return; 
    init_done = true; 

    $(window).resize($.debounce(250, handleResizeWin));
    ......
}


 

 

Inicialização de um App PhoneGap

O exemplo original é um web app, portanto a inicialização dos dados é feita quando o evento document ready é disparado. Ex:

$(document).ready(function()
{
	init();
});


Mas para um app PhoneGap, a inicialização dos dados deve ser feita através do evento "deviceready" do PhoneGap.

document.addEventListener("deviceready", onDeviceReady, false);
function onDeviceReady() {
    console.log("onDeviceReady: Phonegap version " + window.device.cordova);
	init();
}


Isto causa um problema, porque você nunca sabe qual evento é disparado primeiro, o evento "deviceready" do PhoneGap ou o evento document ready.

 

O que fizemos não é perfeito e assim que descobrimos um mecanismo melhor, iremos atualizar este artigo. Por enquanto, use um setTimeout no evento document ready, como abaixo:

 

$(document).ready(function()
{
    console.log("*****document.ready and init.");

    // chama a init() para inicializar os dados
    // ela deve ser chamada somente uma vez. 
    // Mas quando estiver usando o PhoneGap, o evento "DeviceReady" é geralmente disparado depois dessa chamada. Então use o setTimeout().
    setTimeout("init()", 1000);
});


 

 

Portando para Dispositivos Android

Duranyte o port, encontramos muitos problemas e todos eles com excessão de apenas um foram contornados:

  1. A tag audio do html5 audio não é suportada pelos dispositivos Android testados.
    Talvez isso seja alterado no futuro, mas atualmente nós utilizamos o objeto media do PhoneGap para reproduzir a música.
    		if (window.device) // if phonegap is used: 
    {
        if (phoneCheck.android) // android
            this.mediaobj = new Media("/android_asset/www/audiomp3/" + id + ".mp3", this.mediaCallSuccess, this.mediaCallError);
    } else
        this.mediaobj = document.getElementById(id);
    
    		
  2. A tag de audio do html5 suporta o loop, mas o objeto de media PhoneGap, não.
    No index.html, a música da tela de introdução é reproduzida em loop. Mas não existe nenhuma funcionalidade equivalente no PhoneGap 2.0 que faça a mesma coisa. Então quando a App é executada em um dispositivo Android, a música da tela de introdução é reproduzida apenas uma vez. Esperamos que versões futuras do PhoneGap suportem a funcionalidade de loop, ou melhor ainda, que o webkit dentro do Android suporte a tag de áudio. 
    		<audio id="introMusicLoop" loop="true" preload="auto"><source src="audiomp3/introMusicLoop.mp3" type="audio/mp3" /></audio>
    
    		
  3. A tag iframe está causando problemas em dispositivos Android. 
    Esta app possui uma página de licença que é mostrada usando a tag "iframe". Ela funciona bem dentro de um navegador, mas não está funcionando dentro de dispositivos Android como um app PhoneGap. 
    No Google Nexus, o app irá parar a execução na tela de introdução; e no Samsung* Galaxy* S2, o app funciona, mas se você clicar no botão da licença, o botão desaparece.
    Por isso o "iframe" foi removido do "index.html" e é adicionado dinamicamente através de JavaScript quando o app é executado em um navegador. Quando o app for executado como um app PhoneGap, ele usa a função .get do jQuery: 
    		function loadLicenseTxt() {
        if (typeof window.device !== "undefined") { // executando no PhoneGap
    
            $.get('README.txt', function (data) {
                var divLicense = document.getElementById("licensetext");
                divLicense.innerText = data;
            });
        }  else {
            // executando em um navegador como um web app, então use um iframe para mostrar o README.txt
            console.log("***Test: read README.txt iframe");
    
            var licPage = document.getElementById("licensepage");
            var licEle = document.getElementById("licensetext");
    
            var frmEle = document.createElement("iframe");
    
            // Web page 
            frmEle.setAttribute("src", "README.txt");
    
            frmEle.style.height = window.innerHeight * 0.88 + "px";
            frmEle.style.width = window.innerWidth * 0.995 + "px";
    
            licPage.replaceChild(frmEle, licEle);
    
            frmEle.setAttribute('id', "licensetext");
        }
    }
    		
    Mesmo que o código possa ser simplificado para usar um "$.get()", para mantê-lo como o app original no navegador Chrome, o "iframe" continua a ser usado, mas dinamicamente.

Portando para a Loja de Aplicativos do Windows 8

Portar para a loja de aplicativos do Windows 8 não é difícil, uma vez que a aplicação já foi portada para o IE9. Nós usamos o Visual Studio 2012 (professional) em uma máquina com o Windows 8. Por favor consulte a Microsoft MSDN Get the tools (Windows Store apps) para informações detalhadas sobre as ferramentas.

Fazer um build para a loja de aplicativos do Windows 8 possui certos requisitos, mas se você iniciar pelos tipos de projetos fornecidos pelo Visual Studio 2012, ele cria por padrão os seguintes arquivos de imagens com os tamanhos requeridos: 

nome do arquivo de imagem

tamanho requerido de imagem

logo.png 150 x 150px
smalllogo.png 30 x 30px
storelogo.png 50 x 50px
splashscreen.png 620 x 300px

Estes são os passoas para fazer o build do app CountingBeads no Windows 8:

  1. Crie um novo projeto JavaScript "BlankApp"
    Ele cria um projeto JavaScript com conteúdo vazio e diversos arquivos padrão.
  2. Renomeie o arquivo "default.html" para "index.html"
    "default.html" é a página de entrada criada por padrão. Altere o nome com um clique no botão direito do mouse em cima do nome do arquivo, selecionando "renomear".
  3. Defina a página inicial para "index.html" para o pacote 
    Dê um clique duplo no arquivo "package.appxmanifest" e ele vai abrir com o editor de manifest; altere a "Start page" de "default.html" para "index.hmtl":
    start page name
  4. Remova os arquivos que não são necessários: default.css & default.js
  5. Copie os arquivos do CountingBeads para o raiz do diretório do projeto
  6. Adicione os arquivos do CountingBeads:
    Isso leva algum tempo, porque todos os diretórios e arquivos precisam ser adicionados para que possam ser empacotados.
  7. Atualize as images com as imagens do CountingBeads: logo.png, smalllogo.png, spashscreen.png e storelogo.png
  8. Clique em executar na "Máquina Local"

Esta página da MSDN Create your first Windows Store app using JavaScript pode ser útil para você.

Como leva algum tempo para adicionar todos os diretórios e arquivos ao projeto, nós incluimos os arquivos de projeto do Visual Studio 2012* para a sua conveniência. Se quiser testa-lo, siga os passos abaixo:

  1. Copie os arquivos de projeto abaixo de win8-proj para o diretório raiz
  2. Abra o HTML5_CountingBeads.jsproj com o Visual Studio 2012, e execute através da IDE
Para obter informações mais completas sobre otimizações do compilador, consulte nosso aviso de otimização.