
- •Contents
- •Acknowledgments
- •Preface
- •What Makes Android Special?
- •Who Should Read This Book?
- •Online Resources
- •Fast-Forward >>
- •Introducing Android
- •Quick Start
- •Installing the Tools
- •Creating Your First Program
- •Running on the Emulator
- •Running on a Real Phone
- •Key Concepts
- •The Big Picture
- •Building Blocks
- •Using Resources
- •Safe and Secure
- •Android Basics
- •Designing the User Interface
- •Introducing the Sudoku Example
- •Designing by Declaration
- •Creating the Opening Screen
- •Using Alternate Resources
- •Implementing an About Box
- •Applying a Theme
- •Adding a Menu
- •Adding Settings
- •Starting a New Game
- •Debugging
- •Exiting the Game
- •Exploring 2D Graphics
- •Learning the Basics
- •Adding Graphics to Sudoku
- •Handling Input
- •The Rest of the Story
- •Making More Improvements
- •Multimedia
- •Playing Audio
- •Playing Video
- •Adding Sounds to Sudoku
- •Storing Local Data
- •Adding Options to Sudoku
- •Continuing an Old Game
- •Remembering the Current Position
- •Accessing the Internal File System
- •Accessing SD Cards
- •Beyond the Basics
- •The Connected World
- •Browsing by Intent
- •Web with a View
- •From JavaScript to Java and Back
- •Using Web Services
- •Locating and Sensing
- •Location, Location, Location
- •Set Sensors to Maximum
- •Putting SQL to Work
- •Introducing SQLite
- •Hello, Database
- •Data Binding
- •Using a ContentProvider
- •Implementing a ContentProvider
- •3D Graphics in OpenGL
- •Understanding 3D Graphics
- •Introducing OpenGL
- •Building an OpenGL Program
- •Rendering the Scene
- •Building a Model
- •Lights, Camera, ...
- •Action!
- •Applying Texture
- •Peekaboo
- •Measuring Smoothness
- •Fast-Forward >>
- •The Next Generation
- •Multi-Touch
- •Building the Touch Example
- •Understanding Touch Events
- •Setting Up for Image Transformation
- •Implementing the Drag Gesture
- •Implementing the Pinch Zoom Gesture
- •Hello, Widget
- •Live Wallpaper
- •Write Once, Test Everywhere
- •Gentlemen, Start Your Emulators
- •Building for Multiple Versions
- •Evolving with Android APIs
- •Bug on Parade
- •All Screens Great and Small
- •Installing on the SD Card
- •Publishing to the Android Market
- •Preparing
- •Signing
- •Publishing
- •Updating
- •Closing Thoughts
- •Appendixes
- •Bibliography
- •Index

ACTION! 212
The object will appear to have a dull finish, as if it were made out of paper (see Figure 10.4, on the previous page). The top-right corner of the cube is closer to the light, so it appears brighter.
10.7Action!
Up to now the cube has just been sitting there without moving. That’s pretty boring, so let’s make it move. To do that, we need to make a couple of changes to our onSurfaceCreated( ) and onDrawFrame( ) methods in GLRenderer.
Download OpenGL/src/org/example/opengl/GLRenderer.java
private long startTime; private long fpsStartTime; private long numFrames;
public void onSurfaceCreated(GL10 gl, EGLConfig config) { // ...
startTime = System.currentTimeMillis(); fpsStartTime = startTime;
numFrames = 0;
}
public void onDrawFrame(GL10 gl) {
//...
//Set rotation angle based on the time
long elapsed = System.currentTimeMillis() - startTime; gl.glRotatef(elapsed * (30f / 1000f), 0, 1, 0); gl.glRotatef(elapsed * (15f / 1000f), 1, 0, 0);
// Draw the model cube.draw(gl);
}
This code rotates the cube a little bit every time through the main loop. Specifically, every second it rotates 30 degrees around the x-axis and 15 degrees around the y-axis. The result will be a nice, smooth, spinning cube (see Figure 10.5, on the following page).
10.8Applying Texture
Although the scene is starting to look more interesting, nobody would mistake it for real life. Everyday objects have textures, like the rough surface of a brick wall or the gravel on a garden path. Do you own a laminated table? A wood laminate is just a photograph of wood grain that is glued on the surface of a less expensive material like plastic or particle board.

