52862.fb2
Android devices, by and large, will be mobile phones. While the Android technology is being discussed for use in other areas (e.g., car dashboard “PCs”), for the most part, you can think of Android as being used on phones.
For developers, this has benefits and drawbacks.
On the plus side, circa 2009, Android-style smartphones are sexy. Offering Internet services over mobile devices dates back to the mid-1990s and the Handheld Device Markup Language (HDML). However, only in recent years have phones capable of Internet access taken off. Now, thanks to trends like text messaging and to products like Apple’s iPhone, phones that can serve as Internet access devices are rapidly gaining popularity. So, working on Android applications gives you experience with an interesting technology (Android) in a fast-moving market segment (Internet-enabled phones), which is always a good thing.
The problem comes when you actually have to program the darn things.
Anyone with experience in programming for PDAs or phones has felt the pain of phones simply being small in all sorts of dimensions:
• Screens are small (you won’t get comments like, “Is that a 24-inch LCD in your pocket, or …?”).
• Keyboards, if they exist, are small.
• Pointing devices, if they exist, are annoying (as anyone who has lost their stylus will tell you) or inexact (large fingers and “multi-touch” LCDs are not a good mix).
• CPU speed and memory are tight compared to desktops and servers you may be used to.
• You can have any programming language and development framework you want, so long as it was what the device manufacturer chose and burned into the phone’s silicon.
• And, so on …
Moreover, applications running on a phone have to deal with the fact that they’re on a phone.
People with mobile phones tend to get very irritated when their phones don’t work, which is why the “Can you hear me now?” ad campaign from Verizon Wireless has been popular for the past few years. Similarly, those same people will get irritated at you if your program “breaks” their phone by
• tying up the CPU so that calls can’t be received
• not working properly with the rest of the phone’s OS, such that your application doesn’t quietly fade to the background when a call comes in or needs to be placed
• crashing the phone’s operating system, such as by leaking memory like a sieve
Hence, developing programs for a phone is a different experience than developing desktop applications, Web sites, or back-end server processes. You wind up with different-looking tools, different-behaving frameworks, and “different than you’re used to” limitations on what you can do with your program.
What Android tries to do is meet you halfway:
• You get a commonly-used programming language (Java) with some commonly used libraries (e.g., some Apache Commons APIs) along with support for tools you may be used to (Eclipse).
• You get a fairly rigid and separate framework in which your programs need to run so they can be “good citizens” on the phone and not interfere with other programs or the operation of the phone itself.
As you may expect, much of this book deals with that framework and how you write programs that work within its confines and take advantage of its capabilities.
When you write a desktop application, you are “master of your own domain.” You launch your main window and any child windows — like dialog boxes — that are needed. From your standpoint, you are your own world, leveraging features supported by the operating system, but largely ignorant of any other program that may be running on the computer at the same time. If you do interact with other programs, it is typically through an API, such as using JDBC (or frameworks atop it) to communicate with MySQL or another database.
Android has similar concepts, but packaged differently, and structured to make phones more crash-resistant.
The building block of the user interface is the activity. You can think of an activity as being the Android analogue for the window or dialog in a desktop application.
While it is possible for activities to not have a user interface, most likely your “headless” code will be packaged in the form of content providers or services, like the following described.
Content providers provide a level of abstraction for any data stored on the device that is accessible by multiple applications. The Android development model encourages you to make your own data available to other applications, as well as your own — building a content provider lets you do that, while maintaining complete control over how your data gets accessed.
Intents are system messages, running around the inside of the device, notifying applications of various events, from hardware state changes (e.g., an SD card was inserted), to incoming data (e.g., an SMS message arrived), to application events (e.g., your activity was launched from the device’s main menu). Not only can you respond to intents, but you can create your own, to launch other activities, or to let you know when specific situations arise (e.g., raise such-and-so intent when the user gets within 100 meters of this-and-such location).
Activities, content providers, and intent receivers are all short-lived and can be shut down at any time. Services, on the other hand, are designed to keep running, if needed, independent of any activity. You might use a service for checking for updates to an RSS feed, or to play back music even if the controlling activity is no longer operating.
Android comes with a number of features to help you develop applications.
You can package data files with your application, for things that do not change, such as icons or help files. You also can carve out a small bit of space on the device itself, for databases or files containing user-entered or retrieved data needed by your application. If the user supplies bulk storage, like an SD card, you can read and write files on there as needed.
Android devices will generally be Internet-ready, through one communications medium or another. You can take advantage of the Internet access at any level you wish, from raw Java sockets all the way up to a built-in WebKit-based Web browser widget you can embed in your application.
Android devices have the ability to play back and record audio and video. While the specifics may vary from device to device, you can query the device to learn its capabilities and then take advantage of the multimedia capabilities as you see fit, whether that is to play back music, take pictures with the camera, or use the microphone for audio note-taking.
Android devices will frequently have access to location providers, such as GPS, that can tell your applications where the device is on the face of the Earth. In turn, you can display maps or otherwise take advantage of the location data, such as tracking a device’s movements if the device has been stolen.
Of course, Android devices are typically phones, allowing your software to initiate calls, send and receive SMS messages, and everything else you expect from a modern bit of telephony technology.
The Android build system is organized around a specific directory tree structure for your Android project, much like any other Java project. The specifics, though, are fairly unique to Android and what it does to prepare the actual application that will run on the device or emulator. Here’s a quick primer on the project structure to help you make sense of it all, particularly for the sample code referenced in this book, which can be found in the Source Code area of the Apress Web Site at http://apress.com.
When you create a new Android project (e.g., via the activitycreator
script, which you will see in Chapter 4, or an Android-enabled IDE), you get several items in the project’s root directory:
• AndroidManifest.xml
, an XML file describing the application being built and what components — activities, services, etc. — are being supplied by that application
• build.xml
, an Ant[5] script for compiling the application and installing it on the device
• default.properties
, a property file used by the Ant build script
• bin/
holds the application once it is compiled
• libs/
holds any third-party Java JARs your application requires
• src/
holds the Java source code for the application
• res/
holds resources, such as icons, GUI layouts, and the like, that get packaged with the compiled Java in the application
• assets/
holds other static files you wish packaged with the application for deployment onto the device
When you create an Android project (e.g., via activitycreator
), you supply the fully-qualified class name of the “main” activity for the application (e.g., com.commonsware.android.SomeDemo
). You will then find that your project’s src/
tree already has the namespace directory tree in place, plus a stub Activity subclass representing your main activity (e.g., src/com/commonsware/android/SomeDemo.java
). You are welcome to modify this file and add others to the src/
tree as needed to implement your application.
The first time you compile the project (e.g., via ant), out in the “main” activity’s namespace directory, the Android build chain will create R.java
. This contains a number of constants tied to the various resources you placed out in the res/
directory tree. You should not modify R.java
yourself, letting the Android tools handle it for you. You will see throughout many of the samples where we reference things in R.java
(e.g., referring to a layout’s identifier via R.layout.main
).
As already mentioned, the res/
directory tree holds resources — static files that are packaged along with your application, either in their original form or, occasionally, in a preprocessed form. Some of the subdirectories you will find or create under res/
include
• res/drawable/
for images (PNG, JPEG, etc.)
• res/layout/
for XML-based UI layout specifications
• res/menu/
for XML-based menu specifications
• res/raw/
for general-purpose files (e.g., a CSV file of account information)
• res/values/
for strings, dimensions, and the like
• res/xml/
for other general-purpose XML files you wish to ship
We will cover all of these and more in later chapters of this book, particularly Chapter 19.
When you compile your project (via ant or the IDE), the results go into the bin/ directory under your project root, specifically:
• bin/classes/
holds the compiled Java classes
• bin/classes.dex
holds the executable created from those compiled Java classes
• bin/yourapp.ap_
holds your application’s resources, packaged as a ZIP file (where yourapp
is the name of your application)
• bin/yourapp-debug.apk
or bin/yourapp-unsigned.apk
is the actual Android application (where yourapp
is the name of your application)
The .apk
file is a ZIP archive containing the .dex
file, the compiled edition of your resources (resources.arsc
), any un-compiled resources (such as what you put in res/raw/
) and the AndroidManifest.xml
file. It is also digitally signed, with the -debug
portion of the filename indicating it has been signed using a debug key that works with the emulator, or -unsigned
indicating that you built your application for release (ant release), but the APK still needs to be signed using jarsigner
and an official key.
The foundation for any Android application is the manifest file: AndroidManifest.xml
in the root of your project. Here is where you declare what is inside your application — the activities, the services, and so on. You also indicate how these pieces attach themselves to the overall Android system; for example, you indicate which activity (or activities) should appear on the device’s main menu (aka the launcher).
When you create your application, you will get a starter manifest generated for you. For a simple application, offering a single activity and nothing else, the auto-generated manifest will probably work out fine, or perhaps require a few minor modifications. On the other end of the spectrum, the manifest file for the Android API demo suite is over 1,000 lines long. Your production Android applications will probably fall somewhere in the middle.
Most of the interesting bits of the manifest will be described in greater detail in the chapters on their associated Android features. For example, the service
element is described in greater detail in Chapter 30. For now, you just need to understand what the role of the manifest is and its general construction.
The root of all manifest files is, not surprisingly, a manifest
element:
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.commonsware.android.search">
...
</manifest>
Note the namespace declaration. Curiously, the generated manifests apply it only on the attributes, not the elements (e.g., it’s manifest
, not android:manifest
). However, that pattern works, so unless Android changes, stick with their pattern.
The biggest piece of information you need to supply on the manifest element is the package
attribute (also curiously not namespaced). Here you can provide the name of the Java package that will be considered the “base” of your application. Then, everywhere else in the manifest file that needs a class name, you can just substitute a leading dot as shorthand for the package. For example, if you needed to refer to com.commonsware.android.search.Snicklefritz
in our example manifest, you could just use .Snicklefritz
since com.commonsware.android.search
is defined as the application’s package.
Underneath the manifest element, you will find the following:
• uses-permission
elements to indicate what permissions your application will need in order to function properly. See Chapter 29 for more details.
• permission
elements to declare permissions that activities or services might require other applications hold in order to use your application’s data or logic. Again, more details are forthcoming in Chapter 29.
• instrumentation
elements to indicate code that should be invoked on key system events, such as starting up activities, for the purposes of logging or monitoring.
• uses-library
elements to hook in optional Android components, such as mapping services
• Possibly a uses-sdk
element to indicate what version of the Android SDK the application was built for.
• An application
element defining the guts of the application that the manifest describes.
In the following example the manifest has uses-permission elements to indicate some device capabilities the application will need — in this case, permissions to allow the application to determine its current location. And there is the application element, whose contents will describe the activities, services, and whatnot that make up the bulk of the application itself.
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.commonsware.android">
<uses-permission
android:name="android.permission.ACCESS_LOCATION" />
<uses-permission
android:name="android.permission.ACCESS_GPS" />
<uses-permission
android:name="android.permission.ACCESS_ASSISTED_GPS" />
<uses-permission
android:name="android.permission.ACCESS_CELL_ID" />
<application>
...
</application>
</manifest>
The real meat of the manifest file is the children of the application
element.
By default, when you create a new Android project, you get a single activity
element:
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.commonsware.android.skeleton">
<application>
<activity android:name=".Now" android:label="Now">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>
This element supplies android:name
for the class implementing the activity, android:label
for the display name of the activity, and (frequently) an intent-filter
child element describing under what conditions this activity will be displayed. The stock activity
element sets up your activity to appear in the launcher, so users can choose to run it. As you’ll see later in this book, you can have several activities in one project if you so choose.
You may also have one or more receiver elements indicating non-activities that should be triggered under certain conditions, such as when an SMS message comes in. These are called intent receivers and are described in Chapter 23.
You may have one or more provider elements indicating content providers — components that supply data to your activities and, with your permission, other activities in other applications on the device. These wrap up databases or other data stores into a single API that any application can use. Later you’ll see how to create content providers and how to use content providers that you or others create.
Finally, you may have one or more service elements describing services — long-running pieces of code that can operate independent of any activity. The quintessential example is the MP3 player, where you want the music to keep playing even if the user pops open other activities and the MP3 player’s user interface is “misplaced.” Chapters 30 and 31 cover how to create and use services.
Android, like most operating systems, goes through various revisions, versions, and changes. Some of these affect the Android SDK, meaning there are new classes, methods, or parameters you can use that you could not in previous versions of the SDK.
If you want to ensure your application is run only on devices that have a certain version (or higher) of the Android environment, you will want to add a uses-sdk element as a child of the root manifest
element in your AndroidManifest.xml
file. The uses-sdk
element has one attribute, minSdkVersion
, indicating which SDK version your application requires:
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.commonsware.android.search">
<uses-sdk minSdkVersion="2" />
...
</manifest>
At the time of this writing, there are two possible minSdkVersion
values:
• 1, indicating the original Android 1.0 SDK
• 2, indicating the Android 1.1 SDK
If you leave the uses-sdk
element out entirely, it will behave as though minSdkVersion
is set to 1.
If you set uses-sdk
, the application will install only on compatible devices. You do not have to specify the latest SDK, but if you choose an older one, it is up to you to ensure your application works on every SDK version you claim is compatible. For example, if you leave off uses-sdk
, in effect you are stipulating that your application works on every Android SDK version ever released, and it is up to you to test your application to determine if this is indeed the case.
http://ant.apache.org/