A tiny cloud in Android

Exploring the Android file system from your browser

Cloud computing minimally requires two components: the client software that runs on the portable device and the server software that normally runs on a network server. This article proposes creating an Android-based service that emulates a network server that enhances the value of the local machine in unique and unexpected ways. Put a tiny cloud in your Android handset and experience the usefulness of a local Web server.

Share:

Bill Zimmerly, Freelance Writer and Knowledge Engineer, Author

Bill ZimmerlyBill Zimmerly is a knowledge engineer, a low-level systems programmer with expertise in various versions of UNIX and Microsoft Windows, and a free thinker who worships at the altar of Logic. Creating new technologies and writing about them are his passions. He resides in rural Hillsboro, Missouri, where the air is fresh, the views are inspiring, and good wineries are all around. You can reach him at bill@zimmerly.com.



17 November 2009

Also available in Russian Japanese Portuguese

Android is a special distribution of the Linux® operating system, designed to manage the kind of functionality you expect in the smartest of smart phones. To a programmer, everything in Linux — a device, a spreadsheet, or a favorite song — appears as a file. That is, there is a common set of ways to open, extract, manipulate, and save the information content of these diverse and abstract entities. And this commonality forms the core principle of the UNIX® philosophy: Everything is a file.

Frequently used acronyms

  • MIME: Multipurpose Internet Mail Extension
  • HTML: Hypertext Markup Language
  • SDK: Software development kit
  • WWW: World Wide Web

Files are grouped into useful hierarchies called file systems. An Android cell phone typically has two file systems: the non-volatile memory of the cell phone and the SD card plugged into it. Both appear as branches off the root directory (/). A tool that enabled you to browse these file systems conveniently from your browser could prove useful. This project defines a small program, written in the native language of C, that communicates as a Web server and enables you to browse the Android cell phone's file systems from your workstation or straight from the built-in browser of the cell phone itself. It provides pages with hyperlinks that enable you to move up and down the hierarchical tree. By clicking various file types listed, you can view the individual items.

Setting up the development environment

First, make sure that you have a "rooted" Android cell phone so you can do things like run Terminal and execute the su command to obtain root privileges. If you don't know how to "root" your Android phone and obtain these privileges, a quick Internet search should give you what you need. (Note that this process is sometimes called jail-breaking your phone. See Resources for links on how to do this.)

The Android community primarily uses two SDKs. The most familiar one is the high-level Android SDK, which enables you to write application code in the Java™ language and commonly uses Eclipse for writing, testing, and debugging code. Another, less commonly known SDK is the Android kernel source, which is stored in what is known as a git repository. (For links to this repository, see Resources.)

Since this article focuses on creating a low-level Web server that will typically reside in the system/bin directory of your cell phone, it is important to download and install the entire Android kernel source code and the GNU tools used for building it. The home page of the Android Kernel Source project (see Resources) provides simple instructions for downloading the entire platform with a script called repo.

The tiny cloud software will be cross-compiled to the ARM platform on your workstation, so make sure all the necessary tools are installed. Using apt-get, install these tools as shown in Listing 1.

Listing 1. Installing cross-compiling tools
    $ 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

Development directory structure

Use the directory name mydroid to install the Android kernel source. This name makes an effective root directory to work off of, so go to your home directory and issue a mkdir mydroid command. Then use cd mydroid and issue the repo sync command there.

After the repo sync command has downloaded all of the Android source code to your mydriod directory, a few noteworthy subdirectories that were created include:

  • You will be creating the cloud directory inside mydroid/external. The source code for this project (cloud.c) will reside there.
  • After the long-running make command builds the Android system, you will find the binary file cloud inside the out/target/product/generic/system/bin directory.

The Android cloud project

When the cloud program starts, it immediately checks to see whether any command-line parameters have been passed to it. The two parameters that are optionally expected are the port to monitor and the home directory to start in. If neither parameter is specified, the program defaults to using the standard port 80, and the default home directory is whatever the current working directory was when the program was started.

