Uma Pequena Nuvem em Android

Explorando o sistema de arquivos Android a partir do seu navegador

A computação em nuvem necessita minimamente de dois componentes: o software cliente que é executado em um dispositivo móvel e o software servidor que normalmente é executado em um servidor de rede. Este artigo propõe a criação de um serviço baseado em Android que emula um servidor de rede que aprimora o valor da máquina local de maneiras exclusivas e inesperadas. Coloque uma pequena nuvem no seu telefone portátil Android e experimente o benefício de um servidor da Web local.

Bill Zimmerly , Freelance Writer and Knowledge Engineer, Author

Photo of Bill ZimmerlyBill Zimmerly é um engenheiro de conhecimento, um programador de sistemas de nível inferior e especialista em diversas versões do UNIX e do Microsoft® Windows® e um pensador livre que reverencia o altar da Lógica. Bill também é conhecido como uma pessoa irracional. Irracional como em: "Pessoas sensatas adaptam-se ao mundo. Pessoas irracionais tentam adaptar o mundo a elas. Todo o progresso, portanto, depende das pessoas irracionais" (George Bernard Shaw). Criar novas tecnologias e escrever sobre elas são suas paixões. Ele reside na região rural de Hillsboro, Missouri, onde o ar é fresco, as paisagens inspiradoras e boas vinícolas estão por toda a parte. Não há nada como escrever um artigo sobre shell script do UNIX enquanto se saboreia um copo claro como cristal de Stone Hill Blush. Ele pode ser contatado em bill@zimmerly.com.



16/Dez/2009

Android é uma distribuição especial do sistema operacional Linux® , projetado para gerenciar o tipo de funcionalidade que você espera no mais inteligente dos telefones inteligentes. Para um programador, tudo no Linux — um dispositivo, uma planilha ou uma música favorita — aparece como um arquivo. Isto é, existe um conjunto comum de maneiras para abrir, extrair, manipular e salvar o conteúdo das informações dessas entidades diversas e abstratas. E essa semelhança forma o princípio núcleo da filosofia UNIX® : tudo é um arquivo.

Acrônimos frequentemente usados

  • MIME: Multipurpose Internet Mail Extension
  • HTML: Linguagem de Marcação de Hipertexto
  • SDK: Kit de desenvolvimento de software
  • WWW: World Wide Web

Os arquivos são agrupados em hierarquias úteis chamadas sistemas de arquivos. Um telefone celular Android normalmente tem dois sistemas de arquivos: a memória não volátil do telefone celular e o cartão SD plugado nele. Ambos aparecem como ramificações do diretório-raiz (/). Uma ferramenta que possibilita navegar comodamente por esses sistemas de arquivos a partir do seu navegador poderia provar-se útil. Este projeto define um pequeno programa, escrito na linguagem nativa do C, que se comunica como um servidor da Web e possibilita que você navegue pelo sistema de arquivos do telefone celular Android a partir da sua estação de trabalho ou diretamente do navegador integrado do próprio telefone celular. Ele fornece páginas com hyperlinks que possibilitam que você mova para cima e para baixo na árvore hierárquica. Ao clicar em vários tipos de arquivo listados, é possível visualizar os itens individuais.

Configurando o ambiente de desenvolvimento

Primeiro, certifique-se de que você tenha um telefone celular Android "destravado" para que você possa fazer coisas com executar o Terminal e executar o comando su para obter privilégios de administrador. Se você não sabe como "destravar" seu telefone Android e obter esses privilégios, uma rápida busca na Internet deve dar a você o que precisa. (Observe que este processo, às vezes, é chamado de fazer jail-breaking no seu telefone. Consulte Recursos para obter links sobre como fazer isso.)

A comunidade Android primariamente usa dois SDKs. O mais conhecido é o Android SDK de alto nível, que possibilita escrever código do aplicativo na linguagem Java™ e comumente usa o Eclipse para escrever, testar e depurar código. Outro SDK, menos conhecido, é a origem do kernel Android, que é armazenado no que é conhecido com um repositório git . (Para obter links para este repositório, consulte Recursos.)

