Prevent onPause from trashing OpenGL Context

cjserio picture cjserio · Jan 21, 2010 · Viewed 23.7k times · Source

I'm writing an Android application that uses OpenGL ES (GLSurfaceView and GLSurfaceView.Renderer). The problem is that when the user switches applications and then switches back to my app, the GLSurfaceView destroys and recreates the GL context. This is what it's supposed to do according to the documentation but is there a way to prevent this from happening?

It takes a long time to load textures into the context and i'd like to prevent having to reload them.

Answer

seanhodges picture seanhodges · Feb 9, 2010

I think what you are looking for is discussed in the GLSurfaceView documentation:

A GLSurfaceView must be notified when the activity is paused and resumed. GLSurfaceView clients are required to call onPause() when the activity pauses and onResume() when the activity resumes. These calls allow GLSurfaceView to pause and resume the rendering thread, and also allow GLSurfaceView to release and recreate the OpenGL display.

When using the standard Android SDK, you must release/recreate your context whenever the activity is paused/resumed (including screen orientation changes). Not doing so will cause the GL context to be release and not restored when the activity is loaded back into memory. Remember that we are dealing with very limited resources (particularly on low-spec devices). So the short answer is: you can't prevent it without breaking your app.

Assuming you are using the standard Android/OpenGL framework, you need to do the following...

In your activity, ensure you have the following overridden methods:

public void onPause() {
    myGlSurfaceView.onPause();
}

public void onResume() {
    myGlSurfaceView.onResume();
}

Anything you hold outside the GL environment will still need to be preserved and restored manually however (bitmaps, game state, etc), for these you'll need to use static fields or a mechanism like SharedPreferences.

Update

Android 3.x provides a function to preserve the GL context on pause without needing to be recreated. However, there are several caveats:

  1. Android 3.x features are not available to approx. 90% of devices on the market at this time
  2. The devices must also support multiple EGL contexts, it is unclear how many devices on the market currently support this.

Using some API reflection to check capabilities, it may be possible to make use of this function on supporting devices. However, you would still need to fall back to recreating the context for the rest. In my opinion, until more devices run Android 3 it would be better to hold off using setPreserveEGLContextOnPause and focus on ensuring the context recreation approach is sufficiently tested.