Publishing an App in the Android Market

The first version of my Android experimental cell logger app is ready so it's time to publish it. I've put the source under the GNU public license so feel free to experiment with it. As you are reading this post the easiest way to get the app and the source is as follows:

  • For convenience you can pick it up in the Android market. Just search for "cell logger" and you'll find the app with my name as publisher. Or, just click here.
  • The bundled .apk file for installation. If you've come here with your Android device, click on the link and it will install right onto your device. If you've never downloaded an app outside the Android market you'll get an error message saying you have to allow installation of apps from unknown sources. Once done the app will install.
  • And here's the source code. It's the full Eclipse development folder so you'll find everything inside to compile and run it from there.

So what does it take to publish an app on the market and how difficult it is? You can find the detailed version from a programming perspective here. In essence pretty much everything for publication is already done when you compile the app into an ".apk" file and use a real set of self generated signature keys. These are a precondition anyway if the app runs on anything but the Android simulator. So this step was already done as well. In addition, the market requires two screen shots and a 512×512 pixel logo. I decided to generate the logo out of one of the screenshots by cropping and resizing. It's a research project so I decided that this will do for the moment.

From an administration point of view first thing that is required to publish the app in the market is a Google account. I decided to create a new one and it just takes a couple of minutes. Once done, the next step is to create an Android market account via the publisher page of the Android market web site. Access to the market as a publisher costs $25 and probably keeps out those who just want to look. Also, you need to share credit card details and for the general Google account a mobile phone number has to be given that is verified via an SMS. And finally an email address has to be given that is also verified. In other words, everyone who publishes something in the market can be identified unless someone really goes the extra mile and uses an unregisted throw away SIM card, stolen credit card credentials and an anonymous email account.

Once the registration is done, the app is published in a few minutes. The ".apk" file has to be uploaded, a description should be entered, the 512 pixel logo and two screen shots must be added and that's it. Very simple and straight forward.

No RSS Button By Default In Firefox 4

Today I wanted to add a feed to my feed-reader of a website I newly discovered but couldn’t find the RSS symbol being displayed next to the URL of the page in Firefox 4. Could it be that the web site has no RSS feed? It turned out that the page did have a feed but that the RSS symbol / button was removed from the default settings in Firefox 4. It can be added manually again by right-clicking on a free part of the navigation toolbar, selecting “customize” and then drag and drop the RSS icon into the toolbar. So I wonder what this means!? Is the discovery of new RSS feeds a function only used by a tiny fraction of users or, in other words, has reading blogs and news web sites via aggregators not really picked up?

Android Programming – Part 5 – The Rest

This is the 5th and final part in my series on programming on Android. By now my app is pretty much complete and does what I set out to do: It get's notified when the signal strength of the cellular network changes and displays the signal strength, cell-id, location area code, network operator id and network operator name. In this final part I'll describe how one other important feature works, saving the gathered data in a file, and some usability features.

Obviously seeing the current LAC and Cell-ID on the screen is nice, but having a record of cell and signal changes would be nice as well for further analysis later on. In other words, the data needs to be written to a file that can then be retrieved and further processed on the PC. The best place to store the file is on the flash disk which can then be either accessed via a USB cable or by removing it and connecting it via an adapter to a PC. Here's to code that does that: 

try {
  File root = Environment.getExternalStorageDirectory();
  if (root.canWrite()){
      File logfile = new File(root, filename);
      FileWriter logwriter = new
            FileWriter(logfile, true); /* true=append */

      BufferedWriter out = new BufferedWriter(logwriter);
               
      /* now save the data buffer into the file */
      out.write(LocalFileWriteBufferStr);
      out.close();
  }
}   

catch (IOException e) {
   /* don't do anything for the moment */
}

Writing a file could go wrong in which case Java would throw and exception and terminate the program if unhandled. Hence the need for the "try" construct. In the first line I search for the directory name of the flash disk with the getExternalStorageDirectory() method which is part of the Android API. If the disk is present and writable I then open a file in append mode, i.e. if it already exists all data is appended. Then, the standard Java out.write() and out.close() methods are used to write the data to the file and then close it again.

As you can see I have opted to open the file, write something and then to close it again immediately. I've done this as it's entirely possible that the flash disk is removed while the app is running, either physically or when a USB cable is connected to the PC. To reduce the wear on the flash memory of frequent file operations, I use a cache string in memory and only write to the file after a couple of kilobytes of data has accumulated. The downside of this is that one has to be aware when the app is closed and restarted, e.g. when the user turns the device and the screen is switched from portrait to landscape or when the app goes to the background. In those cases the data has to be written to the file, too.