Como o foco deste artigo é a criação de um serviço da Web de baixo nível que tipicamente residirá no diretório do sistema/bin do seu telefone celular, é importante fazer o download e instalar o código de origem do kernel Android inteiro e as ferramentas GNU usadas para construí-lo. A página inicial do projeto Origem do Kernel Android (consulte Recursos) fornece instruções simples para fazer o download da plataforma inteira com um script chamado repo.

O pequeno software em nuvem terá compilação cruzada com a plataforma ARM na sua estação de trabalho, assim, certifique-se de que todas as ferramentas necessárias estejam instaladas. Usando apt-get, instale essas ferramentas como mostrado na Lista 1.

Lista 1. Instalando ferramentas de compilação cruzada
    $ sudo apt-get install git-core gnupg \
    sun-java5-jdk flex bison gperf libsdl-dev \
    libesd0-dev libwxgtk2.6-dev build-essential \
    zip curl libncurses5-dev zlib1g-dev

Estrutura de diretório de desenvolvimento

Use o nome de diretório mydroid para instalar a origem do kernel Android. Este nome faz com que um diretório-raiz efetivo trabalha de fora, assim, acesse seu diretório inicial e emita um comando mkdir mydroid . Depois, use cd mydroid e emita o comando repo sync lá.

Após o comando repo sync ter transferido por download todo o código de origem do Android para o seu diretório mydriod, alguns poucos diretórios que valem a pena ser mencionados que foram criados incluem:

  • Você criará o diretório em nuvem dentro do mydroid/externo. O código de origem para este projeto (cloud.c) residirá aqui.
  • Após o comando de longa execução make construir o sistema Android, você encontrará a nuvem do arquivo binário dentro do diretório out/target/product/generic/system/bin.

O projeto em nuvem do Android

Quando o programa em nuvem iniciar, ele imediatamente verificará se quaisquer parâmetros de linha de comandos foram passados para ele. Os dois parâmetros que são opcionalmente esperados são a porta para monitorar e o diretório inicial no qual iniciar. Se nenhum parâmetro for especificado, o programa assume como padrão o uso da porta padrão 80, e o diretório inicial padrão é qualquer que fosse o diretório funcional quando o programa foi iniciado.

Após a inicialização, o programa inicializa o soquete TCP/IP para "atender" chamadas para ele através da porta mencionada acima, depois transforma-se em um processo daemon, aguardando pelas chamadas do navegador e atendendo a elas. Quando um navegador chama a "página" padrão deste pequeno servidor em nuvem, o código responde retornando uma lista de diretórios do diretório "inicial" mencionado acima. Nomes de arquivo são listados com ou sem um hyperlink, dependendo se eles são um tipo de arquivo conhecido ou diretório. Ser um tipo de arquivo conhecido significa (no mundo da WWW) que o arquivo tem um tipo MIME correspondente. Por exemplo, bem no fundo do telefone celular Android, os tons de toque de áudio estão armazenados como arquivos .ogg. O áudio/ogg do tipo MIME diz ao navegador para reproduzir o arquivo no alto-falante, supondo-se que o seu navegador foi configurado corretamente para fazer isso.

Outro hyperlink que aparece na parte superior das listas de arquivos é o Diretório-Pai. Clicar neste link permite mover para cima na hierarquia do sistema de arquivos até que você eventualmente chegue o mais alto possível: no diretório-raiz. Ao longo do caminho, outros nomes de subdiretórios aparecem como hyperlinks; se você clicar neles, irá para baixo nesse subdiretório para explorar os arquivos contidos nele.

Assim, o aplicativo em nuvem é um programa útil para comodamente explorar o sistema de arquivos do telefone celular, e o código de origem (consulte Download) fornece um bom modelo de funcionalidade que você pode modificar como melhor se ajustar. Maneiras sugeridas para modificar o código aparecem no final deste artigo. (Também é possível compilar o código e executá-lo em sua estação de trabalho, possibilitando que você também navegue nos sistemas de arquivos da estação de trabalho. Para obter instruções sobre como fazer isso, consulte Recursos.)


O código de origem C

Cada código de origem do programa deve mostrar, pelo menos, o nome e o autor do programa. A Lista 2 mostra a atribuição, os arquivos de inclusão dos quais você usará as definições e algumas constantes úteis.