APPLYING TEXTURE 213
Figure 10.5: Rotating the cube
Time-Based Animation
The first version of this example kept track of the current rotation angle and simply incremented it each time through the loop. Can you think of a reason why that was a bad idea?
Since Android can run on a variety of different devices, you can’t predict how long it will take to draw a single frame. It might take half a second or 1/100th of a second. If you moved an object a fixed amount every frame, then on slow devices the object would move too slowly, and on fast devices it would move too fast. By tying the amount of movement to how much time has elapsed, you can achieve predictable movement on any device. Faster hardware will draw the animation more smoothly, but objects will get from A to B in the same amount of time.

APPLYING TEXTURE 214
We’re going to do the same thing to our cube using a picture. Unfortunately, the code to do this is fairly long. Don’t worry if you don’t understand it all right away.
Download OpenGL/src/org/example/opengl/GLCube.java
private final IntBuffer mTextureBuffer;
public GLCube() {
int texCoords[] = { // FRONT
0, one, one, one, 0, 0, one, 0, // BACK
one, one, one, 0, 0, one, 0, 0, // LEFT
one, one, one, 0, 0, one, 0, 0, // RIGHT
one, one, one, 0, 0, one, 0, 0, // TOP
one, 0, 0, 0, one, one, 0, one, // BOTTOM
0, 0, 0, one, one, 0, one, one, };
// ...
ByteBuffer tbb = ByteBuffer.allocateDirect(texCoords.length * 4); tbb.order(ByteOrder.nativeOrder());
mTextureBuffer = tbb.asIntBuffer(); mTextureBuffer.put(texCoords); mTextureBuffer.position(0);
}
static void loadTexture(GL10 gl, Context context, int resource) { Bitmap bmp = BitmapFactory.decodeResource(
context.getResources(), resource); GLUtils.texImage2D(GL10.GL_TEXTURE_2D, 0, bmp, 0); gl.glTexParameterx(GL10.GL_TEXTURE_2D,
GL10.GL_TEXTURE_MIN_FILTER, GL10.GL_LINEAR); gl.glTexParameterx(GL10.GL_TEXTURE_2D,
GL10.GL_TEXTURE_MAG_FILTER, GL10.GL_LINEAR); bmp.recycle();
}
}
Next we need to tell OpenGL to use the texture coordinates. Add this to the beginning of the draw( ) method:
Download OpenGL/src/org/example/opengl/GLCube.java
gl.glEnable(GL10.GL_TEXTURE_2D); // workaround bug 3623 gl.glTexCoordPointer(2, GL10.GL_FIXED, 0, mTextureBuffer);

APPLYING TEXTURE 215
Figure 10.6: Applying a texture
And finally we need to call the loadTexture( ) method in GLRenderer. Add these lines to the end of the onSurfaceCreated( ) method:
Download OpenGL/src/org/example/opengl/GLRenderer.java
// Enable textures gl.glEnableClientState(GL10.GL_TEXTURE_COORD_ARRAY); gl.glEnable(GL10.GL_TEXTURE_2D);
// Load the cube's texture from a bitmap GLCube.loadTexture(gl, context, R.drawable.android);
This code enables textures and texture coordinates and then calls our loadTexture( ) method, passing it the Activity context and resource ID so it can load the texture image.
R.drawable.android is a PNG file 128 pixels square that I copied to res/ drawable-nodpi/android.png. You can find it in the downloadable code package that accompanies this book. Note the number 128 doesn’t