After startup, the program initializes the TCP/IP socket to "listen" for calls to it through the aforementioned port, then turns itself into a daemon process, waiting for browser calls and servicing them. When a browser calls the default "page" of this tiny cloud server, the code responds by returning a directory listing of the aforementioned "home" directory. File names are listed with or without a hyperlink, depending on whether they are a known file type or a directory. To be a known file type means (in the WWW world) that the file has a corresponding MIME type. For example, deep in the heart of the Android cell phone, audio ringtones are stored as .ogg files. The MIME type audio/ogg tells the browser to play the file on the loudspeaker, assuming that your browser was configured correctly to do this.

Another hyperlink that appears at the top of the file listings is Parent Directory. Clicking this link allows you to move up the file system hierarchy until you eventually get as high as you can possibly go: the root directory. Along the way, other subdirectory names appear as hyperlinks; if you click them, you will go down into that subdirectory to explore the files contained therein.

So, the cloud application is a useful program for conveniently exploring the file system of the cell phone, and the source code (see Download) provides you with a good template of functionality you can modify as you see fit. Suggested ways to modify the code appear at the end of this article. (You can also compile the code and run it on your workstation, enabling you to browse the workstation's file systems, too. For instructions on how to do this, see Resources.)


The C source code

Every program's source code should show at minimum the program's name and author. Listing 2 shows the attribution, the include files from which you'll be using definitions, and some useful constants.

Listing 2. Attribution, includes, and useful constants
    // Android Cloud Application by Bill Zimmerly.
    // Based on "NWEB" by 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

Listing 3 provides the global working storage that is accessible by all functions defined in this program. Most of the buffer pointers are allocated storage when a browser calls the tiny cloud. After returning the content to the browser, the memory allocated is returned to the cell phone. In computers with limited resources, this practice becomes more important than many other considerations.

Listing 3. Global working storage
    char* about="</pre>Cloud is a simple application that enables "
                "web-based browsing of the Android file system "
                "and is intended for use by people who like to "
                "explore the lowest levels of their device. It "
                "runs on a rooted Android phone and is only for "
                "browsing the file system. See the IBM "
                "developerWorks article for a full description "
                "of this application.<pre>";

    char* mainbuf;
    char* theDir;
    char* thePort[8];
    char* theList;
    char* fstr;

    char logDir[LBUF];

    int ret;

In this program, a simple table of file extensions map into the MIME types that browsers need to know to properly handle the file's content. The structure in Listing 4 is used by the mimeokay function for one purpose: to set the global string pointer fstr to the appropriate MIME type string matching the file's extension: fext. With this information, the tiny cloud can display the file name with a hyperlink or as plain text without a link. It also serves the dual purpose of providing the MIME type when a file's content is being sent to the browser.

Listing 4. Determining MIME types
    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;
        }
      }
    }

Listing 5 shows the optional code that will log Android cloud activity to a cloud.log file during development and testing. Because the cloud runs on relatively slow hardware, it is good to leave this functionality shut off unless you really need to see what's happening in the code while you're modifying it. The LOGGING constant in Listing 1 should be TRUE if you want this logging to work, but leave it FALSE when it is running on the cell phone, as the performance hit can be significant.

Listing 5. Logging activity
    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);
    }

Listing 6 provides several functions defined for the purpose of creating the HTML output of the tiny cloud. Note that every page of a well-designed Web site should maintain a common look, and the buildbuf function is where this overall look is defined.

Listing 6. Generating HTML output
    void apname(void)
    {
      strcat(mainbuf, "Android Cloud Application");
    }
    
    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));
    }

Listing 7 shows how the tiny cloud returns the content of a file with a defined MIME type. Notice how the browser expects the MIME type to be sent from the server as a Content-Type: string. By just clicking the cloud-generated links, this function is called upon to return the content of that file. If, however, a creative and mischievous soul edits a bad file name in his browser's address bar, the error404 function (defined above) will inform the user of it.

