Android Framework Overview
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 when referring 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 was designed for use on potentially massive computer networks, such as vast collections of blade computers that are used to run large enterprises or corporations with thousands of active users, although Java EE also can be run on smaller installations as well as long as they have enough system memory and a couple of processing cores. Its differentiating features beyond Java SE are that Java EE features more multiuser scalable functionality than Java SE, which is designed more for a single user on a single computer system, say a home PC or a laptop, or better yet, an Android device such as an iTV set, e-book e-reader, tablet, or smartphone.
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 standard mobile phone (usually termed a “feature phone” today) without using too much memory and resources to run it. Most entry-level mobile phones (flip-phones) run Java ME, but Android smartphones 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 touchscreen 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 which are used to build applications that are easier to share and debug due to implementing 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, as you saw firsthand in Chapter 4 when you built your first Android application. Without XML, you would need to rely solely on Java code to define everything, which would make developing apps a lot more complicated, especially for the design department.
Finally, we’ll cover the main parts of the Android framework, and you will be able to see the object-oriented programming (OOP) underpinnings that Android supports. We’ll briefly cover each component and explain which chapter covers it in more detail.
The Foundation of OOP: The Object
The foundation of OOP is the object itself. Objects in OOP languages are similar to objects that you see around you every day, except they are virtual and not tangible. As with tangible real-world objects, Java objects have characteristics, called states, and things that they can do, called behaviors. One way to think about this is that objects are nouns, or things that exist in and of themselves, and behaviors are like verbs, or things that nouns do.
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:
The following are some things that a car can do, or behaviors:
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.
Figure 5-1 . Car object showing car characteristics (inner oval) and car behaviors (outer oval)
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 that you use every day is the multilevel directory or folder structure on your computer’s 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. We saw a great example of this in Chapter 4, where our Eclipse Workspace folder was in our Users folder, our HelloAbsoluteBeginner project folder was in our Workspace folder, and our Launch Icons were in Resource (Drawable) folders within that HelloAbsoluteBeginner project folder!
You can do this same hierarchical construction with objects that 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 underneath that object type.
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 with the Java programming language and the XML markup language. It is important to note that both Java and XML can be used to define objects for Android applications. We already defined a TextView resource object having six characteristics in Chapter 4 using XML (see lucky Figure 4-13 for that object definition).
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.
Some OOP Terminology
Now let’s cover some of the technical terminology used for Java objects. First, objects have fields and methods, as follows:
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 object 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 time and 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 added or removed modularly during testing to ascertain where bugs are located within the overall code. In our car object example, the attributes of our car are encapsulated inside of the car object, and can thus be changed only via the methods that surround them in each diagram. For instance, one would use the Shift Gears method to change the Gears=1 field variable to Gears=2.
The Blueprint for an Object: The Class
In real life, there is seldom just a single type 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 type of blueprint as to what the object is, what states it contains, and what it can do (what methods it has).
Note 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.
Note Semicolons are used in programming languages to separate each code construct or definition from the other ones within 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 also can 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 with which to work.
Note 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(). Read more about naming conventions for Java at: http://www.oracle.com/technetwork/java/codeconv-138413.html
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 is then 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.
Note 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:
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;
}
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.
For us to create an instance of an object, we must 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.activity_car);
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");
}
On 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:
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:
objectName.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. Also note that you can place comments in your code by preceding them with two forward slashes. When the compiler sees this it ignores anything after the two slashes until the end of that line.
Providing Structure for Your Classes: Inheritance
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 superclass. There can be only one superclass, but there can be an unlimited number of subclasses. All of the subclasses inherit the methods and fields from the superclass.
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 turnTowLightOn() 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.
Figure 5-2 . Inheritance of a Car object superclass to create SUV and SPORT Car subclasses
To create a subclass from a superclass, you extend the subclass from the superclass using the extends keyword in the class declaration, as in the following:
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. Because the original core fields and methods come from the Car class, it becomes the superclass, and the Suv class becomes the subclass. Suv is said to be subclassed from the Car superclass.
To refer to one of the superclass 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 because the SUV applyBrake() method first calls the applyBrake() of the superclass via the super.applyBrake(brakingFactor); line of the method and then again decrements the speed variable by the brakingFactor a second time, making the brakes twice as powerful or effective.
Be sure to use good programming practices and refer to Javadoc documentation for the superclass fields and methods within each subclass. This documentation lets the users know that the superclass’s fields and methods are available because they do not explicitly appear in the code for the subclass.
Defining an Interface
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;
}
}
Adding the public keyword before the void 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 (more accurately any class) should be able to use it.
Bundling Classes in a Logical Way: The Package
Each time you start a new project in Android, the Eclipse IDE will create a package to contain your own custom classes that you will define to implement your application’s functionality. In the Hello Absolute Beginner application that we created in the previous chapter, our package was named first.example.helloabsolutebeginner. In fact, the New Project Android Application 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 Absolute Beginner application:
package first.example.helloabsolutebeginner;
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, or in the case of Android applications, API code that serves up functionality available within the Android operating system (OS).
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. Each Android API Level (Level 16 for the current Android Jelly Bean OS version 4.1) contains a collection of functional packages that are used by developers to access its feature set.
In our Hello Absolute Beginner application in the previous chapter, we needed the following import statements in our HelloActivity.java file to support class functions in our application:
import android.os.Bundle;
import android.app.Activity;
import android.view.Menu;
This is basically to address where the code for each import statement is located. Here is a generalization of how an import statement follows a path to the class:
import platform. functionality. classname;
This applies to our statement as follows:
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 OS applications, and one of these is the Activity class, which allows us to define UIs, and the other is the Bundle class from the android.os package that allows us to bundle up application variables. Both of these can be seen in our Chapter 4 Java code in the Eclipse IDE by clicking the plus (+) symbol next to the import statements.
You may 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) level. 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. Android 4.1 Jelly Bean API Level 16 is the sixteenth Android Platform to be released so far and it contains a great many packages with which to define it’s total functionality.
An Overview of XML
There are actually two types of languages used in Android development: Java and XML. XML stands for eXtensible Markup Language. Developed in 1996, XML is similar to HTML (which stands for Hyper-Text Markup Language), which is used for website 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. Remember that the values must be inside quotation marks to be validated (passed over to) the XML processor (parser). Like this:
<string name=”string_name_here”>This is the Value of the String Here</string>
Note 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 that 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 XML color element or parameter.
In our Hello Absolute Beginners application in Chapter 4, we defined four string resources with the following XML in the strings.xml file:
<resources>
<string name="app_name">HelloAbsoluteBeginner</string>
<string name="hello_world">Hello Absolute Beginner!</string>
<string name="menu_settings">Settings</string>
<string name="title_activity_hello">HelloActivity</string>
</resources>
You can readily see the modularity via the nesting of tags. The <resources> tag contains the four <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 the more complicated Java code environment. 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.
XML constructs can be turned into Java constructs by a process called “inflating,” which we actually got a taste of in the Java code in our HelloAbsoluteBeginner application that created (inflated) the Options Menu using our activity_hello.xml menu definition via the line of code that reads:
getMenuInflater().inflate(R.menu.activity_hello, menu);
Because XML is easier to use than Java, and because this is a book for absolute 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 Anatomy of an Android Application: The APK File
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, now branded as “Google Play” increased APK file size limits for .apk files from 25MB to 50MB, which is great news for developers. Using something called “expansion files” as of May 2012 an application can now support up to 4GB (4,000 Megabytes) of data beyond the 50MB APK file that holds your application and its primary assets. Two additional expansion files of up to 2GB each can be accessed from your application’s APK file, but that said, the smaller you can get your application, the faster it will download, and the smoother it will function across consumer electronics devices. Also, if you have 4GB of extra application data, be aware that your users will have to use the space on their Android device’s SD card to store this data, which may well use up valuable space that they may want or need for other purposes.
So, back to learning about APK. If your application is called Zoomerza, for instance, the file that you will get on final publishing will be called Zoomerza.apk, and it will run on any Android phone, iTV, e-reader, or tablet. This file format is closely related to the standard Java .jar format, and uses the familiar ZIP type of data compression. The .apk file is specifically set up so that it can be run in place (as is) without going through any data unpacking processing.
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 because you are using a nondestructive “Read” operation and not writing or rewriting (overwriting) the APK file.
If you have Windows Vista, Windows 7, or Windows 8, the ZIP functionality is built into the operating system. An easy way to see your .apk file is to rename it as a .zip extension and open it inside the Windows Explorer file management utility. By now you should know how to find your Workspace Folder and HelloAbsoluteBeginner Project Folder. The HelloAbsoluteBeginner.apk file will be in the /bin subfolder under the main project folder. Bin stands for “Binary” an early term for “Executable” files, and as expected in this folder we have the Android executable APK file and the “classes.dex” Dalvik executable class files needed for the App. The Windows 7 Explorer and the folders (path) to the file, as well as the /bin folder contents and the right-click menu (right-click on the APK file) and rename option are all shown in Figure 5-3.
Figure 5-3 . Renaming an APK file to a ZIP file using the right-click on filename Rename option in Windows 7
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 it the easy way here using just the Windows 7 Explorer utility, so you can see what I’m talking about.
Figure 5-4 . Confirm an intent to rename a APK file to a ZIP file so we can look inside it
Figure 5-5 . Viewing the internal file structure of our recently renamed HelloWorldAndroid.zip
As shown in Figure 5-5, the application includes an AndroidManifest.xml file and a classes.dex file. It also contains the /res folder with all of the /drawable subfolders as well as the /menu and /layout subfolders, which hold and organize the various application assets we used to develop the HelloAbsoluteBeginner Android 4.1 application.
Android Application Components
Android is designed to afford developers with the maximum amount of modularity possible. This modularity makes it easy for developers to exchange functionality between their applications, which is a central concept of the open source paradigm on 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 in their own apps. You do not even need to have that code located 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 their hands-on use during the rest of this book. Here, you’ll get an overview of what Android is made of, before we get into the details about class creation and more advanced topics in later chapters.
Android Activities: Defining the UI
An Android activity contains a UI construct that accomplishes a given user-input task via the smartphone, tablet, e-reader, or iTV 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:
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 activity_hello.xml file, as you saw in the Hello Absolute Beginner application we created in the previous chapter. For a game, this might be named activity_splash.xml.
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 activity_hello.xml UI definition:
public class HelloAbsoluteBeginner extends Activity {
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_hello);
}
}
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 learn how to code each of these Activity scenarios, and much more, throughout the remainder of this book.
We will get into Activity class creation in all of the following chapters, and cover it specifically in Chapters 6, 7, and 8 next.
Android Services: Processing in the Background
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:
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 closer 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: Announcements and Notifications
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 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:
And here are a couple examples of application-to-application broadcast messages:
Your application can implement as many broadcast receivers as you like 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: Data Management
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 operating system utilities themselves to provide useful services to smartphone, tablet, e-reader, and iTV users. It can also be data that is created by your application and is then made accessible to other Android applications. The content provider component is both powerful and flexible in its ability to create, control, and manage data assets.
For example, an Android phone utility uses a content provider to access the Contacts database that is kept within your smartphone, tablet, e-reader, or iTV set. Android comes with a number of built-in content provider databases, including contacts, images, audio, and video, among others. These can be accessed via Android operating system utilities, as well as by your applications through your custom Java coding.
Content data can be stored in a file system on your SD card in your smartphone, tablet, e-reader, or iTV, off-device in a remote HTTP server, or in a proper SQLite 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 via Android’s built-in SQLite functionality.
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, to navigate through the data in the database that is needed by the application.
A content provider is activated when it receives a request for data from a content resolver, which you will see in detail as we cover Content Providers in Chapter 10. The other three components—activities, services, and broadcast receivers—are activated via asynchronous messages called intents, which we’ll look at next, and again in greater detail in Chapter 11.
Android Intent Objects: Messaging for Components
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:
We will look very closely at using Intent objects with activities later on in Chapter 11.
Android Manifest XML: Declaring Your Components
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. As you saw in Figure 5-5 earlier in this chapter, the AndroidManifest.xml is also in the resulting APK file that holds your application code and resources, so it is obviously a very important file.
The Android manifest uses XML for several good reasons:
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 will be needed, and which Android assets it needs permission to use within the Android operating system 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 needed for application components that will need to be supported. AndroidManifest.xml also is used to define secure access permissions for the more sensitive areas of the Android operating system (such as private, internal operating system databases) that you will need to access with your application.
Let’s take a look at the AndroidManifest.xml file for our Hello Absolute Beginner app.
<manifest xmlns:android="http://schemas.android.com/apk/res/android "
package="first.example.helloabsolutebeginner"
android:versionCode="1"
android:versionName="1.0">
<uses-sdk android:minSdkVersion="8" />
<uses-sdk android:targetSdkVersion="16" />
<application android:icon="@drawable/ic_launcher"
android:label="@string/app_name"
android:theme="@style/AppTheme" >
<activity android:name=".HelloActivity"
android:label="@string/title_activity_hello">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>
The opening parameter of the manifest tag is the XML schema version and encoding declaration—standard fare inserted for us by Eclipse (as are the other manifest entries). This is followed by the following tags:
Note 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 in which the Android manifest is a certain class of XML for use with Android development that needs to conform to a set format and rules.
After closing the <application>, <activity>, and <intent-filter> tags (in reverse order, of course, so they are nested properly, we close our <manifest> tag, and we are finished declaring our Hello Absolute Beginner 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.
Summary
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 and is utilized when Android initially launches your application.
The main component of Java is the object, which contains fields, or states, and methods that operate on those object states to change the attributes of the object, just as in real life.
This object-oriented programming, or OOP, approach allows objects to mimic real-world objects, and also allows data encapsulation, which helps us to develop and code objects that are more secure and self-contained. This modularization helps in testing and debugging, especially with more complex programming projects 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 the object 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 superclass, 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 sports car classes, which allowed us to create SUV and sports car 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 Java 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 classes file and the Android manifest XML file and the 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, and by using two external 2GB expansion files Android applications can now be as large as 4GB!
Next we looked at Android application components. Android activity components hold your application’s UI elements, and are the front-end of your application to your end users; let’s call them your application’s “eyes,” as they let users “see” your application’s content. Android services define your processing routines, and are the back end of your applications; let’s call them your application’s “brain,” as they do the thinking (processing) for your app. Android broadcast receivers send messages between your application components and are your intercomponent application messengers; let’s call them your application’s “mouth and ears” because they do the communicating for your app. Android content providers store and distribute your application data within your application to other applications and to the Android operating system itself; let’s call them your application’s “memory” because they store things away long-term for your app.
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. Using our analogy from the previous paragraph, think of these as the neurons that fire in your app’s “brain” and carry thoughts (intents) and impulses from one part of your app’s “brain” to another.
Finally, we covered the all-important Android manifest XML file, AndroidManifest.xml. This file defines for the Android operating system exactly 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, tablets, e-readers, and iTV sets.
All of the concepts in this chapter will be covered again in greater detail in the remaining chapters of this book, so by the end of the book, you will have gone from Absolute Beginner to Android Applications Programmer!
44.200.94.150