Android: Start up init only once?

Started by
9 comments, last by frob 8 years, 10 months ago

I started to plunge into android and make an application that runs OpenGL ES 2. Everything is going pretty well but there is one thing I don't understand and it may sound extremely stupid but: How do run an init or start up method only once when creating a GLSurfaceView?

I have a method called StartUpInit that I want to call only once. Basically this method is where I would put any start up code, so things like initial OpenGL system creation, config loading, game save loads, etc.

My problem happens when the screen orientation changes. I see that my whole GLSurfaceView object / renderer get recreated from scratch breaking my start up code. How can I run my method only once even if the screen orientation changes?

The reason I need / have the start up method in the onSurfaceChanged is that some of my init code requires an OpenGL context for its calls and I need the width and height.

Any help would be awesome

Current code:


//Activity class
class App extends Activity
{
	private MyRenderer renderer;
	private MySurface surface;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

		renderer = new MyRenderer();
        surface = new MySurface(this.getBaseContext(), renderer);
        setContentView(surface);
    }
	
	/*Other methods */
}

//Renderer Class
class MyRenderer implements GLSurfaceView.Renderer
{
	public boolean startUp;
	public float renderWidth;
	public float renderHeight;
        
        public MyRenderer()
        {
                startUp = true;
        }
	

	public void onSurfaceCreated(GL10 gl, EGLConfig config)
	{
		/* init OpenGL calls EG: glClearColor */
	}

	public void onSurfaceChanged(GL10 gl, int width, int height)
	{

		renderWidth = width;
		renderHeight = height;
		
		if(startUp)
		{
			StartUpInit(renderWidth, renderHeight);
			startUp = false;
		}
	}
	
	public void onDrawFrame(GL10 gl)
	{
		/* Draw Stuff */
	}
} 

//Surface Class
class MySurface extends GLSurfaceView
{
	public MySurface(Context context, MyRenderer renderer)
	{
		super(context);
		setEGLContextClientVersion(2);

		setRenderer(renderer);
	}
	
	/*Other methods */
}

Advertisement

By default android recreates activity each time something has changed. Make sure you have something like this: android:configChanges="keyboard|keyboardHidden|orientation|screenSize|smallestScreenSize|screenLayout|uiMode" inside your <activity> tag in manifest (With this line you tell, you will handle this stuff by yourself)

Android does not necessarily recreate the activity on changes. The application life-cycle events are fully described in the Android developers documentation, which I would suggest you take a look into as I would not be surprise that as soon as you get the answer to handling screen orientation changes, you will be asking another question or run into issue with other life-cycle events.


I have a method called StartUpInit that I want to call only once. Basically this method is where I would put any start up code, so things like initial OpenGL system creation, config loading, game save loads, etc.

Please read the developer documentation about system events and activity callbacks.

The features you mention belong elsewhere, and the proper times and locations are clearly documented. Properly handling pause, resume, stop, and restart are extremely important.

Please read the developer documentation about system events and activity callbacks.

The features you mention belong elsewhere, and the proper times and locations are clearly documented. Properly handling pause, resume, stop, and restart are extremely important.


I went back and read the documentation on the life cycle events and while I do understand it, in a way I do not

I would think that I would want my StartUpInit method in the onCreate event, but I'm getting an error: call to OpenGL ES API with no current context (logged once per thread)

So by this time (this event) I would say its safe to say my OpenGL context is not created yet.

Which is why I placed it in the onSurfaceCreate event of GLSurfaceView. But based on the docs the activity is destroyed and recreated when the screen orientation changes

So I feel that regardless of where I place my StartUpInit method it wont actually work in the sense that it will be fired once, since everything will get created again and again.

Maybe I'm not thinking of things right?

I mean the way I see it, when considering all of the lifecycle events I feel like I would need to recreate all of my OpenGL resources all the time.

Because if the GLSurfaceView is recreated every time then my OpenGL context gets destroyed and things like buffers, textures, and etc become invalid. Right?

So then I guess my question becomes how can I preserve that context?

How can I preserve the state of my objects? Even if they contain OpenGL resources such as buffers, texture ids, and etc

What is typically done?

Resources are lost at specific times, not "all the time". You need to write code that handles it.

As for how you can preserve it, some stuff you cannot. The data is removed from the buffers or is otherwise invalidated.

There are many different times, different events and triggers, and they need to be handled. Someone bringing up a different app, or the phone's power button getting hit, or the screen orientation changing, many things need to be handled. It isn't just the graphics, there are times you should save, there are times you should reload, there are times you should stop processing.

Thee are many different times, different events and triggers, and they need to be handled. Someone bringing up a different app, or the phone's power button getting hit, or the screen orientation changing, many things need to be handled. It isn't just the graphics, there are times you should save, there are times you should reload, there are times you should stop processing.


Of course, but how should I be preserving it? I know there is the Bundle object I can place stuff into, but I don't think (I don't see) there is a method for putting objects into a Bundle. So does that mean I should be serializing things and saving them on some available storage?

First of all might I suggest that you just 'request' a fixed screen orientation?

Do you really need to switch between portrait and landscape mode all the time?

That would mean otherways you need to recreate your GUI anyway depending if the user chooses to work with portrait or landscape mode.

In theory it doesn't matter much if you are holding your phone in landscape mode at 0° or at 180°.

The automatic screen orientation is often something that is turned off by default anyways as many people use their phone not only in a 90° angle to the floor, the only situation the sensors work correctly.

It might sound like a cheap fix but I think this is first of all the most desired option for the users and most importantly of all it doesn't distract you from your project.

AFAIK on newer versions of Android (at least on all of my test devices with Android 4.0 and higher) when the screen orientation changes, just a "onSurfaceChanged()" method gets called where I update the newest screen resolution and the app keeps running without a problem.

I know that on the oldest phone of them with Android API 8 or 9 on every screen orientation even "onCreate()" gets called again which is very undesirable meaning the whole app is started again.

Maybe later on think about a solution supporting a dynamic screen orientation? When there is an actual app that could support it and not just a placeholder?

The details are specific to the application, but many things should not be preserved. Reload to graphics assets from storage to the card, don't keep copies of all that big stuff in precious memory. Other items that you may be manipulating should be saved on pause, either to load quickly when the player returns after switching apps or for when the app is fully closed then started again.

Both are specific to your game.

I know that on the oldest phone of them with Android API 8 or 9 on every screen orientation even "onCreate()" gets called again which is very undesirable meaning the whole app is started again.
Maybe later on think about a solution supporting a dynamic screen orientation? When there is an actual app that could support it and not just a placeholder?


This is definitely true, I was so confused when the screen orientation changed and my whole app got recreated

The details are specific to the application, but many things should not be preserved. Reload to graphics assets from storage to the card, don't keep copies of all that big stuff in precious memory. Other items that you may be manipulating should be saved on pause, either to load quickly when the player returns after switching apps or for when the app is fully closed then started again.

Both are specific to your game.

Sure I should save only what I need, but my question is more on the side of how should I save? What is the best or proper way to save? Whats the quickest way to load?

Should I make all my objects serializable, do I just write everything to some big text file and parse it out when onResume is called, etc?

This topic is closed to new replies.

Advertisement