One of the first “killer apps” for Ajax was Google Maps.6 Using Java-Script and the XmlHttpRequestobject, Google engineers created a drag-gable, zoomable, silky smooth map viewer that ran in any modern web browser without a plug-in. The idea was quickly copied by other ven-dors such as Microsoft and Yahoo, but the Google version is arguably still the best.
You can use these web-based maps in Android, perhaps with an embed-ded WebViewcontrol as discussed in Section7.2, Web with a View, on page135. But the architecture of your application would be overly con-voluted. That’s why Google created theMapViewcontrol.
Embedding a MapView
A MapViewcan be embedded directly in your Android application with just a few lines of code. Most of the functionality of Google Maps, plus hooks for adding your own touches, is provided (see Figure8.3, on the following page).
TheMapViewclass can also tie into your location and sensor providers.
It can show your current location on the map and even display a com-pass showing what direction you’re heading. Let’s create a sample pro-gram to demonstrate a few of its capabilities.
First create a “Hello, Android” application using these values in the wizard:
Project name: MyMap
Build Target: Google APIs (Platform: 2.2) Application name: MyMap
Package name: org.example.mymap Create Activity: MyMap
Min SDK Version: 8
Note that we’re using the “Google APIs” build target instead of the
“Android 2.2” target. That’s because the Google Maps APIs are not part of the normal Android distribution. Edit the layout file, and replace it with aMapViewthat takes over the whole screen.
6. http://maps.google.com
BIRD’S-EYE VIEW 173
Figure 8.3: Embedded map showing your current location
Download MyMap/res/layout/main.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/frame"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent">
<com.google.android.maps.MapView android:id="@+id/map"
android:apiKey="MapAPIKey"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:clickable="true" />
</LinearLayout>
Substitute MapAPIKey with a Google Maps API key that you get from Google.7 Note that we have to use the fully qualified name (com.google.
7. http://code.google.com/android/maps-api-signup.html
android.maps.MapView) because MapView is not a standard Android class. We also need to stick a <uses-library>tag in the <application>
element ofAndroidManifest.xml:
Download MyMap/AndroidManifest.xml
<uses-sdk android:minSdkVersion="3" android:targetSdkVersion="8" />
</manifest>
If you leave out the <uses-library> tag, you will get a ClassNotFoundEx-ceptionat runtime.
In addition to the fine- and coarse-grained location providers, the Map-View class needs Internet access so that it can call Google’s servers to get the map image tiles. These will be cached in your application directory automatically.
Here’s the outline of theMyMapclass:
Download MyMap/src/org/example/mymap/MyMap.java
BIRD’S-EYE VIEW 175
public class MyMap extends MapActivity { private MapView map;
private MapController controller;
@Override
public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState);
protected boolean isRouteDisplayed() { // Required by MapActivity
return false;
} }
The most important part is that your activity has to extendMapActivity. TheMapActivityclass spins up the background threads, connects to the Internet for tile data, handles caching, does animations, takes care of the life cycle, and much more. All you need to do is properly set it up and let it go.
Getting Ready
The first thing we need to do is call findViewById( ) to get access to the MapViewand its container. We can do that in theinitMapView( ) method:
Download MyMap/src/org/example/mymap/MyMap.java
private void initMapView() {
map = (MapView) findViewById(R.id.map);
controller = map.getController();
map.setSatellite(true);
map.setBuiltInZoomControls(true);
}
ThegetController( ) method returns aMapControllerthat we’ll use to posi-tion and zoom the map. setSatellite( ) switches the map into satellite mode, andsetBuiltInZoomControls( )8turns on the standard zoom controls.
TheMapViewclass will take care of making the controls visible when the user pans the map and will take care of fading them out slowly when panning stops.
The last step is to tell theMapViewto follow your position in the initMy-Location( ) method.
8. Introduced in Android 1.5.
Joe Asks. . .
Why Is MapView in the com.google.android.maps Package and Not android.maps?
Any code in theandroid.*packages is part of the Android core.
It’s open source and available on every Android device. By contrast, maps are proprietary to Google and to the data providers that Google paid for the geological information and imagery. Google provides the API free of charge as long as you agree to certain conditions.∗ If you’re not happy with the restrictions, you can roll your own views and find your own data sources, but it’s not going to be easy or cheap.
∗. http://code.google.com/apis/maps/terms.html
Download MyMap/src/org/example/mymap/MyMap.java
private void initMyLocation() {
final MyLocationOverlay overlay = new MyLocationOverlay(this, map);
overlay.enableMyLocation();
//overlay.enableCompass(); // does not work in emulator overlay.runOnFirstFix(new Runnable() {
public void run() {
// Zoom in to current location controller.setZoom(8);
Android provides aMyLocationOverlayclass that does most of the heavy lifting. An overlay is just something that is drawn on top of the map, which in this case is a pulsing dot showing your current location. You call enableMyLocation( ) to tell the overlay to start listening to location updates and callenableCompass( ) to tell it to start listening to updates from the compass.
The runOnFirstFix( ) method tells the overlay what to do the first time it gets a position reading from the location provider. In this case, we set the zoom level and then start an animation that moves the map from wherever it’s pointing now to where you are located.
If you run the program now, you should see something like Figure8.3,
FAST-FORWARD>> 177
and use the zoom buttons to get a closer look. When you walk around carrying the phone, the dot on the map should follow you.
Emulation Notes
The first time you run theMyMapprogram on the emulator you may get an Android AVD Error. Follow the directions in Section1.3, Creating an AVD, on page23to create a new AVD for the “Google APIs (Google Inc.) - API Level 8” build target called “em22google.”
On the emulator, you’ll initially see a zoomed-out map of the world and no dot for your current location. As before, use the Emulator Control view in Eclipse (or in the stand-alone DDMS program) to feed fake GPS data to the sample application.
When running in the emulator, the compass inset will not be shown because the compass sensor is not emulated.
8.4 Fast-Forward >>
This chapter introduced you to the exciting new world of location- and environmental-aware mobile computing. These technologies, in combi-nation with trends such as the adoption of broadband mobile Inter-net and the exponential growth of computing power and storage, are going to revolutionize the way we interact with computers and with each other.
Another way to perceive the world is by looking and listening. Android provides the Camera class9 for taking photographs using the built-in camera (if there is one), but you can also use it to do other things like make a bar-code reader. TheMediaRecorderclass10allows you to record and store audio clips. These are beyond the scope of this book, but if you need them for your program, consult the online documentation.
Speaking of storage, the next chapter will show you how to use SQL to store structured information (for example, a travel log of locations, photographs, and notes) locally on your mobile phone. If that’s not your area of interest, you can skip ahead to Chapter 10, 3D Graphics in OpenGL, on page 198 and learn how to unlock Android’s hidden 3D graphics potential.
9. http://d.android.com/reference/android/hardware/Camera.html 10. http://d.android.com/reference/android/media/MediaRecorder.html
Putting SQL to Work
In Chapter 6, Storing Local Data, on page 120, we explored keeping data around in preferences and in plain files. That works fine when the amount of data is small or when the data is all one type (such as a picture or an audio file). However, there is a better way to store large amounts of structured data: a relational database.
For the past thirty years, databases have been a staple of enterprise application development, but until recently they were too expensive and unwieldy for smaller-scale use. That is changing with small embedded engines such as the one included with the Android platform.
This chapter will show you how to use Android’s embedded database engine, SQLite. You’ll also learn how to use Android’s data binding to connect your data sources to your user interface. Finally, you’ll look at theContentProviderclass, which allows two applications to share the same data.
9.1 Introducing SQLite
SQLite1 is a tiny yet powerful database engine created by Dr. Richard Hipp in 2000. It is arguably the most widely deployed SQL database engine in the world. Besides Android, SQLite can be found in the Apple iPhone, Symbian phones, Mozilla Firefox, Skype, PHP, Adobe AIR, Mac OS X, Solaris, and many other places.
1. http://www.sqlite.org
SQL 101 179
SQLite License
The SQLite source code contains no license because it is in the public domain. Instead of a license, the source offers you this blessing:
May you do good and not evil.
May you find forgiveness for yourself and forgive others.
May you share freely, never taking more than you give.
There are three reasons why it is so popular:
• It’s free. The authors have placed it in the public domain and don’t charge for its use.
• It’s small. The current version is about 150KB, well within the memory budget of an Android phone.
• It requires no setup or administration. There is no server, no config file, and no need for a database administrator.
A SQLite database is just a file. You can take that file, move it around, and even copy it to another system (for example, from your phone to your workstation), and it will work fine. Android stores the file in the/data/data/packagename/databasesdirectory (see Figure9.1, on the next page). You can use theadbcommand or the File Explorer view in Eclipse (Window > Show View > Other... > Android > File Explorer) to view, move, or delete it.
Instead of calling Java I/O routines to access this file from your pro-gram, you run Structured Query Language (SQL) statements. Through its helper classes and convenience methods, Android hides some of the syntax from you, but you still need to know a bit of SQL to use it.