Lista 2. Atribuição, inclusões e constantes úteis
    // Aplicativo em Nuvem Android por Bill Zimmerly.
    // Baseado no "NWEB" por Nigel Griffiths.

    #include <dirent.h>
    #include <stdio.h>
    #include <stdlib.h>
    #include <unistd.h>
    #include <errno.h>
    #include <string.h>
    #include <fcntl.h>
    #include <signal.h>
    #include <sys/types.h>
    #include <sys/socket.h>
    #include <netinet/in.h>
    #include <arpa/inet.h>

    #define TRUE      -1
    #define FALSE     0
    #define SBUF      1048576
    #define LBUF      4096
    #define LAPN      64
    #define ERROR     1
    #define LOG       2
    #define LOGGING   FALSE

A Lista 3 fornece o armazenamento de funcionamento global que é acessível por todas as funções definidas neste programa. A maioria dos ponteiros do buffer são armazenamentos alocados quando um navegador chama a pequena nuvem. Após retornar o conteúdo para o navegador, a memória alocada é retornada ao telefone celular. Em computadores com recursos limitados, esta prática torna-se mais importante do que muitas outras considerações.

Lista 3. Armazenamento de funcionamento global
    char* about="</pre>Nuvem é um aplicativo simples que possibilita "
                "navegação baseada na Web do sistema de arquivos Android " 
				"e é destinada ao uso por pessoas que gostam de "
                "explorar os níveis mais baixos de seu dispositivo. Ele "
                "é executado em um telefone Android destravado e
				é destinado apenas à "
                "navegação do sistema de arquivos. Consulte o artigo do "
                "developerWorks da IBM para uma descrição completa " 
				"deste aplicativo.<pre>";
    char* mainbuf;
    char* theDir;
    char* thePort[8];
    char* theList;
    char* fstr;

    char logDir[LBUF];

    int ret;

Neste programa, uma tabela simples de extensões de arquivos mapeiam nos tipos MIME que os navegadores precisam conhecer para manipular adequadamente o conteúdo do arquivo. A estrutura na Lista 4 é usada pela função mimeokay para um propósito: configurar o ponteiro da cadeia de caracteres global fstr para o tipo MIME apropriado correspondente à extensão do arquivo: fext. Com estas informações, a pequena nuvem pode exibir o nome do arquivo com um hyperlink ou como texto simples sem um link. Ela também serve ao propósito duplo de fornecer o tipo MIME quando o conteúdo de um arquivo estiver sendo enviado para o navegador.

Lista 4. Determinando tipos MIME
    struct
    {
      char *ext;
      char *mimetype;
    }

    mimes [] =
    {
      {".htm",  "text/html"  },
      {".html", "text/html"  },
      {".xml",  "text/xml"   },
      {".gif",  "image/gif"  },
      {".jpg",  "image/jpeg" },
      {".jpeg", "image/jpeg" },
      {".png",  "image/png"  },
      {".log",  "text/plain" },
      {".conf", "text/plain" },
      {".rc",   "text/plain" },
      {".sh",   "text/plain" },
      {".prop", "text/plain" },
      {".txt",  "text/plain" },
      {".TXT",  "text/plain" },
      {".cpp",  "text/plain" },
      {".c",    "text/plain" }, 
      {".h",    "text/plain" },
      {".ogg",  "audio/ogg" },
      {0,0}
    };

    void mimeokay(char* fext)
    {
      int buflen;
      int len;
      long i;

      buflen=strlen(fext);
      fstr = (char*) 0;

      for(i=0; mimes[i].ext != 0; i++)
      {
        len = strlen(mimes[i].ext);

        if(!strncmp(&fext[buflen-len], mimes[i].ext, len))
        {
          fstr=mimes[i].mimetype;
          break;
        }
      }
    }

A Lista 5 mostra o código opcional que efetuará o log da atividade em nuvem do Android em um arquivo cloud.log durante o desenvolvimento e o teste. Como a nuvem executa em um hardware relativamente lento, é bom deixar esta funcionalidade desligada a menos que você realmente precise ver o que está acontecendo no código enquanto o estiver modificando. A constante LOGGING na Lista 1 deve ser TRUE se você desejar que essa criação de log funcione, mas deixe-a como FALSE quando ela estiver em execução no telefone celular, já que a taxa de desempenho pode ser significante.