And finally, a couple of words on the menu of the app. There are three entries in the menu: "About", "Reset Counters" and "Toggle Debug Mode".

 The code for them looks as follows:

@Override
public boolean onCreateOptionsMenu(Menu menu) {

    menu.add(0, RESET_COUNTER, 0, "Rest Counters");
    menu.add(0, ABOUT, 0, "About");
    menu.add(0, TOGGLE_DEBUG, 0, "Toggle Debug Mode");
    return true;
}
   
@Override
public boolean onOptionsItemSelected (MenuItem item) {

    switch (item.getItemId()) {
        case RESET_COUNTER:
               
            NumberOfCellChanges = 0;
            […]
               
            return true;
              
        case ABOUT:
            AlertDialog.Builder builder = new
                   AlertDialog.Builder(this);

            […]
               
            AlertDialog alert = builder.create();
            alert.show();

            return true;

        case TOGGLE_DEBUG:
            /* Toggle the debug behavior of the program
               when the user selects this menu item */

            if (outputDebugInfo == false) {
                outputDebugInfo = true;
            }
            else {
                outputDebugInfo = false;
            }
                   
       default:
            return super.onOptionsItemSelected(item);

    }
}

There we go, the app is almost complete now. A bit more polishing and then I'll post it on the blog together with the source and publish it in the Android market for easy access.

GSM 900 Use in Cities and the Countryside

Back in 2006, two network operators in Germany who so far only had GSM spectrum in the 1800 MHz range each got assigned a 5 MHz chunk of 900 MHz spectrum to improve rural coverage and urban in-house coverage. Also the move was necessary to equalize the playing field with the other two network operators who already owned 900 MHz spectrum from the beginning. It's 5 years later now so I wondered if and how they have made good use of it.

While I was recently on the countryside in Southern Germany I had a look in a number of places where 900 MHz spectrum would have been very beneficial. While O2 made consistent use of 900 MHz spectrum there in addition to some 1800 MHz carriers, E-Plus only used it very occasionally. I wouldn't have expected that as, after all, it's E-Plus who's always pointing out that they are at such a disadvantage.

The picture is even more interesting in cities. Here, 900 MHz spectrum significantly improves indoor coverage as can be observed with UMTS 2100 coverage being lost indoors much sooner than UMTS. Again, O2 has made use of their 900 MHz spectrum in Cologne in addition to their 1800 MHz spectrum. And again, no traces of a 900 MHz GSM deployment from E-Plus 5 years after they've been awarded spectrum.

On the other hand, their lack of 900 MHz deployment offers some interesting possibilities for UMTS deployment strategies. They've talked about that before in the press but only seeing is believing.

Android Programming – Part 4 – The Telephony Event Handler

In part 3 I've looked at the entry method of my app that is called whenever the app is started and how it registers a listener object to network status events. In this part I'll take a look at the listener object itself.

The code for the listener object is part of my app and is a private class that is only visible to my app but not to the outside world. Here's a code snippet that shows how it looks like:

private class MyPhoneStateListener extends PhoneStateListener {
 
  /* Get the Signal strength from the provider,
     each time there is an update */

