Previous  | Next  | Home

Application Fundamentals


 

This is a brief synopsis of the structure of an Android application (see this more extensive discussion). In learning to program within a new software development kit it is always important to understand such structure. However, this is particularly so for a language like Android, which is designed to operate on devices with constrained resources that may not be very tolerant of poorly constructed programs.

 

Overview of an Android Program

Android programs are written in Java, supplemented by various resources supplied in terms of XML layout and data files, image files, raw data files, and so on. Much of the Java API is accessible, except for those classes that don't have an obvious use on mobile devices, or those whose functionality is better implemented through classes optimized specifically for mobile applications. For example, the usual Java layout tools such as the AWT and Swing are not implemented because they are replaced by Android layout tools optimized for Android devices.

Although not essential to a functioning Android program, best practices dictate that the presentation layer should be separated from the computing layer when feasible. The model for accomplishing this in Android is to place as much as is convenient of the user interface (UI) layout specification in XML resource files, with the Java coding reserved for defining event handlers for the UI widgets and methods to accomplish the required tasks. This is different from the usual programming of Java, where one would commonly use tools like Swing to lay out the UI within the Java code.


One can lay out the UI in Android using only Java, but it is not considered best practice because it entangles presentation with logic and computing, which complicates maintenance and extension of an application. Of course, mindless adherence to rules is a poor way to program and for more complex and dynamical layouts it may make perfectly good sense to handle much or all of the layout in Java. We shall give many examples of both approaches.

The compiled Java code, and any data and resource files required by the code, are bundled automatically by the Android development tools into an Android package, which is an archive file with a .apk extension. All the code in a single .apk file is one Android application (or app). Installing an app on a mobile device consists of installing the corresponding .apk file on that device.

 

The Android Security Model: Each Application is an Island

Each application is isolated from all other applications unless explicit permissions are given to allow them to communicate or share resources. By default:

Thus, the crash of an application is generally not of direct consequence to any other application because they are sandboxed in separate virtual machines. There are mechanisms to change these defaults and to allow different apps to share data and resources, but to do so requires explicit override of the defaults. For example, two applications can be made to share the same ID, in which case they can see each other's files, and if they share the same ID they can we arranged to share the same VM by running under the same Linux process.

 

Components of an Application

One of the first questions an experienced Java or C programmer looking at an Android application for the first time might ask is, "where is the main() method"? In a stand-alone Java program written for a desktop computer one would typically have a main() method that defines the (single) entry point for the program. Android is structured differently because of the nature of its target deployment environment: hardware systems that use Android (phones, tablet computers, embedded devices ...) typically have limited resources relative to desktop computers. In an Android application there is no main() method. Rather, Android is structured so that (if permissions are given) applications may use relevant pieces of other applications, without having to load all of the other application. This ability is important in implementing "lean and mean" applications that use minimal resources, and implies that well-written Android applications must be highly modular, with multiple entry points.

This is accomplished in Android by constructing applications from four types of components: (1) activities, (2) services, (3) broadcast receivers, and (4) content providers, all of which run by default on the main thread of the UI.


When an application is initiated by executing its initial component, Android starts a corresponding Linux process with a single execution thread. By default, all components of the application run in that process and thread. However, components can be arranged to run in other processes, and any process can spawn additional threads. As we will discuss further below, implementing such options is important for operations that have the potential to block the main UI thread, if one wants to retain responsiveness in an application (see further details at Processes and Threads ).


Let us now summarize the nature of these four basic ingredients that make up any Android application.

 

Activities

An activity is a single, focused "activity"; the closest analogy in normal computing is probably to that of a window on a desktop computer screen. For example, a simple activity might present a set of choice buttons to a user. An application could consist of a single activity, but more often will involve a sequence of activities, each of which is independent of the others, but all organized toward the common goal of the application. The typical motif for accomplishing this is to designate one activity as the screen first presented to the user, with movement between this and subsequent activities accomplished by having a current activity call another (with the visual consequence most often being that one visible screen is replaced by another on the device). For example, clicking a button on the first screen might replace that screen with another screen containing other widgets, a web page, a movie, or text information. Visually, the window corresponding to an activity represents a hierarchy of view objects derived from the base class View, as we discuss more extensively in Android User Interfaces.

Activities are typically created by subclassing (extending) the Android class Activity. Since most activities will be expected to interact with the user, the Activity class automatically takes care of creating a window for you in which you can place your user interface (UI) with the method setContentView(View). Activities most often are associated with full-screen windows, but they can also be floating windows (by implementing a theme with windowIsFloating set) or they can be embedded inside another activity (using ActivityGroup).

There are several methods of the Activity class that most subclasses will override (provide their own custom implementations of):

All activity classes require a corresponding <activity> declaration in the AndroidManifest.xml file for their package. Activities, like the other basic Android components, run on the main thread of the UI.

 

Services

A service extends the base class Service and corresponds to a process that runs in the background without a visual user interface. These are similar to Unix daemons. A service typically is used when an application wishes to perform a long-term operation that does not require (or desire) explicit user interaction, or wishes to supply continuous functionality for other applications to use. Examples of tasks for which you might want to use a service include a GPS tracking program that monitors the location of the device and transmits it to a server, a program that plays music in the background while a user is performing other tasks, or a program continuously monitoring a data feed in real time for sports scores or stock market quotes.