Lista 5. Atividade de criação de log
    void aclog(int type, char *s1, char *s2, int num)
    {
      int fd ;
      char aclogbuffer[LBUF];
      char logFile[LBUF];

      if(!LOGGING)
        return;

      switch(type)
      {
        case ERROR:
          sprintf(aclogbuffer, "ERROR: %s:%s Error Number=%d, PID=%d",
                  s1, s2,
                  errno, getpid());
          break;
        case LOG:
          sprintf(aclogbuffer, "INFO: %s:%s:%d", s1, s2, num);
          break;
      }	

      strcpy(logFile, logDir);
      strcat(logFile, "/cloud.log");

      if((fd = open(logFile, O_CREAT | O_WRONLY | O_APPEND,
                    0644)) >= 0)
      {
        ret=write(fd, aclogbuffer, strlen(aclogbuffer));
        ret=write(fd, "\n", 1);
        close(fd);
      }

      if(type == ERROR)
        exit(3);
    }

A Lista 6 fornece várias funções definidas para o propósito de criação de saída de HTML da pequena nuvem. Observe que cada página de um Web site bem projetado deve manter uma aparência comum, e a função buildbuf é onde essa aparência geral é definida.

Lista 6. Gerando saída de HTML
    void apname(void)
    {
      strcat(mainbuf, "Aplicativo em Nuvem Android");
    }

    void buildbuf(char* data)
    {
      mainbuf[0]=0;
      strcat(mainbuf, "<html>\n<head>\n<title>");
      apname();
      strcat(mainbuf, "</title>\n</head>\n");
      strcat(mainbuf, "<body>\n<h3>");
      apname();
      strcat(mainbuf, "</h3>\n");
      strcat(mainbuf, "<a href=\"/About_\">About</a><br>\n");
      strcat(mainbuf, "<a href=\"/Home_\">Home</a><br>\n");
      strcat(mainbuf, "<hr>\n");
      strcat(mainbuf, "Dir: ");
      strcat(mainbuf, theDir);
      strcat(mainbuf, "<br>\n<hr>\n<pre>\n");
      strcat(mainbuf, data);
      strcat(mainbuf, "\n</pre>\n");
      strcat(mainbuf, "</body>\n</html>\n");
    }

    void htmlout(int fd, char* data)
    {
      fstr=mimes[0].mimetype;
      sprintf(mainbuf, "HTTP/1.0 200 OK\r\nContent-Type: %s\r\n\r\n", fstr);
      ret=write(fd, mainbuf, strlen(mainbuf));
      buildbuf(data);
      ret=write(fd, mainbuf, strlen(mainbuf));
    }

    void error404(int fd)
    {
      fstr=mimes[0].mimetype;
      sprintf(mainbuf, "HTTP/1.0 404 OK\r\nContent-Type: %s\r\n\r\n", fstr);
      ret=write(fd, mainbuf, strlen(mainbuf));
      buildbuf("404 Error - File not found!");
      ret=write(fd, mainbuf, strlen(mainbuf));
    }

A Lista 7 mostra como a pequena nuvem retorna o conteúdo de um arquivo com um tipo MIME definido. Observe como o navegador espera que o tipo MIME seja enviado de um servidor como uma cadeia de caracteres Content-Type: . Basta clicar nos links gerados para nuvem e esta função é chamada para retornar o conteúdo desse arquivo. Se, porém, uma alma criativa e travessa editar um nome de arquivo inválido na barra de endereços de seu navegador, a função error404 (definida acima) informará ao usuário sobre isso.

Lista 7. Retornando conteúdo de arquivo
    void retfile(int fd, int hit)
    {
      int file_fd;
      long ret;

      mimeokay(mainbuf);

      if(fstr == 0)
      {
        error404(fd);
        return;
      }

      if((file_fd = open(&mainbuf[4], O_RDONLY)) == -1)
      {
        error404(fd);
      }
      else
      {
        aclog(LOG, "SEND", &mainbuf[4], hit);

        sprintf(mainbuf, "HTTP/1.0 200 OK\r\nContent-Type: %s\r\n\r\n", fstr);
        ret=write(fd, mainbuf, strlen(mainbuf));

        while((ret=read(file_fd, mainbuf, SBUF)) > 0 )
        {
          ret=write(fd, mainbuf, ret);
        }
      }
    }

