Fluxo de trabalho da WebView

Publicado em 28 de fevereiro de 2014

Uma das grandes vantagens do desenvolvimento da Web é o rico conjunto de ferramentas que você pode usar para melhorar seu fluxo de trabalho.

Um exemplo de uma dessas ferramentas é o Grunt, um executor de tarefas JavaScript que permite definir tarefas a serem realizadas no seu app da Web, desde a compilação do Sass e a inicialização de um servidor ativo até a compactação de imagens, a minificação de JavaScript e a execução do JSHint antes de criar um build pronto para produção.

O Yeoman é uma ferramenta que ajuda a criar aplicativos da Web, gerando boilerplate, trazendo bibliotecas do Bower e do npm e criando um arquivo Grunt com tarefas predefinidas.

Neste tutorial, você vai usar o Yeoman para criar um novo aplicativo da Web básico e, em seguida, integrar o sistema de build do Android Studio (Gradle) com o Grunt para criar o aplicativo da Web. Você também vai configurar tarefas do Grunt para iniciar um servidor de recarga em tempo real local para testar seu aplicativo no navegador, para que não seja necessário atualizar manualmente a página toda vez que você mudar um arquivo HTML, CSS ou JavaScript.

Pré-requisitos

Antes de começar, você precisa instalar alguns pré-requisitos:

  1. Instale o Yeoman: https://github.com/yeoman/yeoman/wiki/Getting-Started
  2. Instale o Android Studio: https://developer.android.com/sdk/installing/studio.html

Etapa 1. Criar um novo projeto no Android Studio com uma WebView

Confira instruções completas sobre como fazer isso no guia de início.

Etapa 2. Criar um subdiretório para o conteúdo do app da Web

Depois de criar o projeto, crie um novo diretório de nível superior. No Android Studio, clique com o botão direito do mouse na pasta do projeto e selecione New > Directory.

Nomeie o diretório como webapp.

Etapa 3. Criar um projeto Yeoman no novo diretório

Em um terminal, cd para o diretório webapp no projeto.

cd <path-to-project>/webapp/

Em seguida, crie um novo app da Web com o Yeoman:

yo webapp

Siga as instruções na tela para selecionar as opções do projeto. Talvez seja necessário executar sudo npm install, dependendo de como o npm está instalado na sua máquina.

Antes de passar para a próxima etapa, teste o app executando o seguinte comando:

grunt server

Uma nova guia será aberta no navegador, conectando-se a um servidor local iniciado pelo Grunt. Se você mudar um dos arquivos HTML, CSS ou JavaScript no projeto, a página será recarregada e atualizada automaticamente.

Se você executar grunt build, um novo diretório, dist, será criado, e seu app da Web será compactado, otimizado e transformado em uma versão pronta para produção dentro desse diretório.

Etapa 4. Configurar o build do Gradle

No diretório webapp, crie um arquivo com o nome build.gradle.

No novo arquivo build.gradle, adicione o seguinte:

import org.apache.tools.ant.taskdefs.condition.Os

task buildWebApp(type: Exec) {
  executable = Os.isFamily(Os.FAMILY_WINDOWS) ? "grunt.cmd" : "grunt"
  args = ["build"]
}

Isso cria uma nova tarefa chamada buildWebApp com um tipo predefinido Exec. Em seguida, defina a variável executable em Exec para o comando grunt relevante, dependendo do SO atual. args são definidos como "build", o que equivale a grunt build sendo executado na linha de comando. Por fim, a importação na parte de cima é para usar Os.isFamily(Os.FAMILY_WINDOWS).

Antes de usar essa nova tarefa, precisamos informar o projeto sobre o novo arquivo build.gradle.

Abra settings.gradle no diretório raiz e adicione esta linha:

include ':webapp'

Etapa 5. Criar o app da Web ao criar o app Android

Crie o app da Web e copie-o para o diretório assets do nosso app Android.

Copie o seguinte no arquivo build.gradle dos apps Android:

task copyWebApplication(type: Copy) {
  from '../webapp/dist'
  into 'src/main/assets/www'
}

task deleteWebApplication(type: Delete) {
  delete 'src/main/assets/www'
}

copyWebApplication.dependsOn ':webapp:buildWebApp'
copyWebApplication.dependsOn deleteWebApplication

android.applicationVariants.all { variant ->
  tasks.getByPath(":${project.name}:assemble${variant.buildType.name.capitalize()}").dependsOn copyWebApplication
}

Vamos examinar cada parte disso.

tarefa copyWebApplication

task copyWebApplication(type: Copy) {
  from '../webapp/dist'
  into 'src/main/assets/www'
}

Essa tarefa Copy copia seu aplicativo do diretório webapp/dist. Queremos copiar os arquivos para src/main/assets/www. Essa tarefa também cria a estrutura de arquivos necessária se algum dos diretórios necessários não existir.

task deleteWebApplication

task deleteWebApplication(type: Delete) {
  delete 'src/main/assets/www'
}

Essa tarefa exclui todos os arquivos no diretório assets/www.

copyWebApplication.dependsOn

copyWebApplication.dependsOn ':webapp:buildWebApp'
copyWebApplication.dependsOn deleteWebApplication

A primeira linha indica que o copyWebApplication tem uma dependência da tarefa buildWebApp do arquivo build.gradle do app da Web.