Listing 7. Returning file contents
    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);
        }
      }
    }

Listing 8 shows how the tiny cloud builds the main file listing with hyperlinks. The hyper function is used several times, so it is prudent to factor it out into its own function. The isDir value prepends the /CD_ text before the full path to the file name so that the tiny cloud knows that it must display the contents of that directory. The fileList function is truly the heart and soul of this application.

Listing 8. Directory listing functions
    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;
    }

In Listing 9, the child functionality of the tiny cloud server is defined. This functionality runs every time the server receives a browser request, and it has a simple function: allocate the buffers necessary for satisfying the request, process them, then free them so the allocated system memory is kept low when not needed. On a cell phone, memory is a scarce and precious resource, and should be released back to the system when your program is done servicing a request.

Listing 9. Daemon child functionality
    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);
    }

The main (parent) functionality of the tiny cloud is defined in Listing 10. It allocates the TCP/IP socket on which it will be listening for browser request calls. Then it initializes a few global variables like theDir, where the tiny cloud was started. And finally, it makes itself into a resident program (known as a daemon) so it can quietly process browser requests in the background while other processes are running.

Listing 10. Main functionality
    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("Usage: cloud [Port Directory]\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("ERROR: Invalid directory %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);
          }
        }
      }
    }

Compiling, deploying, and testing the application

You need to create one more file to properly build the cloud application using the Android kernel source makefile. Create a file called Android.mk, and paste what you see in Listing 11 into it. (This file is also included in the source available in Download.)

Listing 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

Navigate to the external directory of the Android kernel source, create a subdirectory named cloud, and put both the cloud.c and the Android.mk files into it. You're now ready to build a new Android kernel system with the tiny cloud application in it.

Move up to the root directory of the Android kernel source, type make, then go get some coffee. This process will take a while, so relax and let the system do its job.

If all goes well and the system has completed the make, you should find the tiny cloud binary in the out/target/product/generic/system/bin directory. You don't really need to go through all the trouble of installing the entire distribution into your rooted Android cell phone: Just copy the cloud binary to the SD card. Listing 12 shows how you can do this on your host computer (assuming that the mydroid directory contains all the Android source kernel code).

Listing 12. Making the kernel and the cloud
    $ cd mydroid/external
    $ mkdir cloud
    $ cd cloud
    $ cp ~/src/tinycloud/cloud.c .
    $ cp ~/src/tinycloud/Android.mk .
    $ cd ../..
    $ make
    
    --- Android system "make" messages scroll up the screen for a long time. ---
    
    $ cd out/target/product/generic/system/bin
    $ cp cloud /media/ANDROIDSDCARD/.

Notice that /media/ANDROIDSDCARD assumes you have the cell phone plugged in and mounted. Also, the name of your SD card may be different. Look around in the /media subdirectory (if running under Ubuntu Linux) for the correct name.

Running one of the freely available Terminal programs found in the Android Market allows you to run a shell session on the Android phone itself. The Android cloud would normally reside in the system/bin directory, but it doesn't have to. For the sake of testing, it's good to experiment with it in another directory. Create a directory under /data and call it cloud. Copy the cloud binary from the /sdcard directory to /data/cloud. Then run a chmod command to make the cloud program executable, and run it by typing cloud. Listing 13 shows you what these steps look like.

Listing 13. Testing the cloud on your Android cell phone
    $ su
    # cd data
    # mkdir cloud
    # cd cloud
    # cp /sdcard/cloud .
    # chmod 777 cloud
    # ./cloud
    # ps
    
    --- Listing of resident daemons, and "./cloud" should be one of them. ---

Press the Home key, start the browser, and go to the URL http://localhost. You should see the output of the tiny cloud on Android's browser. You can move around the file system of your handset by clicking the links displayed.