A Lista 8 mostra como a pequena nuvem constrói a lista de arquivos principal com hyperlinks. A função hyper é usada várias vezes, portanto, é prudente fatorá-la em sua própria função. O valor isDir pré-anexa o texto /CD_ antes do caminho completo para o nome do arquivo para que a pequena nuvem saiba que ela deve exibir o conteúdo desse diretório. A função fileList é verdadeiramente o coração e a alma deste aplicativo.

Lista 8. Funções da lista de diretórios
    void hyper(int isDir, char* name)
    {
      strcat(theList, "<a href=\"");

      if(isDir)
        strcat(theList, "/CD_");

      strcat(theList, (char*) theDir);

      if(strcmp(theDir, "/"))
        strcat(theList, "/");

      strcat(theList, name);
      strcat(theList, "\">");
      strcat(theList, name);
      strcat(theList, "</a>");
      strcat(theList, "\n");
    }

    char* fileList(void)
    {
      struct dirent **namelist;
      int n;
      long i;
      long j;

      theList[0]=0;

      n=scandir(".", &namelist, 0, (void*) alphasort);

      if (n < 0)
        perror("scandir");
      else
      {
        for(i=0; i<n; i++)
        {
          if(namelist[i]->d_type == DT_DIR)
          {
            if(!strcmp(namelist[i]->d_name, "."))
            {
              // strcat(theList, namelist[i]->d_name);
            }
            else if(!strcmp(namelist[i]->d_name, ".."))
            {
              if(strcmp(theDir, "/"))
              {
                strcat(theList, "<a href=\"");
                strcat(theList, "/CD_");
                strcat(theList, (char*) theDir);

                j=strlen(theList);

                while(j--)
                {
                  if(theList[j] == '/')
                  {
                    theList[j]=0;
                    j=1;
                  }
                }

                if(!strcmp(&theList[strlen(theList)-4], "/CD_"))
                {
                  strcat(theList, "/");
                }
    
                strcat(theList, "\">Parent Directory</a>");
                strcat(theList, "\n");
              }
            }
            else
              hyper(TRUE, namelist[i]->d_name);
          }
          else
          {
            mimeokay(namelist[i]->d_name);

            if(fstr == 0)
            {
              strcat(theList, namelist[i]->d_name);
              strcat(theList, "\n");
            }
            else
              hyper(FALSE, namelist[i]->d_name);
          }

          free(namelist[i]);
        }

        free(namelist);
      }

      return theList;
    }

Na Lista 9, a funcionalidade filha do servidor da pequena nuvem é definida. Esta funcionalidade é executada sempre que o servidor recebe um pedido do navegador e tem uma função simples: alocar os buffers necessários para satisfazer o pedido, processá-los e, depois, liberá-los para que a memória do sistema alocada seja mantida baixa quando não necessária. Em um telefone celular, a memória é um recurso escasso e precioso e deve ser liberada de volta ao sistema quando o programa terminar de atender a um pedido.

Lista 9. Funcionalidade filha de Daemon
    void child(int fd, int hit)
    {
      long i;
      long ret;
      char* cret;

      mainbuf=malloc(SBUF+1);
      theList=malloc(SBUF+1);
      theDir=malloc(LBUF+1);
      cret=getcwd(theDir, LBUF);

      ret=read(fd, mainbuf, SBUF);

      if(ret == 0 || ret == -1)
      {
        error404(fd);
      }
      else
      {
        if(ret > 0 && ret < SBUF)
          mainbuf[ret]=0;
        else
          mainbuf[0]=0;

        for(i=0; i<ret; i++)
          if(mainbuf[i] == '\r' || mainbuf[i] == '\n')
            mainbuf[i]='*';

        aclog(LOG, "request", mainbuf, hit);

        for(i=4; i < SBUF; i++)
        {
          if(mainbuf[i] == ' ')
          {
            mainbuf[i]=0;
            break;
          }
        }

        if(!strncmp(&mainbuf[0], "GET /\0", 6) ||
           !strncmp(&mainbuf[0], "get /\0", 6))
        {
          htmlout(fd, fileList());
        }
        else
        {
          if(!strncmp(&mainbuf[5], "About_", 6))
          {
            htmlout(fd, about);
          }
          else if(!strncmp(&mainbuf[5], "Home_", 5))
          {
            htmlout(fd, fileList());
          }
          else if(!strncmp(&mainbuf[5], "CD_", 3))
          {
            if(chdir(&mainbuf[8]) == -1)
            {
              error404(fd);
            }
            else
            {
              if(strcmp(theDir, &mainbuf[8]))
                strcpy(theDir, &mainbuf[8]);

              htmlout(fd, fileList());
            }
          }
          else
          {
            retfile(fd, hit);
          }
        }
      }

      free(theDir);
      free(theList);
      free(mainbuf);
      sleep(1);
      exit(1);
    }