A segunda linha indica que há uma dependência na tarefa deleteWebApplication.

Em outras palavras, antes de copiar arquivos para o diretório assets, crie o app da Web e exclua o conteúdo atual do diretório assets.

android.applicationVariants.all

android.applicationVariants.all { variant ->
  tasks.getByPath(":${project.name}:assemble${variant.buildType.name.capitalize()}").dependsOn copyWebApplication
}

Essa tarefa especifica as dependências de todos os builds do projeto para cada versão do app. Ela define uma dependência nas tarefas assemble para executar copyWebApplication.

As tarefas assemble montam a saída do projeto. Portanto, o app da Web precisa ser copiado para o projeto do Android primeiro.

Etapa 6. Verificar se tudo funciona

No Android Studio, não deve haver um diretório assets na pasta src dos aplicativos Android.

Defina a WebView para usar a página index.html:

mWebView.loadUrl("file:///android_asset/www/index.html");

Clique em Run e deixe o aplicativo ser criado. Você vai encontrar um diretório assets com seu aplicativo da Web no subdiretório www.

Etapa 7: Criar um servidor e uma recarga em tempo real

O recarregamento em tempo real pode ser muito útil para fazer mudanças rápidas nos seus aplicativos da Web. Para ativar isso, crie dois "sabores de produto" para o app: uma versão ativa do servidor e uma versão estática, em que o conteúdo da Web é empacotado no aplicativo Android.

No build.gradle do app Android, adicione as linhas abaixo no final do elemento android:

android {
  ...
  defaultConfig {
    ...
  }
  productFlavors {
    staticbuild {
      packageName "com.google.chrome.myapplication"
    }

    liveserver {
      packageName "com.google.chrome.myapplication.liveserver"
    }
  }

}

O Gradle agora oferece a capacidade de criar uma versão do app com um nome de pacote do liveserver e outro com o nome de pacote normal. Para verificar se funcionou, clique em Sync Project with Gradle Files (na barra de cima, ao lado do botão Run).

Em seguida, confira as Build Variants, que estão no canto inferior esquerdo do Android Studio e mostram basicamente quais versões do app você pode criar.

Para cada productFlavor, há versões Debug e Release, que o Plug-in do Android para Gradle oferece por padrão. Isso determina se o build precisa ser um build de depuração ou de lançamento adequado para implantação na Play Store.

Agora você tem duas versões, mas elas ainda não fazem nada diferente.

Etapa 8. Carregar de um servidor ativo

Agora, configure seu aplicativo para carregar um URL diferente, dependendo do tipo de produto criado.

No seu app Android, os arquivos comuns a todos os sabores do produto ficam em src/main. Para adicionar códigos ou recursos específicos a um tipo de produto, crie outro diretório em src com o mesmo nome do productFlavor. Quando você cria para essa variante de build, o Gradle e o plug-in do Android mesclam esses arquivos adicionais sobre os arquivos em src/main.

Defina o URL como um recurso de string e use esse recurso no código em vez de um URL fixado.

  1. Crie as pastas src/liveserver e src/staticbuild.

  2. Na pasta liveserver, crie uma nova pasta com o nome res e uma subpasta chamada values. Dentro dele, crie um arquivo chamado config.xml. Repita esse processo para a pasta staticbuild.

  3. Nos arquivos de configuração, adicione as seguintes linhas a src/liveserver/res/values/config.xml:

    <?xml version="1.0" encoding="utf-8"?>
    <resources>
      <string name="init_url">https://<Your Local Machine IP Address>:9000</string>
    </resources>
    

    Adicione o seguinte bloco a src/staticbuild/res/values/config.xml:

    <?xml version="1.0" encoding="utf-8"?>
    <resources>
      <string name="init_url">file:///android_asset/www/index.html</string>
    </resources>
    
  4. Defina a WebView para usar o init_url desses arquivos de configuração.

    mWebView.loadUrl(getString(R.string.init_url));
    
  5. Crie um novo arquivo chamado AndroidManifest.xml em liveserver/AndroidManifest.xml e adicione as seguintes linhas:

    <?xml version="1.0" encoding="utf-8"?>
    <manifest xmlns:android="https://schemas.android.com/apk/res/android">
      <uses-permission android:name="android.permission.INTERNET" />
    </manifest>
    

    Isso adiciona a permissão de Internet para os builds liveserver.

  6. Dentro de webapp/Gruntfile.js, procure:

    connect: {
      options: {
        port: 9000,
        livereload: 35729,
        // change this to '0.0.0.0' to access the server from outside
        hostname: **'localhost'**
      },
      ...
    }
    

    Substitua localhost por 0.0.0.0 para que o servidor local seja acessível pela rede local:

    connect: {
      options: {
        port: 9000,
        livereload: 35729,
        // change this to '0.0.0.0' to access the server from outside
        hostname: '**0.0.0.0'**
      },
      ...
    }
    

Para testar as mudanças:

  1. Inicie o servidor ao vivo:

    grunt server
    
  2. No Android Studio, na seleção Build Variant, selecione LiveserverDebug. Em seguida, clique em Executar.

    Você poderá editar o conteúdo HTML, CSS e JavaScript e conferir as alterações imediatamente no navegador.

Agora você tem duas versões do aplicativo: uma versão de desenvolvimento com recarga ao vivo do servidor do Grunt e uma versão estática, empacotada localmente no app Android.