You can start a service if it is not running using Context.startService(), connect (bind) to a running service using Context.bindService(), and communicate with the running service through an interface that the service exposes. Each service class must have a corresponding <service> declaration in the AndroidManifest.xml file for its package.

By default, a service is not a separate process, nor is it a separate execution thread; services, like all UI components, run by default on the main thread of the application process. Therefore, if services involve blocking operations like network access, or computationally intensive tasks like repetitive loops, you will want to consider putting these operations on background threads so that they don't block the main UI (see Processes and Threads).

 

Broadcast Receivers

A broadcast receiver extends the base class BroadcastReceiver and has only one function: to listen for and respond to broadcast announcements. Applications can initiate broadcasts (e.g., a message for other interested applications that some data have been received over the network), but often broadcasts involve things like timezone changes or low-battery alerts that originate at the System level.

An application can have any number of broadcast receivers. A broadcast receiver does not display an explicit user interface but will typically generate a visual cue for the user by initiating an activity or by using a NotificationManager to display a persistent icon in the status bar of the device, vibrate, play a sound, flash lights, etc. to indicate to the user that something significant has happened in the background.

 

Content Providers

By default the data for an application in Android are private and not visible to other applications. However, an application may choose to use a content provider that extends the ContentProvider class and makes a specified part of the application's data available to other applications (see the Content Providers document for a more extensive discussion). Other applications wishing to receive data from a ContentProvider do not call its methods directly but rather instantiate a ContentResolver object and use its methods to retrieve the data from the content provider. The ContentResolver object has the ability to cooperate with any content provider to manage any interprocess communications that are necessary.

Android supplies by default a number of content providers for common data types like audio, video, images, or personal contact information (see the android.provider package). Your application can query these packages for the data they contain if it has acquired the appropriate permissions. There are two ways to make data from your own application public:

  1. Add your data to an existing Android provider, if there is one that controls the same type of data and your app has permission to write to it.

  2. Create your own content provider by subclassing ContentProvider.

How to do each is described in Content Providers.

 

The Android Manifest File

Android must know that a component of an application exists before it can start it. This is accomplished by having applications declare their components in an XML manifest file that is always called AndroidManifest.xml, and that every application must contain. As we shall find, the manifest file does many other things, such as naming any external libraries the application needs to be linked against and identifying any permissions the application expects to be granted, but its most fundamental task is to inform Android about the application's components. Here is an example of a simple manifest file


    <?xml version="1.0" encoding="utf-8"?>
    <manifest xmlns:android="http://schemas.android.com/apk/res/android"
        package="com.lightcone.webviewdemo"
        android:versionCode="1"
        android:versionName="1.0">
        <application android:icon="@drawable/icon" android:label="@string/app_name">
            <activity android:name=".WebViewDemo" android:label="@string/app_name">
                <intent-filter>
                    <action android:name="android.intent.action.MAIN" />
                    <category android:name="android.intent.category.LAUNCHER" />
                </intent-filter>
            </activity>
            <activity android:name=".Webscreen" android:label="Web"> </activity>
        </application>
        <uses-sdk android:minSdkVersion="3" />
        <uses-permission android:name="android.permission.INTERNET" />
    </manifest> 

in which two activities, WebViewDemo and Webscreen are declared. Additional features of this manifest file, such as the permissions tags, will be discussed later.


Activities, services, and content providers that are not declared in the manifest are not visible to the system and are consequently never run. However, broadcast receivers can either be declared in the manifest, or they can be created dynamically in code.

For a more extensive discussion of the manifest file, see The AndroidManifest.xml File.

 

Using Intents to Activate Components

The basic organization of an Android application is that components call each other. How is that implemented? We have just seen that a content provider is activated when it is targeted by the methods of a ContentResolver object. The other three types of Android application components (activities, services, and broadcast receivers) are activated by asynchronous messages called intents that are objects of the Intent class.

An intent is a passive data structure that holds an abstract description of an operation to be performed (or, in the case of BroadcastReceivers, it may hold a description of something that has happened and is being announced), and can provide late runtime binding between code in different applications. It can be used in conjunction with the methods

The most common use of an intent is in the launching of activities, where it can be thought of loosely as the "glue" between activities.

 

Explicit and Implicit Intents

Intents in Android fall into two broad categories:

  1. Explicit intents, where the target component is designated explicitly by name.

  2. Implicit intents, where the target component is not named explicitly and the Android system is expected to determine the best component to implement the intent.

To resolve implicit intents, Android relies on intent filters, which are described in the next section.

 

Intent Filters

An intent can name a target component but if a target is not named explicitly Android locates the best component to respond to the intent by comparing the intent object to the intent filters of potential targets. A component's intent filters tell Android which kinds of intents the component is able to handle. The intent filters of a component are declared in the manifest file (see the intent-filter tags in the above listing of a sample Manifest.xml file). A more extensive discussion of intents and intent filters may be found in Intents and Intent Filters.

 

Using Intents to Launch Google Applications

A programmer can use an Intent to launch various Google applications in particular ways, for example to dial a specific phone number or open a streetview on a particular location. Here is a partial list of possibilities.


Previous  | Next  | Home