The primary programming language used in developing your Android applications is Java SE, from Oracle (formerly Sun Microsystems). As noted in Chapter 1, Java SE stands for Java Standard Edition, and many people shorten this to just Java to refer to the programming language. Two other editions of the Java programming language are called Java EE, short for Java Enterprise Edition, and Java ME, for Java Micro Edition.
Java EE is designed for massive computer networks, such as vast collections of blade computers that are used to run large enterprises or corporations with thousands of active users. Thus, Java EE has more multiuser scalable features than Java SE, which is more for a single user on a single computer system, say a home PC or a handheld PC, like Android.
Java ME is designed for embedded systems to create highly portable computers such as mobile phones. It has fewer features than Java SE, so that it can fit onto a phone without using too much memory and resources to run it. Most mobile phones run Java ME, but Android phones run the more powerful Java SE. Android phones can run Java SE because they have a full gigabyte of memory and a 1GHz or faster CPU, so essentially today's Android smartphones are tiny Linux computers.
Java is an object-oriented programming (OOP) language. It is based on the concepts of developing modular, self-contained constructs called objects, which contain their own attributes and characteristics. In this chapter, you will learn about the OOP characteristics of Java, and the logic behind using these modular programming techniques to build applications that are easier to share and debug due to this OOP approach.
After you've had a taste of the power of Java, we'll quickly cover XML, because it's the way you define UIs and configurations in your Android apps. Without it, you would need to rely solely on Java code, which would make developing apps a lot more complicated.
Finally, we'll cover the main parts of the Android framework, and you will be able to see the OO underpinning it has. We'll briefly cover each component and explain which chapter covers it in more detail.
The foundation of an OOP is the object itself. Objects in OOP languages are similar to objects that you see around you, except they are virtual, and not tangible. Like tangible real-world objects, objects have characteristics, called states, and things that they can do, called behaviors. One way to think about it is that objects are nouns, or things that exist in and of themselves, and behaviors are like verbs.
As an example, consider a very popular object in all of our lives: the automobile. Some characteristics, or states, of a car might be as follows:
Color (red)
Direction (N, S, E, or W)
Speed (15 miles per hour)
Engine type (gas, diesel, hydrogen, propane, or electric)
Gear setting (1, 2, 3, 4, or 5)
Drivetrain type (2WD or 4WD)
The following are some things that a car can do, or behaviors:
Accelerate
Shift gears
Apply the brake
Turn the wheels
Turn on the stereo
Use the headlights
Use the turn signals
You get the idea.
Figure 5-1 is a simple diagram of the object structure using the car example. It shows the characteristics, or attributes, of the car that are central to defining the car object, and the behaviors that can be used. These attributes and behaviors define the car to the outside world.
Objects can be as complicated as you want them to be, and can nest or contain other objects within their structure, or object hierarchy. A hierarchy is like a tree structure, with a main trunk and branches and subbranches as you move up (or down) its structure. A good example of a hierarchy is the directory or folder structure on your hard disk drive.
Directories or folders on your hard disk drive can contain other directories or folders, which can in turn contain yet other directories and folders, allowing complex hierarchies of organization to be created. You can do the same thing with objects, which can contain subobjects, which can themselves contain further subobjects as needed to create your structure. You'll see plenty of nested objects when working with Android, because nested objects are useful for grouping objects that are used in only one place. In other words, some types of objects are useful only to one other type of object in an Android app, so they are provided in a nested hierarchy.
You should practice identifying objects in the room around you, and then break their definition down into states (characteristics) and behaviors (things that they can do), as this is how you will need to think to become more successful in your OOP endeavors.
You'll notice that in real life, objects can be made up of other objects. For example, a car engine object is made up of hundreds of discrete objects that function together to make the engine object work as a whole. This same construction of more complicated objects out of simpler objects can be done in OOP languages, where complex hierarchies of objects can contain other objects that have been created in previous Java code.
Now let's cover some of the technical terminology used for Java objects. First, objects have fields and methods, as follows:
Fields, called variables, hold the object's states.
Methods are programming routines that operate on the object's internal states. If object characteristics can be thought of as nouns, then methods can be thought of as verbs using this analogy. Methods also allow other objects external to the object itself to communicate with the object.
One of the key concepts of OOP is data encapsulation, where the object's fields are allowed to be modified directly only through that same object's methods. This allows the object to be self-sufficient. For example, to turn the car, you use the steering method, which positions the wheels in the desired direction.
With data encapsulation, each object that is part of a larger construct can be built and tested individually, without requiring accessing data from other objects or modules of the application (which can translate into bugs). Without data encapsulation, people could simply access any part of your object's data and use it however they pleased. This could introduce bugs, affecting the methods you have perfected to manipulate your object and provide your solution.
Data encapsulation promotes the core concept in OOP of modularity. Once an object is created and tested, it can be used by other objects without worrying about its integrity. Data encapsulation thus allows code reuse, so programmers can develop libraries of useful objects that do not need to be rewritten or retested by other programmers. You can see how this can save developers money by structuring only the work that needs to be done and avoiding redundant work processes.
Data encapsulation also allows developers to hide the data and the internal workings of the object if desired.
Finally, objects make debugging easier because they can be removed modularly during testing to ascertain where bugs are located in the overall code. In our car object example, the attributes of our car are encapsulated inside the car object, and can be changed only via the methods that surround them in the diagram. For instance, use the Shift Gears method to change the Gears=1 attribute to Gears=2.
In real life, there is seldom just a single kind of object. Usually, there are a number of different types and variations. For instance, for a car object, there are many different manufacturers, sizes, shapes, seating capacity, engine types, fuel types, transmission types, and so on.
In Java SE, we write something called a class to define what an object can do (its methods) and the fields it has. Once this class has been coded in Java, we can then create an instance of each object that we wish to use by referencing the class definition. In architectural terms, the class is a kind of blueprint as to what the object is, what states it contains, and what it can do (what methods it has).
An instance is a concrete object created from the blueprint of the class, with its own states or unique data attributes. For example, you might have a (second) blue car instance that is traveling south in third gear. (In the example, our first car instance is red and traveling north in first gear.)
To illustrate this further, let's construct a basic class for our car object example. To create a car class, you use the Java keyword class
, followed by your name for the new class that you are writing, and then curly brackets to hold your code definition, like so:
class Car {Code definition for a car class goes in here. We will do this next}
The first thing that we usually put inside our class (inside the curly {}
brackets) is the data fields (variables) that will hold the states, or attributes, of our car. In this case, we have six fields that define the car's gear, speed, direction, fuel type, color, and drivetrain (two- or four-wheel drive), as specified in the basic diagram shown earlier in Figure 5-1.
To define a variable in Java, you first declare its data type (int
means a whole number, and string
means text), followed by your variable name. You can also (optionally) set a default, or starting, value by using an equal sign and a data value. The variable definition ends with a semicolon.
Semicolons are used in programming languages to separate each code construct or definition from the other ones in the same body of code.
So, with our six variables from our anatomy of an object diagram in place, our class definition looks like this:
class Car { int speed = 15; int gear = 1; int drivetrain = 4; String direction = "N"; String color = "Red"; String fuel = "Gas"; }
Remember that these are all the default values—the ones each object instance will have when we create it.
Notice how the example spaces out the curly braces ({}
) on their own lines and indents lines, so that you can see what is contained within those braces more easily.
The next part of the class file will contain the methods that define how the car object will operate on the variables that define its current state of operation. Methods can also return a value to the calling entity, such as values that have been successfully changed or even answers to an equation. For instance, there could be a method to calculate distance that multiplies speed by time and returns a distance value.
To declare a method that does not return any value to the calling entity, you use the void
keyword. A good example of using void
is a method that triggers something—the method is used to invoke a change in the object, but does not need to send a value back to the calling function.
If your method or function returns a value, instead of using the void
keyword, you use the data type of the data that is to be returned, say int
or string
. For example, an addition method would return a number after finishing its calculation, so you would use int
.
After the void
keyword comes a name for the method (say, shiftGears
). This is followed by the type of data (in this case, an int
) and variable name (newGear
) in parentheses.
void shiftGears (int newGear) {
The variable contains a data parameter that will be passed to the method, so the method now has this variable to work with.
The normal method-naming convention is to start a method name with a lowercase letter, and to use uppercase letters to begin words embedded within the method name, like this: methodNameExample()
.
Some methods are called without variables, as follows:
methodSample();
To call the shiftGears()
method, you would use the following format:
shiftGears(4);
This passes 4 into the shiftGears()
method's newGear
variable, which sets its value. This value then is passed into the interior of the shiftGears()
method logic (the part inside the curly braces), where it is finally used to set the object's gear (internal) field to the new gear shift value of 4, or fourth gear.
A common reason to use a method without any parameters is to trigger a change in an object that does not depend on any data being passed in. So, we could code an upShift()
method and a downShift()
method that would upshift and downshift by one gear level each time they were called, rather than change to a gear selected by the driver. We then would not need a parameter to shift gears on our car; we would just call upShift()
or downShift()
whenever gear shifting was needed.
Notice the empty parentheses after the method names in the text. These are used when writing about the method, so that the reader knows that the author is talking about a method. You will see this convention used throughout the rest of this book.
After the method declaration, the method's code procedures are contained inside the curly braces. In this example, we have four methods:
The shiftGears()
method sets the car's gear to the gear that was passed into the shiftGears()
method.
void shiftGears (int newGear) { gear = newGear; }
The accelerateSpeed()
method takes the object's speed
state variable and adds an acceleration factor to the speed, which causes the object to accelerate. This is done by taking the object's current speed setting, or state, and adding an acceleration factor to it, and then setting the result of the addition back to the original speed
variable, so that the object's speed
state now contains the new (accelerated) speed value.
void accelerateSpeed (int acceleration) { speed = speed + acceleration; }
The applyBrake()
method takes the object's speed
state variable and subtracts a braking factor from the current speed, which causes the object to decelerate, or to brake. This is done by taking the object's current speed
setting and subtracting a braking factor from it, and then setting the result of the subtraction back to the original speed
variable, so that the object's speed
state now contains the updated (decelerated) braking value.
void applyBrake (int brakingFactor) { speed = speed - brakingFactor; }
The turnWheel()
method is straightforward, much like the shiftGears()
method, except that it uses a string value of N, S, E
, or W
to control the direction that the car turns. When turnWheel("W")
is used, the car will turn left.
void turnWheel (String newDirection) { direction = newDirection; }
The methods go inside the class and after the variable declarations, as follows:
class Car { int speed = 15; int gear = 1; int drivetrain = 4; String direction = "N"; String color = "Red"; String fuel = "Gas"; void shiftGears (int newGear) { gear = newGear; } void accelerateSpeed (int acceleration) { speed = speed + acceleration; } void applyBrake (int brakingFactor) { speed = speed - brakingFactor; } void turnWheel (String newDirection) {
direction = newDirection; } }
This Car
class allows us to define a car object, but it can't do anything until we use it to instantiate an object. In other words, it does not do anything until it is called.
To create an instance of an object, we instantiate it. Here's the onCreate()
method of an Android application, where we instantiate two cars and use them (refer to the example in Chapter 4 to see how to create an onCreate()
method in an Android app):
public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); Car carOne = new Car(); // Create Car Objects Car carTwo = new Car(); carOne.shiftGears(3); carOne.accelerateSpeed(15); // Invoke Methods on Car 1 carOne.turnWheel("E"); carTwo.shiftGears(2); // Invoke Methods on Car 2 carTwo.applyBrake(10); carTwo.turnWheel("W"); }
Upon launch or creation of our Android application, we now have two empty car objects. We have done this using the Car()
class constructor, along with the new
keyword, which creates a new object for us, like so:
Car carOne = new Car();
The syntax for doing this is very similar to what we used to declare our variables:
Define the object type Car
.
Give a name to our object (carOne
).
Set the carOne
object equal to a new Car
object definition, which has all the default variable values set.
To invoke our methods using our new car objects requires the use of something called dot notation. Once an object has been created and named, you can call methods by using the following code construct:
bjectName.methodName(variable);
So, to shift into third gear on car object number one, we would use this:
carOne.shiftGears(3);
So, as you can see in the final six lines of code in the onCreate()
method, we set carOne
to third gear, accelerate it from 15 to 30 mph by accelerating by a value of 15, and turn east by using the turnWheel()
method with a value of "E"
(the default direction is north, or "N"
). Car two we shift into second, applyBrake()
to slow it down from 15 to 5 mph, and turn the car west by using the turnWheel("W")
method via our dot notation.
There is also support in Java for developing different types of car objects by using a technique called inheritance, where more specific car classes (and thus more uniquely defined objects) can be subclassed from a more generic car class. Once a class is used for inheritance by a subclass, it becomes the super class. There can be only one super class and an unlimited number of subclasses. All the subclasses inherit the methods and fields from the super class.
For instance, from our Car
class, we could subclass an Suv
class that extended the Car
class to include those attributes that would apply only to an SUV type of car, in addition to the methods and states that apply to all types of cars. An SUV car class could have onStarCall()
and turn TowLightOn()
methods, in addition to the usual car operation methods. Similarly, we could generate a subclass for sports cars that includes an activateOverdrive()
method to provide faster gearing and an openTop()
method to put down the convertible roof. You can see these subclasses in the extension of our car object diagram shown in Figure 5-2.
To create a subclass from a super class, you extend
the subclass from the super class using the extends
keyword in the class declaration, like this:
class Suv extends Car { New Fields and Methods Go Here }
This extends to Suv
all of the fields and methods that Car
features, so that the developer can focus on just the new or different fields and methods that relate to the differentiation of the SUV from the regular car definition. Since the original core fields and methods come from the Car
class, it becomes the super class, and the Suv
class becomes the subclass. Suv
is said to be subclassed from the Car
super class.
To refer to one of the super class methods from within the subclass you are writing, you can use the super
keyword. For example, in the Suv
class, we may want to use a generic car's applyBrake()
method, and then apply some other factor to the brakes that is specific to SUVs. The following code does this:
class Suv extends Car { void applyBrake (int brakingFactor) { super.applyBrake(brakingFactor); speed = speed - brakingFactor; } }
This means the SUV's brakes are twice as powerful as a generic car's brakes.
Be sure to use good programming practices and document the super class fields and methods within each subclass. This documentation lets the users know that the super class's fields and methods are available, since they do not explicitly appear in the code for the subclass.
In many Java applications, the classes conform to a certain pattern, so that the rest of the application knows what to expect of those classes when they are instantiated as objects. This is especially common when using a framework like Android.
The public interface that the classes present to the rest of the application makes using them more predictable and allows you to use them in places where any class of that pattern is suitable. In other words, the public interface is a label that tells the application what this class can do, without the application needing to test its capabilities.
In Java terms, making a class conform to a pattern is done by implementing an interface. The following is an ICar
interface that forces all cars to have the methods defined in the interface. This also means that the rest of the application knows that each car can do all of these actions, because the ICar
interface defines the public interface of all cars.
public interface ICar { void shiftGears (int newGear); void accelerateSpeed (int acceleration); void applyBrake (int brakingFactor); void turnWheel (String newDirection); }
So, a car is not a car unless it contains these particular methods.
To implement an interface, use the implements
keyword as follows, and then define all the methods as before, except they must be public
.
class Car implements ICar
{
int speed = 15;
int gear = 1;
int drivetrain = 4;
String direction = "N";
String color = "Red";
String fuel = "Gas";
public
void shiftGears (int newGear) { gear = newGear; }public
void accelerateSpeed (int acceleration) { speed = speed + acceleration; }public
void applyBrake (int brakingFactor) { speed = speed - brakingFactor; }public
void turnWheel (String newDirection) { direction = newDirection; } }
The public
keyword allows other classes to call these methods, even if those classes are in a different package (packages are discussed in the next section). After all, this is a public interface, and anyone should be able to use it.
Each time you start a new project in Android, the Eclipse IDE will create a package to contain your own custom classes that you define to implement your application's functionality. In the Hello World application we created in the previous chapter, our package was named Hello.World
. In fact, the New Android Project dialog asked us for this package name.
The package declaration is the first line of code in any Android application, or in any Java application for that matter. The package declaration tells Java how to package your application. Recall the first line of code in our Hello World application:
package hello.world;
After the package
keyword and declaration come import
statements, which import existing Java classes and packages into your declared package. So, a package is not only for your own code that you write yourself, but also for all code that your application uses, even if it is open source code written by another programmer or company.
Basically, the package concept is similar to the folder hierarchy on your computer. A package is just a way of organizing your code by its functionality. Android organizes its classes into logical packages, which we will routinely import and use throughout this book.
In our Hello World application in the previous chapter, we needed two import
statements in our MyHelloWorld.java file to support class functions in our application:
import android.app.Activity; import android.os.Bundle;
These are basically addresses to where the code for each import
statement is located. Here is a generalization of how an import
statement follows a path to the class:
importplatform
.functionality
.classname
;
This applies to our two statements as follows:
android
says this is an Android package.
app
and os
refer to the broad functionality of the package in question.
Activity
and Bundle
refer to the classes we are importing.
Thus, the Activity
class, which is the super class for any activity that you create, is found within the android.app
package. This app
part says that this package logically contains classes that are necessary for the creation of Android applications, and one of these is the Activity
class, which allows us to define UIs.
The android.os
package we referenced in our import
statement contains classes that are operating system utilities. One of these is Bundle
, which allows us to create bundles of variables for convenience and organization.
You might be wondering if the package is the highest level of organization in Java. The answer is no, there is one higher level. This level is sometimes called a platform or application programming interface (API). This is a collection of all the core packages for a given language, such as Java SE or Java ME, or all the packages of a specialized product, such as Android.
There are actually two types of languages used in Android development: Java and XML. XML stands for eX
tensibleM
arkup L
anguage. Developed in 1996, XML is similar to HTML (for Hyper-Text Markup Language), which is used for web site design.
The primary use of XML is to structure data for items that require a predefined data structure, such as address books or computer-aided design (CAD). Like Java, XML is very modular, which allows complicated data definition constructs to be created.
XML uses structures called tags, just as HTML does. And as in HTML, these tags use tag keywords bracketed by the <
and >
characters. For example, in Android, the <resources>
tag contains resource definitions, and the <string>
tag contains string resource definitions. The <string>
tag also features attributes (which I think of more as parameters of sorts); for instance, a <string>
tag has a name
attribute that allows it to be named.
A parameter is a choice of data options that can be set, telling some code what you want it to do—sort of a way you can configure it exactly to your liking. So, you could set a background color of red by specifying a red
parameter to a method or as an attribute to an HTML element.
In our Hello World application in Chapter 4, we defined two string resources with the following XMLin the strings.xml file:
<resources> <string name="hello">Hello Android World, Here I Come!</string> <string name="app_name">Hello Great Big Android World</string> </resources>
You can readily see the modularity via the nesting of tags. The <resources>
tag contains the two <string>
tags and their attributes, putting them into one resources group. Nesting can be as many levels deep as required for more complicated data definition constructs.
XML is used in Android to define constructs so that you do not need to create them in more complicated Java code. It is easier to write definitions in XML than it is to write them in Java. This is because XML has the simpler markup format used in HTML, rather than the more complicated block code structure used in Java. This makes it easier for nonprogrammers to help write applications.
Because XML is easier to use than Java, and because this is a book for beginners, we will do everything that we can using XML instead of Java. Android allows this, and the XML works as well as Java code to achieve exactly the same results.
The cornerstone of Android application development is the application package file format, or the APK file format. When you compile and output an application for distribution to your Android users, the Eclipse IDE and Android SDK output your application file name with an .apk extension. There is only one .apk file, and it includes all of your application code (in the form of a DVM executable .dex file format), as well as any new media resources or assets and the AndroidManifest.xml file (which we'll discuss in detail in the final section of this chapter). Interestingly, the Android Market increased file size limits for .apk files from 25MB to 50MB, which is great news for developers.
So, if your application is called Zoomerza, for instance, the file that you get upon final publishing will be called Zoomerza.apk, and it will run on any Android phone. This file format is closely related to the standard Java .jar format, and uses the familiar ZIP type compression. The .apk file is specifically set up so that it can be run in place without going through the unpacking process.
You can look at the .apk file using the familiar file packing and unpacking software packages, such as PKZIP, WinZip, WinRAR, Ark, and 7-Zip. If you are interested in looking inside your application's .apk file to see its folders, it will not hurt the .apk file to do so.
If you have Windows Vista or Windows 7, the ZIP functionality is built into the operating system. An easy way to see your .apk file is to rename it to a .zip extension and open it inside the Windows Explorer file management utility. Another clever way to do this without renaming the file is to right-click the .apk file and use the Open with option to select a ZIP extraction utility. Let's do that here, so you can see what I'm talking about.
When you're warned about renaming the file, choose to do so anyway.
Click HelloWorldAndroid.zip. You will be able to see the internal file structure, as shown in Figure 5-3.
As shown in Figure 5-3, the application includes an AndroidManifest.xml file and a classes.dex file. It also contains the /res folder with the /drawable and /layout subfolders, which hold the assets we used to develop the app.
Android is designed with the maximum amount of modularity in mind. This modularity makes it easy for developers to exchange functionality between their applications, which is a central concept of the open source paradigm upon which Android is based. For instance, if you have coded a cool animated UI element, and you make this available to other applications, they can implement your class and use that element. And you do not need to have that code inside those other applications. As long as the application that contains the element's code is running (or can be launched) on the Android smartphone, you can call the method via the Android operating system.
There are four main types of components that can be (but do not need to be) used within an Android application:
Let's take a closer at each of these components, to prepare for the hands-on use of them in the rest of this book. Here, you'll get an overview of what Android is made up of, before we get into the details about class creation and such in later chapters.
An Android activity contains a UI construct that accomplishes a given user-input task via the smartphone display screen.
Android applications can have more than one activity. In fact, more complex applications usually have one activity for each UI screen implementation. For example, if you are programming a game, you might have the following activities:
The introductory splash screen with the Continue to Play Game OR Press Button to Play Game
The instructions screen, with a scrolling text UI
The high-score screen, with UI elements that allow the user to manage high-score entries
A player groups screen, where users choose who will play the game with them
The actual core gameplay screen itself
If an application has more than one activity, one is marked as the activity that is presented when the application is launched. In our game example, that is the splash screen (although it could be the instructions screen). This activity has an onCreate()
method that calls the main.xml file, as you saw in the Hello World application we created in the previous chapter.
Here is the code for the onCreate()
method from the Activity
base, or super, class (note the super
keyword) and sets the content View
to the main.xml UI definition:
public class MyHelloWorld extends Activity { /** Called when the activity is first created. */ @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); } }
An activity can be full screen, or it can be part of a screen, allowing for floating windows on top of other windows. An activity can also make use of other windows. For instance, an activity might show a pop-up dialog requesting that the user enter information, or it could display a product information window when a user clicks a product name or SKU.
We will get into Activity
class creation in all of the following chapters, and cover it specifically in Chapters 6 and 7,
Unlike activities, services do not have any visual UI (that's what an activity is for). Services handle the processing or heavy lifting for your application. They are often used for doing things that need to be done in the background or back end of the application, while the user works with your UI in the foreground or front end of your application.
Here are some examples of what service components can do:
Calculate numeric values
Process game logic
Play media elements such as video and audio streams
Pull data from remote network locations
Transfer data between devices via Bluetooth
Services handle calculations or processing that needs to be done in the background while the user is busy looking at the results of this processing on the activity-generated UI screen elements.
Not surprisingly, you create your own services in Android by subclassing the Android Service
class. Services can run in the background, even after an activity UI screen is no longer visible, such as when a user picks an MP3 audio file to play, and then does something else with the phone while listening to the music. We will take a look at using services in Chapter 11. There, you'll learn how to use a MediaPlayer to play audio and video streams in the background of your applications.
Broadcast receivers are communication components that receive messages that are sent between the Android operating system and other application components, or between Android application components themselves.
The Android operating system often sends out messages regarding the status of what is going on in real time with the Android phone itself. These are statuses that any Android application may want or even need to know about in order to protect the application integrity, such as if the phone is about to lose power and your app needs to save files.
The following are some examples of Android operating system-initiated broadcast messages:
A low battery life warning
A timezone change notice
A language preference change notice
A message that the camera has been used to snap a picture
And here are a couple examples of application-to-application broadcast messages:
An alert that data has finished downloading
A message that streaming video media has arrived, is cached, and is ready for the start of playback
Your application can implement as many broadcast receivers as you like, in order to intercept any of the types of messages that need to be monitored for your application's operation.
Like Android services, broadcast receivers operate in the background, and thus do not have any associated UI elements. However, this does not mean that the broadcast receivers cannot trigger or invoke a UI activity in response to the messages that they carry. In fact, it is common practice to have broadcast receivers trigger UI elements that alert the user as to what is going on within the application.
Broadcast receivers can also use the Android NotificationManager
class to alert the user via built-in phone notification methods, such as flashing the screen backlight, playing a sound, triggering phone vibrations, and placing a persistent alert icon on the smartphone status bar.
Broadcast receivers are created by extending the Android BroadcastReceiver
class. We will look at using them in Chapter 11.
Content providers in Android provide a way to make data available to your application and to other applications, if that is desired. This can be data that is created in and for your own application, or it can be data that can be accessed by your application, but that is created by other applications, or even by the Android phone utilities themselves. It can also be data that is created by your application and is made accessible to other applications. The content provider component is both powerful and flexible.
For example, an Android phone utility uses a content provider to access the phone number database that is kept within your smartphone. Android comes with a number of built-in content provider databases, including contacts, images, audio, and video. These can be accessed via phone system utilities, as well as by your applications through coding.
Content data can be stored in a file system on your SD card in your smartphone, off-phone in a remote HTTP server, or in a proper database. The latter is the preferred method for storing and accessing data within Android, and you'll see that in action in Chapter 10, which covers using content providers.
To create your own content provider, you extend the ContentProvider
base class, which implements a standard set of methods that are used to store and retrieve data. Applications access the methods defined by your ContentProvider
class with a ContentResolver
object, which is used to talk to any content provider, in order to navigate the data that is needed by the application.
A content provider is activated when it receives a request for data from a content resolver. The other three components—activities, services, and broadcast receivers—are activated via asynchronous messages called intents, which we'll look at next.
An Intent
object in Android holds the contents of a message that is sent between modules, typically to launch them or to send them new task instructions. For activities and services, an Intent
object provides an action to be taken, the data that the action needs to operate on, and optionally, some details or additional information that may be required for more complicated operations.
You communicate with each type of Android component (activity, service, and broadcast receiver) using a different set of methods to receive the Intent
object that is passed to it. For this reason, Intent
objects are easy to keep separate and well defined, as they will be different for each type of Android component.
The components use the Intent
object methods as follows:
An activity is started up, or if it's already started, given a new task, by passing an Intent
object to the Context.startActivity()
method. The Activity
class can look at the contents of the Intent
object via the getIntent()
method, and at subsequent intent objects via the onNewIntent()
method.
An Android service component is started by passing an Intent
object to the Context.startService()
method, which then calls the service class onStart()
method, and passes it the Intent
object that contains the actions for the service to perform and the data on which to perform them.
If the service is already running and the Intent
object contains new instructions, then the intent is passed to the Context.bindService()
method in order to establish an open connection between the calling component and the service that is being used. This always open, real-time connection between code modules is commonly called binding in programming.
An Android broadcast receiver component is started by passing an Intent
object to the Context.sendBroadcast()
method, or optionally to the Context.sendOrderedBroadcast()
method or Context.sendStickyBroadcast()
method. The Intent
object in this case contains the message action to be taken and the data (the message) on which that action needs to be taken.
We will look closely at using Intent
objects with activities in Chapter 11.
You have seen that Android needs to have a single XML file in your root project folder: AndroidManifest.xml, which is the file that Android uses to launch your application. The only other file in your project root folder is default.properties, which is generated by Eclipse and should never be modified. So, the only file in your project root folder that you ever need to worry about is AndroidManifest.xml.
The Android manifest uses XML for several good reasons:
It is easy to code.
It allows you to define a logical data structure that is easy for Android to parse (break down into logical data definition components) and understand.
It can exist outside your Java code, so that Android can access it before it starts looking at your Java code and asset resources.
The Android manifest XML file is essentially a road map for the Android operating system, telling it what your application is going to do, which components are needed, and what Android assets it needs permission to use within the Android smartphone operating environment.
When your application is launched initially, the AndroidManifest.xml data definitions are used by Android to set up areas of system resources and memory for application components that need to be supported. They also are used to define secure access permissions for the more sensitive areas of Android (such as private, internal smartphone databases) that you need to access with your application.
Let's take a look at the AndroidManifest.xml file for our Hello World app.
<?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="Hello.World" android:versionCode="1" android:versionName="1.0"> <application android:icon="@drawable/icon" android:label="@string/app_name"> <activity android:name=".MyHelloWorld" android:label="@string/app_name">
<intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> </application> <uses-sdk android:minSdkVersion="3" /> </manifest>
The opening line is the XML version and encoding declaration—standard fare inserted for us by Eclipse (as are other manifest entries). This is followed by the following tags:
<manifest>
: This tag has four standard attributes, including the Hello.World
package name that we entered in our New Android Project dialog. The xmlns:android
attribute points to the online definition of the Android XML schema and is also standard fare in all XML files. The other two attributes are the Android XML version code and name, which are version 1 and 1.0, respectively.
An XML schema definition is a road map as to what is allowed in a given XML file—that is, the structure that it must follow and the tags or attributes it may contain. Think of it as defining all of the rules that you need to follow for any given class of XML file, where the Android manifest is a certain class of XML that needs to conform to a set format.
<application>
: This tag's android:icon
attribute points to our icon.png file in our /drawable folder. The android:label
attribute points to our application name (the name that goes in the application title bar at the top of the smartphone screen) in the strings.xml file. Note that the <application>
tag is nested inside the <manifest>
tag. You can see nesting by looking at the order of the closing tags at the end of the manifest file structure.
<activity>
: Here, we declare our application's activity
class by specifying its name via the android:name
attribute as .MyHelloWorld
, which we also specified in our New Android Project dialog. Note that if we had a service class or broadcast receiver class, we would also declare them in this area of the manifest, along with their related <service>
and <receiver>
tags, as you will see in Chapter 11.
<intent-filter>
: This tag specifies the action and category of the Intent
object that launches our application. The action is android.intent.action.MAIN
, which launches main.xml. The category is android.intent.category.LAUNCHER
, which specifies that MyHelloWorld
is the activity that launches the application (because it is the activity that contains this <intent-filter>
tag).
<uses-sdk>
: This tag specifies our minimum SDK support level of Android 1.5 SDK 3 via the attribute named android:minSdkVersion
, which we also specified in our New Android Project dialog. This comes after the closing tags for the <application>, <activity>
, and <intent-filter>
tags.
After that, we close our <manifest>
tag, and we are finished declaring our Hello World application manifest XML file.
We will look at Android manifest files in later chapters that cover more advanced Android features, so you will be learning more about these tags before you are finished with this book.
This chapter gave you an overview of the Java and XML languages, as well as the various components of the Android operating system. We also looked at the AndroidManifest.xml file, which ties everything together when Android launches your application.
The main component of Java is the object, which contains fields, or states, and methods that operate on those states in order to change the attributes of the objects, just as in real life. This approach allows objects to mimic real-world objects and also to exhibit data encapsulation, which allows objects to be secure and self-contained. This modularization helps in testing and debugging, because problems can be localized more precisely.
Objects can be created using classes, which are programming code constructs that are used to define the object fields and methods, and thus their architecture. These classes define the initial, or default, fields for the objects that are created from them, as well as the programming code that defines methods for changing these default states as the program executes. We used a car example to demonstrate the different attributes and methods that would define a car object, such as acceleration, braking, steering, and gear shifting.
Classes can be used to create more detailed classes through a process called inheritance. Through inheritance, the original base class becomes a super class, and new, more finely detailed classes are subclassed from the base class to form different types of class definitions. In our car example, we created SUV and sportscar classes, which allowed us to create SUV and sportscar objects.
Once you have finished coding all of your classes, you can bundle them logically together in a package, which allows you to group your classes and even your application together as one logical, well, package. You use the import
statement to load Android packages and classes. The format import
platform
.package.classname
allows you to precisely specify which packages and classes you wish to include and use in your own applications.
We also took a look at XML, which uses tags to allow users to structure data. Tags can be nested to become subsets of other tags, and thus complicated and precise data structures can be created. Android uses XML so that some of the programming can be done in an easier language than Java. This allows nonprogrammers to become involved in the application design process.
The Android APK (.apk) file holds our application code binaries and resources in a compressed .zip file format. This includes the classes.dex Dalvik executable file and the Android manifest and application resources. Renaming the .apk file to .zip allows you to look inside the file and see its assets. Recently, file size limits for .apk files were increased from 25MB to 50MB.
Then we looked at Android application components. Android activity components hold your UI elements and are the front end of your applications to your end users. Android services define your processing routines and are the back ends of your applications. Android broadcast receivers send messages between your application components and are your intercomponent application messengers. Android content providers store and distribute your application data within your application to other applications and to the Android operating system itself.
We next looked at Android Intent
objects. These are our task managers. They send instructions between our application components as to which actions to perform and on which data to perform them.
Finally, we covered the Android manifest file, AndroidManifest.xml. This file defines to the Android operating system how to start up your application, including which components will be used and which permissions and SDK levels your application will support on various model smartphones.
All of the concepts in this chapter will be covered in detail in the remaining chapters of this book.
44.200.94.150