A funcionalidade principal (pai) da pequena nuvem é definida na Lista 10. Ela aloca o soquete TCP/IP no qual estará atendendo chamadas de pedido do navegador. Depois, ela inicializa algumas poucas variáveis globais como theDir, onde a pequena nuvem foi iniciada. E, finalmente, ela se transforma em um programa residente (conhecido como um daemon) para que possa processar silenciosamente os pedidos do navegador no segundo plano enquanto outros processos estão sendo executados.

Lista 10. Funcionalidade principal
    int main(int argc, char **argv)
    {
      char* str;
      char* cret;

      static struct sockaddr_in cli_addr;
      static struct sockaddr_in serv_addr;

      socklen_t length;

      int i;
      int port;
      int pid;
      int listenfd;
      int socketfd;
      int hit;

      cret=getcwd(logDir, LBUF);

      if(argc < 2)
      {
        strcpy((char*) thePort, "80");
        port=atoi((char*) thePort);
      }
      else
      {
        if(!strcmp(argv[1], "-?"))
        {
          printf("Uso: nuvem [Diretório da Porta]\n");
          exit(0);
        }
        strcpy((char*) thePort, argv[1]);
        port=atoi((char*) thePort);

        if(port < 0 || port > 60000)
          aclog(ERROR, "Invalid port number (try 1 --> 60000)", argv[1], 0);

        if(chdir(argv[2]) == -1)
        {
          printf("ERRO: Diretório inválido %s\n", argv[2]);
          exit(4);
        }
      }

      if(fork() != 0)
        return 0;

      signal(SIGCHLD, SIG_IGN);
      signal(SIGHUP, SIG_IGN);
    	
      for(i=0; i<32; i++)
        close(i);
    	
      setpgrp();

      aclog(LOG, "Cloud Port/PID=", (char*) thePort, getpid());

      if((listenfd=socket(AF_INET, SOCK_STREAM, 0)) < 0)
        aclog(ERROR, "syscall", "socket", 0);
    	
      serv_addr.sin_family      = AF_INET;
      serv_addr.sin_addr.s_addr = htonl(INADDR_ANY);
      serv_addr.sin_port        = htons(port);

      if(bind(listenfd, (struct sockaddr*) &serv_addr,
              sizeof(serv_addr)) < 0)
        aclog(ERROR, "syscall", "bind", 0);

      if(listen(listenfd, 64) <0)
        aclog(ERROR, "syscall", "listen", 0);

      for(hit=1; ;hit++)
      {
        length=sizeof(cli_addr);

        if((socketfd=accept(listenfd,
                            (struct sockaddr*) &cli_addr,
                            (socklen_t*) &length)) < 0)
          aclog(ERROR, "syscall", "accept", 0);

        if((pid=fork()) < 0)
        {
          aclog(ERROR, "syscall", "fork", 0);
        }
        else
        {
          if(pid == 0)
          {
            close(listenfd);
            child(socketfd, hit);
          }
          else
          {
            close(socketfd);
          }
        }
      }
    }

Compilando, implementando e testando o aplicativo

É preciso criar mais um arquivo para construir adequadamente o aplicativo em nuvem usando o makefile da origem do kernel do Android. Crie um arquivo chamado Android.mk e cole nele o que você vê na Lista 11. (Este arquivo também é incluído na origem disponível em Download.)

