Interacting with Android Views and Events Android

Now that you have gone through this introduction to OpenGL ES on Android, you have seen how to draw 3D objects on the screen. Actually, these 3D objects are drawn on a SurfaceView, which has all the typical Android attributes found on View widgets. We now use these attributes to interact with the rest of the application.

First, we show you how to send information from the OpenGL thread back to the main thread to monitor performance. Then, we give an example of how to forward key events from the main thread to the OpenGL thread to control the animation on the screen.

(Left) A red colored cube with texture and (right) the same cube without red coloring.

(Left) A red colored cube with texture and (right) the same cube without red coloring

Enabling the OpenGL Thread to Talk to the Application Thread The Android SDK provides a helper class for running code on another thread. The Handler class can allow a piece of code to run on a target thread—the thread that the Handler was instantiated in. For the purpose of this example, you do this within the Activity class:

public final Handler mHandler = new Handler();

This enables the OpenGL thread to execute code on the Activity thread by calling the post() method of the Handler. This enables us to act on other View objects on the screen that we can’t act on from outside of the Activity thread on the OpenGL thread. For this example, the frame rate of the scene rendered is calculated in the OpenGL thread and then posted back to the Activity thread. Here is a method that does just that:

public void calculateAndDisplayFPS() {
if (showFPS) {
long thisTime = System.currentTimeMillis();
if (thisTime - mLastTime < mSkipTime) {
mFrames++;
} else {
mFrames++;
final long fps =
mFrames / ((thisTime-mLastTime)/1000);
mFrames = 0;
mLastTime = thisTime;
mHandler.post(new Runnable() {
public void run() {
mFPSText.setText("FPS = " + fps);
}
});
}
}
}

The calculateAndDisplayFPS() method is called from within the animation loop of the OpenGL thread. The math is fairly straightforward: the number of frames divided by the duration for those frames in seconds. Then, we take that and post it to the Handler for the Activity thread by creating a new Runnable object that applies a String to the TextView that holds the current frame rate.

However, doing this every iteration causes the performance to drop substantially. Instead, a counter tracks the number of frames drawn, and we do the calculation and display every time the duration of mSkipTime has gone by.A value of 5000ms has worked well to avoid influencing the performance too much by simply measuring the performance.

This shows the display with the frame rate.

A textured, lit, shaded cube with the frame rate displayed.

A textured, lit, shaded cube with the frame rate displayed

Enabling the Application Thread to Talk to the OpenGL Thread

Now let’s look at the reverse situation. We want the main application thread to communicate with the OpenGL thread. We could use a Handler to post code to the OpenGL thread for execution. However, if we are not going to execute any OpenGL code, we aren’t required to run it within the OpenGL thread context. Instead, we can add a key event handler to the SurfaceView to either speed up or stop the animation within the OpenGL thread.

A SurfaceView needs to be the current focus before it receives key events. A couple of method calls configure this:

setFocusable(true);
setFocusableInTouchMode(true);

Setting focusable for both touch modes enables key events to come in regardless of the mode. Now, within the SurfaceView, key event handlers need to be implemented. First, we implement a handler for toggling the frame rate on and off. The following is a sample implementation of the onKeyDown() method override:

public boolean onKeyDown(int keyCode, KeyEvent event) {
switch (keyCode) {
case KeyEvent.KEYCODE_F:
mGLThread.toggleFPSDisplay();
return true;
}
return super.onKeyDown(keyCode, event);
}

When the user presses the F key, a call to the toggleFPSDisplay() method of the OpenGL ES thread is made. This merely changes the state of the boolean flag and then updates the text field status. The onKeyDown() method is called multiple times if the key is held, toggling the display until the key is released. There are multiple methods to prevent this, such as just handling it within onKeyUp() or using different keys to enable and disable the state.

The next control we provide to the user is the ability to pause the animation while the P key is held down. Add the following case statement to onKeyDown():

case KeyEvent.KEYCODE_P:
mGLThread.setAnim(false);
return true;

Here, the state is forced to false regardless of how many times onKeyDown() is called. Next, an implementation of onKeyUp() is needed to resume the animation when the user lifts his finger:

public boolean onKeyUp(int keyCode, KeyEvent event) {
switch (keyCode) {
case KeyEvent.KEYCODE_P:
mGLThread.setAnim(true);
return true;
}
return super.onKeyUp(keyCode, event);
}

Again, the value is forced and set to true so that when the user lifts his finger off the key, the animation resumes regardless of the current state. An if statement around the inner part of the entire while() animation loop can pause the entire rendering in this example.

In these examples, the code does not actually run in the OpenGL thread to change the state of the flags. This is acceptable for the following reasons:

  • The values are set in this way exclusively (no concurrency problems).
  • The exact state of the flags is unimportant during the loop.
  • No calls to OpenGL are made.

The first two reasons mean that we don’t have to perform thread synchronization for the functionality to work acceptably and safely. The last reason means that we don’t need to create a Handler on the OpenGL thread to execute OpenGL calls in the proper thread. There are many circumstances where these aren’t met. Discussing thread synchronization is not within the scope of this chapter, however. Standard Java methods are available for doing this, though.



Face Book Twitter Google Plus Instagram Youtube Linkedin Myspace Pinterest Soundcloud Wikipedia

All rights reserved © 2018 Wisdom IT Services India Pvt. Ltd DMCA.com Protection Status

Android Topics