  @Override
  public void onSignalStrengthsChanged(SignalStrength signalStrength) {

  […]
         
  try {
    /* output signal strength value directly on canvas of
       the main activity */

    outputText = "v7, number of updates: " +
    String.valueOf(NumberOfSignalStrengthUpdates);

    NumberOfSignalStrengthUpdates += 1;
            
    outputText += "rnrnNetwork Operator: " +
                   Tel.getNetworkOperator() +
                   " "+ Tel.getNetworkOperatorName() + "rn";

    outputText += "Network Type: " +
                   String.valueOf(Tel.getNetworkType()) +
                   "rnrn"
;

   […] 

To keep things simple the app only uses one listener method in the listener object, "onSignalStrengthsChanges". As the name implies this method is called whenever the signal strength of the current cell changes. It is "overridden" as I don't want Android to execute the default actions of this method but I want to do my own things in my instance of the class. When this method is called I also get other network status information and compare it to previously received values. If, for example, the cell-id has changed, I increase a corresponding counter variable accordingly.

Reading network status information seems to be a dangerous thing. If network coverage is lost and the method is called for whatever reason, one of the status query methods throws an error, known as an "exception" in Java. If that exception is not handled, the application will be terminated with an error message presented to the user. To prevent that from happening, all network status querries are performed in a "try – catch" construct. If an exception occurs in the "try" part of the code, execution continues in the "catch" part where the exception can be handled. In the case of this app, the code for the "catch" part is rather short as it doesn't do anything with the exception and just hopes for a better day when the device finds the network again.

To retrieve the network status information I am interested in, I call the following methods provided by the Android API:

  • TelephonyManager.getNetworkOperator()
  • TelephonyManager.getNetworkOperatorName()
  • TelephonyManager.getNetworkOperatorType()
  • SignalStrength.getGsmSignalStrength() –> works for UMTS as well…
  • GsmCellLocation.getCid()
  • GsmLellLocation.getLac()

There's also objects and methods in the API to get information about neighboring cells. However, this doesn't seem to be implemented consistently accross different devices and network technologies. In fact I tried this on several different types and models and only one would give me neighboring cell information and then only for GSM but not for UMTS. Here's the code for it:

   /* Neighbor Cell Stuff */
   List<NeighboringCellInfo> nbcell = Tel.getNeighboringCellInfo ();
   outputText += "Number of Neighbors: "  +
                  String.valueOf(nbcell.size()) + "rn";

   Iterator<NeighboringCellInfo> it = nbcell.iterator();
   while (it.hasNext()) {
     outputText += String.valueOf((it.next()getCid())) + "rn";
   }

And finally, the output text I've generated needs to end up on the screen. There are several ways to do it and I've decided to go for the straight forward approach:

   /* And finally, output the generated string with all the
      info retrieved */

   TextView tv = new TextView(getApplicationContext());
   tv.setText(outputText);
   setContentView(tv);

There we go, this is the core of the app to get network status information via the Android API. I guess one more part in this series is necessary to describe some bells and whistles for smooth user interaction and of course the release of the complete code so you can play around with it as well if you like.

Android Calling Home

If you are a frequent reader of this blog you are probably aware that I prefer to keep my personal data close to myself. I don't want my personal address book, calendar, etc. etc. with Google or anyone else in the cloud, I don't want anyone collecting location information, anonymously or not without my consent and I don't want my devices to frequently call the mother ship. In this day and age, that's quite a challenge with iOS and Android sending information back into the cloud if the settings are left unchanged. So I was wondering how this data collection works in practice today and how much can be prevented from going out.

To have a closer look at what's going on I set-up a test environment with my Android 2.2 based phone connected to the Internet via Wi-Fi. The Wi-Fi access point was not directly connected to the Internet, however, but instead to the Ethernet port of a notebook that had Internet connection sharing enabled via its own Wi-Fi interface and a second Wi-Fi access point. This way, Wireshark can be used to trace the communication between the mobile device and the rest of the world. To see how Android interacts with Google and the rest of the world and how this can be scaled down I tested three scenarios:

  • A device fully configured with a Google account, but calendar and address book synchronization disabled. Most people won't even deactivate this synchronization but I figured that's where most people who prefer to keep their data to themselves would start.
  • As above but the Google account inaccessible due to a change of the password.
  • After a factory reset without a Google account configured.

Lets take a look at the first scenario:

When the device is switched on, the first thing it does is to connect to synchronize the clock with an NTP time server (north-america.pool.ntp.org). Next, it retrieves GPS ephemeris information (xtra1.gpsonextra.net). This is interesting since gpsonextra.net is a domain registed by Qualcomm (and not Google), the maker of the radio chipset of the device.

After that, the device registers with Google (android.clients.google.com). For the interchange of most information, SSL is used so it's not possible to see what kind of data is interchanged inside the encrypted channel.

If registration with Google was successful the device then registers with Google Talk (mtalk.google.com) as Google Talk starts automatically in the background. This even happens when I configure Google Talk not to log me in automatically. I should add that I never registered to use Google Talk so I guess that comes as part of the Android/Google account.

And finally, the device starts talking to another time synchronization service (time-nw.nist.gov). Since this doesn't happen when I set the date and time to be configured manually, this interaction is probably there to check and correct the Android date and time. Again, this is not a Google service, NIST is the National (US) Institute for Standards and Technology. From that I infer that the NTP interaction above might be for the Qualcomm GPS calibration and not for Android itself.

All these interactions take place in the first few seconds after Internet connectivity has been established. After that, the device remains quiet until an app is started that interacts with a server on the network.

I wasn't able to trace an interaction with the Google location server that is reported to scan for WiFi SSIDs and Cell-IDs on a regular basis if this is not disabled in the configuration. This is most likely because my setup was stationary so the device was not able to collect information.

Put together, there is quite some interaction going on with the default settings. As mentioned above, many things can be disabled in the configuration. In a follow-up post or two I'll have a look at what can be prevented from going out and how that limits the use of the device.

Android Programming – Part 3 – Things Put Into Practice

After the general introduction to the Eclipse programming environment in part 1 and the basic concepts of object orientation and how it is used in Android in part 2, this part now finally takes a look how the theory looks like in practice. The application I had in mind since the beginning of this series is about exploring the network information such as cell-ids, signal strength and other data that Android provides to apps via its Application Programming Interface (API). In the following I'll show an extract of the code. I'll publish the source of the full app once it's a bit more polished.

As described in the previous post, Android apps use an event driven execution approach. When the app is started by the user, Android loads the app into memory and then jumps to the "onCreate" method. The following code snippet shows the beginning of the onCreate method of my app.

    /* Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
       
        /* If saved variable exist from last run still exist, recover them */
        if (savedInstanceState != null) {
        […]
        }

As I want to do my own things when the app starts, the onCreate method is "overridden". This means that while the original input and output parameters of the method are used in my app so Android can call the method in a defined way, the code in the method itself is unique for my application. In some cases it makes sense to not only have individual functionality in overridden methods but to also execute the code of the original method. This is done in the first line of the method by calling "super.onCreate".

The onCreate method receives a parameter that references data that the app has saved while it was last executed. This way, the app can populate all necessary variables at startup so it can continue from its previous state as if nothing had happened. This is quite helpful as Android closes an app automatically for various reasons such as, for example, when the system runs out of memory. An app is also closed and then automatically reopened when the user rotates the device and the screen orientation changes, something that happens quite frequently. So in my app I use this reference to populate a number of variables, such as the number of cell and location area changes that have occurred before (not shown in the code snippet above).

Once the variables are initialized, my onCreate method puts a number of things in place to get access to the network information. What I am interested in are mainly the cell-id, the location area code, the signal strength and when one of these change. On a machine that only runs a single program, a loop could be used to periodically check if these parameters have changed and then display them on the screen. In practice, however, this would not work as Android is a multitasking operating system so a single program must not lock up the device by running in a loop. Therefore, apps are event driven, i.e. a handler method is called when something happens. The app then performs an action such as updating the display and then goes back to sleep until another event happens and the handler is called again. So the way to get to the network status information I am interested in and to be informed about changes is to create a listener class with listener methods that Android calls when certain cellular network events such as signal strength changes occur. This is done with the following code:

     /* Get a handle to the telephony manager service and install a listener */
     MyListener = new MyPhoneStateListener();
     Tel        = (TelephonyManager) getSystemService(Context.TELEPHONY_SERVICE);
     Tel.listen(MyListener, PhoneStateListener.LISTEN_SIGNAL_STRENGTHS);

In the first line I instantiate an object from a class that I have defined further down in my app, the "MyPhoneStateListener" class. In the second line a reference is retrieved to the service object that manages the cellular network connectivity. In Android, this object is called the Telephony_Service, which is, from my point of view, a bit misleading. In the third line of the code, I then install my listener object as a listener of the telephony system service. This way, whenever the signal strength or other properties of the cellular network connectivity changes, the app is automatically notified and can then perform appropriate actions such as displaying the updated signal strength, cell-id and other information on the screen.

I'll describe the details on how that is done in the next post.

Facetime and Skype Video Quality

Today I read an article on the video quality of Facetime and Skype on an iPad2 here (sorry, article is in German). For both, the author came to the conclusion that the video quality is quite bad compared to Skype on a PC. So I wonder why this is so!? Perhaps it has something to do with the available processing power? I can observe similar things on my netbook where Skype video resolution and quality is far behind what I get on my fully-fledged notebook, despite the processor almost running at 100%. While things are probably not going to change on my Atom based netbook with a weak GPU, I wonder if the graphics GPUs built into mobile devices will be able to help in the near future with encoding and decoding the combined real time audio and video stream? I think it's quite an application. Let's see what Google has to say when they release their own video calling application on Android devices soon.

Taiwan Mobile RRC State Change Problems

While TMN doesn't let me use their 3G network with my German SIM card as reported in an earlier post, they do offer SIM cards for Internet access which are interesting for occasional use or travelers in the country for a couple of days. For the details on the offer see here. While the throughput in their network is quite o.k. and in the range of 3 MBit/s, their network has some compatibility issues with my 3G dongles.

I don't see such issues often anymore but TMN is one of those networks that still seem to have a strange RAN software version running that make my 3G dongles get stuck every now and then when an RRC state change occurs. Sometimes the connection recovers after a minute or so, sometimes I have to reset the connection entirely. The only thing that helps is a constant ping to keep the RRC connection in Cell-DCH.

TMN, you might want to run a compatibility check against some mainstream UMTS hardware not necessarily sold in Taiwan…