Lista 11. Android.mk
    ifneq ($(TARGET_SIMULATOR),true)

    LOCAL_PATH:= $(call my-dir)

    include $(CLEAR_VARS)
    LOCAL_SRC_FILES:= cloud.c
    LOCAL_MODULE := cloud
    LOCAL_STATIC_LIBRARIES := libcutils libc
    include $(BUILD_EXECUTABLE)

    endif  # TARGET_SIMULATOR != true

Navegue para o diretório externo da origem do kernel do Android, crie um subdiretório chamado nuvem e coloque os arquivos cloud.c e Android.mk nele. Agora você está pronto para construir um novo sistema de kernel do Android com o aplicativo da pequena nuvem nele.

Mova para cima no diretório-raiz da origem do kernel Android, digite make e, depois, vá tomar um café. Este processo levará um tempo, então, relaxe e deixe o sistema fazer seu trabalho.

Se tudo for bem e o sistema tiver concluído o make, você deve localizar o binário da pequena nuvem no diretório out/target/product/generic/system/bin. Na verdade, você não precisa passar por todo o trabalho de instalar a distribuição inteira no seu telefone celular Android destravado: basta copiar o binário da nuvem para o cartão SD. A Lista 12 mostra como você pode fazer isso no seu computador host (supondo que o diretório mydroid contém todo o código do kernel de origem do Android).

Lista 12. Fazendo o kernel e a nuvem
    $ cd mydroid/external
    $ mkdir cloud
    $ cd cloud
    $ cp ~/src/tinycloud/cloud.c .
    $ cp ~/src/tinycloud/Android.mk .
    $ cd ../..
    $ make

    --- Mensagens "make" do 
	sistema Android rolam para cima da tela por um longo tempo. ---

    $ cd out/target/product/generic/system/bin
    $ cp cloud /media/ANDROIDSDCARD/.

Observe que /media/ANDROIDSDCARD assume que você tem o telefone celular plugado e montado. Além disso, o nome do seu cartão SD pode ser diferente. Procure o nome correto no subdiretório /media (se estiver executando sob o Ubuntu Linux).

Executar um dos programas Terminal gratuitamente disponíveis localizados no Android Market permite que você execute uma sessão shell no próprio telefone Android. A nuvem Android normalmente reside no diretório system/bin, mas não necessariamente. Para a finalidade de teste, é bom experimentá-la em outro diretório. Crie um diretório sob /data e chame-o de cloud. Copie o binário da nuvem do diretório /sdcard para /data/cloud. Depois, execute um comando chmod para tornar o programa em nuvem executável e execute-o digitando cloud. A Lista 13 mostra qual é a aparência desses passos.

Lista 13. Testando a nuvem no seu telefone celular Android
    $ su
    # cd data
    # mkdir cloud
    # cd cloud
    # cp /sdcard/cloud .
    # chmod 777 cloud
    # ./cloud
    # ps

    --- Lista dos daemons residentes, e "./cloud" deve ser um deles. ---

Pressione a tecla Home , inicie o navegador e acesse a URL http://localhost. Você deverá ver a saída da pequena nuvem no navegador do Android. É possível mover pelo sistema de arquivos do seu telefone portátil clicando nos links exibidos.

A seguir, se o Wi-Fi do seu telefone Android estiver em execução na sua rede, será possível usar o seu computador para chamar a pequena nuvem. Para fazer isso, você precisa conhecer o endereço IP do Wi-Fi do seu telefone celular. Existem várias maneiras de determinar este endereço, incluindo verificar os logs do roteador do seu Wi-Fi. Outra maneira é voltar ao programa Terminal e digitar netstat -r; você deverá ver uma entrada similar a essa na Lista 14.

Lista 14. Usando o Netstat para obter o endereço de IP de um telefone celular
    # netstat -r
    Proto Recv-Q Send-Q  Local Address    Foreign Address    ...
    .
    .
    .
    tcp        0      0  192.168.0.3:80   192.168.0.5:58744  ...
    .
    .
    .

Digite http://192.168.0.3/ (o endereço IP do seu telefone celular) na barra de endereços do seu navegador. Em um momento, você deverá estar olhando para a sua lista do sistema de arquivos do seu telefone celular Android, apresentada pela pequena nuvem.

