• No results found

Set Sensors to Maximum

Let’s say you’re writing a racing game so you need to give the player a way to steer their car on the screen. One way would be to use buttons, like driving games on a Sony PlayStation or the Nintendo DS. Press right to steer right, press left to steer left, and hold down another button for the gas. It works, but it’s not very natural.

Have you ever watched somebody play one of those games? Uncon-sciously, they sway from side to side when making a hairpin curve, jerk the controller when bumping into another car, lean forward when speeding up, and pull back when putting on the brakes. Wouldn’t it be

3. http://d.android.com/guide/developing/tools/ddms.html

SETSENSORS TOMAXIMUM 169

cool if those motions actually had some effect on the game play? Now they can.

Engaging Sensors

The Android SDK supports many different types of sensor devices:

• TYPE_ACCELEROMETER: Measures acceleration in the x-, y-, and z-axes

• TYPE_LIGHT: Tells you how bright your surrounding area is

• TYPE_MAGNETIC_FIELD: Returns magnetic attraction in the x-, y-, and z-axes

• TYPE_ORIENTATION: Measures the yaw, pitch, and roll of the device

• TYPE_PRESSURE: Senses the current atmospheric pressure

• TYPE_PROXIMITY: Provides the distance between the sensor and some object

• TYPE_TEMPERATURE: Measures the temperature of the surrounding area

Not all devices will offer all this functionality, of course.4

The SensorTest example, available on the book’s website, demonstrates using the Sensor API. Android’sSensorManager class is similar to Loca-tionManager, except the updates will come much more quickly, perhaps hundreds per second. To get access to the sensors, you first call the getSystemService( ) method like this:

Download SensorTest/src/org/example/sensortest/SensorTest.java

private SensorManager mgr;

// ...

mgr = (SensorManager) getSystemService(SENSOR_SERVICE);

Then you call the registerListener( ) in your onResume( ) method to start getting updates and call unregisterListener( ) in youronPause( ) method to stop getting them.

Interpreting Sensor Readings

The sensor service will call your onSensorChanged( ) method every time a value changes. It should look something like this:

4. Unfortunately, Android 1.5 removed support for theTRICORDERsensor that turned your device into a fully functional Star Trek tricorder. Darn it, Jim—I’m a programmer, not an ovum paschalis.

Download SensorTest/src/org/example/sensortest/SensorTest.java

public void onSensorChanged(SensorEvent event) { for (int i = 0; i < event.values.length; i++) {

// ...

} }

All the sensors return an array of floating-point values. The size of the array depends on the particular sensor; for example, TYPE_

TEMPERATURE returns only one value, the temperature in degrees Cel-sius. You may not even need to use all the numbers returned. For instance, if you just need a compass heading, you can use the first number returned from theTYPE_ORIENTATIONsensor.

Turning the sensor readings (especially from the accelerometer) into meaningful information is something of a black art. Here are a few tips to keep in mind:

• Accelerometer readings are extremely jittery. You’ll need to smooth out the data using some kind of weighted averaging, but you have to be careful not to smooth it too much, or your interface will feel laggy and soft.

• Sensor numbers will come in at random times. You may get several in a row, then have a short pause, and then receive a bunch more.

Don’t assume a nice even rate.

• Try to get ahead of the user by predicting what they’re going to do next. Let’s say the last three readings show the start of a roll to the right, with each one a little faster than the last. You can guess with some degree of accuracy what the next reading is going to be and start reacting based on your prediction.

The most challenging use of sensors is an action game that requires a one-to-one connection between how the player moves the device and what happens on the screen. Unfortunately, the emulator isn’t going to be much use for this kind of thing.

Emulation Notes

According to Google, it is not possible to test the sensors using the emulator at all. Most computers don’t have a light sensor, a GPS chip, or a compass built into them. Sure enough, if you run the SensorTest program in the emulator, it will display no results at all. However, a

SETSENSORS TOMAXIMUM 171

Figure 8.2: Faking out the sensors with the Sensor Simulator

project called OpenIntents5 provides an alternate sensor’s API that you can call just for testing purposes.

The way it works is that you connect the emulator to another applica-tion running on your desktop computer called the Sensor Simulator.

The simulator shows a picture of a virtual phone and lets you move it around on the screen with the mouse (see Figure8.2), and then it feeds those movements to your Android program running on the emulator. If your development computer actually does have sensors of its own (like the Apple MacBook) or you can connect to a Wii remote with Bluetooth, the Sensor Simulator can use that as a data source.

The downside is that you have to modify your source code to make it work. See the OpenIntents website for more information if you want to try it. My recommendation is to forget about sensor emulation and get your hands on a real device. Keep tweaking your algorithms until it feels right.

5. http://www.openintents.org

Now that you know the low-level calls to get your location and query the sensors for numbers such as your compass heading, for certain applications you can forget all that and just use the Google Maps API.