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.