Para usar a pequena nuvem no seu telefone celular para navegar para uma Web page que você está criando ao mesmo tempo, basta alternar o aplicativo que você está usando pressionando e mantendo pressionada a tecla Home e clicando no navegador ou no editor. Se você clicar no navegador, faça uma atualização do menu para ver suas mudanças editadas. Ao repetir o ciclo editar/testar/editar/testar até que ele tenha a aparência que você deseja, é possível dominar a Web enquanto aguarda no consultório do dentista.


Aprimorando o projeto

Existem tantas maneiras de aprimorar o projeto quanto existem pessoas com ideias, mas aqui estão algumas sugestões que talvez você deseje tentar:

  • Inclua um item de menu específico chamado Java que automaticamente navegue para o diretório no qual os arquivos da classe Java residem, permitindo que você clique em qualquer um deles para propósitos exploratórios. (Arquivos de classe são, na verdade, diretórios compactados e serão qualificados para hyperlinks.) É possível fazer isso para qualquer outro diretório específico que contenha código que interesse a você.
  • Inclua uma página como uma página superior que se atualize a cada minuto aproximadamente e exiba as informações de opção que podem ser lidas das informações no diretório /proc.
  • Escreva o código que permite que você consulte os banco de dados SQLite a partir de uma página da Web.
  • Apresentações inteiras baseadas em HTML podem ser hospedadas no cartão SD, e a portabilidade do telefone celular é grande, assim, ao usar o navegador da Web integrado na maioria nos estágios de apresentação moderna, é possível exibir sua apresentação de slides no seu telefone celular.

Quando tiver decidido sobre uma ideia para aprimoramento da pequena nuvem, siga essas três etapas genéricas para incluir essa funcionalidade:

  1. Modifique a função buildbuf na Lista 6 inserindo uma nova opção de menu que represente a nova funcionalidade que você deseja incluir.
  2. Modifique a função child na Lista 9 para que ela possa servir à nova funcionalidade. Por exemplo, estude como o item de menu About_ funciona em ambas as funções (buildbuf e child) e você verá como é fácil incluir nova funcionalidade na pequena nuvem.
  3. Escreva a função que servirá ao item de menu e certifique-se de inserir uma chamada na nova função na filha.

Conclusão

É sempre bom saber o máximo que você puder sobre os dispositivos que usa. Além disso, escrever ferramentas que possam ajudá-lo a saber mais pode ser muito divertido. Colocar um aplicativo de computação em pequena nuvem no coração do seu telefone celular Android é uma atividade divertida e educacional que o forçará a saber muito sobre o que, de fato, reside "sob o capô" desses dispositivos incríveis.


Download

DescriçãoNomeTamanho
Source code for the tiny cloud appos-tinycloud-source.zip9KB

Recursos

Aprender

Obter produtos e tecnologias

Discutir

Comentários

developerWorks: Conecte-se

Los campos obligatorios están marcados con un asterisco (*).


Precisa de um ID IBM?
Esqueceu seu ID IBM?


Esqueceu sua senha?
Alterar sua senha

Ao clicar em Enviar, você concorda com os termos e condições do developerWorks.

 


A primeira vez que você entrar no developerWorks, um perfil é criado para você. Informações no seu perfil (seu nome, país / região, e nome da empresa) é apresentado ao público e vai acompanhar qualquer conteúdo que você postar, a menos que você opte por esconder o nome da empresa. Você pode atualizar sua conta IBM a qualquer momento.

Todas as informações enviadas são seguras.

Elija su nombre para mostrar



Ao se conectar ao developerWorks pela primeira vez, é criado um perfil para você e é necessário selecionar um nome de exibição. O nome de exibição acompanhará o conteúdo que você postar no developerWorks.

Escolha um nome de exibição de 3 - 31 caracteres. Seu nome de exibição deve ser exclusivo na comunidade do developerWorks e não deve ser o seu endereço de email por motivo de privacidade.

Los campos obligatorios están marcados con un asterisco (*).

(Escolha um nome de exibição de 3 - 31 caracteres.)

Ao clicar em Enviar, você concorda com os termos e condições do developerWorks.

 


Todas as informações enviadas são seguras.


static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=80
Zone=Software livre
ArticleID=454039
ArticleTitle=Uma Pequena Nuvem em Android
publish-date=12162009