Next, if your Android phone Wi-Fi is running on your network, you can use your computer to call up the tiny cloud. To do this, you need to know the Wi-Fi IP address of your cell phone. There are various ways to determine this address, including checking your Wi-Fi router's logs. Another way is to go back to the Terminal program and type netstat -r; you should see an entry similar to that in Listing 14.

Listing 14. Using Netstat to obtain a cell phone's IP address
    # netstat -r
    Proto Recv-Q Send-Q  Local Address    Foreign Address    ... 
    .
    .
    .
    tcp        0      0  192.168.0.3:80   192.168.0.5:58744  ...
    .
    .
    .

Type http://192.168.0.3/ (your cell phone's IP address) in your browser's address bar. In a moment, you should be looking into your Android cell phone's file system listing, presented by the tiny cloud.

To use the tiny cloud in your cell phone to browse a Web page you are creating at the same time, simply swap the application you're using by pressing and holding the Home key and clicking the browser or the editor. If you click the browser, do a menu refresh to see your edited changes. By repeating the edit/test/edit/test cycle until it looks how you want it to, you can be Web-mastering while waiting at the dentist's office.


Enhancing the project

There are as many ways to enhance the project as there are people with ideas, but here are a few suggestions that you may want to try:

  • Add a specific menu item called Java that automatically navigates to the directory in which the Java class files reside, allowing you to click any of them for exploratory purposes. (Class files are actually compressed directories and will qualify for hyperlinks.) You can do this for any other specific directory that contains code that interests you.
  • Add a top-like page that refreshes itself every minute or so and displays choice information that can be read from the information in the /proc directory.
  • Write code that allows you to query SQLite databases from a Web page.
  • Whole HTML-based presentations can be hosted on the SD card, and the portability of the cell phone is great, so by using the Web browser built into most modern presentation stages, you can display your slide show presentation on your cell phone.

When you have decided on an idea for improving the tiny cloud, follow these three generic steps to add that functionality:

  1. Modify the buildbuf function in Listing 6 by entering a new menu choice that represents the new functionality you want to add.
  2. Modify the child function in Listing 9 so it can service the new functionality. For example, study how the About_ menu item works in both of these functions (buildbuf and child), and you'll see how easy it is to add new functionality to the tiny cloud.
  3. Write the function that will service the menu item and be sure to insert a call to the new function in the child.

Conclusion

It's always a good thing to know as much as you can about the devices you use. Furthermore, writing tools that can help you learn more can be a lot of fun. Putting a tiny cloud computing application into the heart of your Android cell phone is a fun and educational activity that will force you to learn a lot about what actually resides "under the hood" of these amazing devices.


Download

DescriptionNameSize
Source code for the tiny cloud appos-tinycloud-source.zip9KB

Resources

Learn

Get products and technologies

Discuss

Comments

developerWorks: Sign in

Required fields are indicated with an asterisk (*).


Need an IBM ID?
Forgot your IBM ID?


Forgot your password?
Change your password

By clicking Submit, you agree to the developerWorks terms of use.

 


The first time you sign into developerWorks, a profile is created for you. Information in your profile (your name, country/region, and company name) is displayed to the public and will accompany any content you post, unless you opt to hide your company name. You may update your IBM account at any time.

All information submitted is secure.

Choose your display name



The first time you sign in to developerWorks, a profile is created for you, so you need to choose a display name. Your display name accompanies the content you post on developerWorks.

Please choose a display name between 3-31 characters. Your display name must be unique in the developerWorks community and should not be your email address for privacy reasons.

Required fields are indicated with an asterisk (*).

(Must be between 3 – 31 characters.)

By clicking Submit, you agree to the developerWorks terms of use.

 


All information submitted is secure.

Dig deeper into Open source on developerWorks


static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=1
Zone=Open source, Cloud computing
ArticleID=445975
ArticleTitle=A tiny cloud in Android
publish-date=11172009