LibGDX dealing with context loss

I’m creating a game for Android with LibGDX, and aside from supporting multiple screen resolutions (any information on how to would be great, just as a side request!), its going good. But I’ve run into an issue. When a user hits the back button on their phone, the “app” is pretty much closed down completely and the memory is restored to the phone from the game. The home button simply “pauses” the app, so the data is still in memory. I think I’m right, but correct me if I’m wrong.

Now, my issue is loading textures upon resume after hitting the back key. I know about managed and unmanaged textures, so I don’t think I need more information on that. Let me start out by explaining what happens when I try resuming the game.

  • I have a UI in game that is made up of separately loaded textures (IE not from a texture atlas). On resume, they render fine.

  • The levels are made up of tiles loaded in using the TextureRegion class. I get the texture regions from a statically created texture (Texture texture = new Texture(blahhh…):wink: The tiles do not reload after resuming, I just get white where the tiles should be.

  • The “mobs” (the player and all the NPCs) are also loaded from the same Texture that the tiles are loaded from (the mobs are TextureRegions). These also do not reload after resume.

I think the issue has to do with my texture atlas. I statically create it like so:

	public static Texture tiles = new Texture(Gdx.files.internal("data/tiles.png"));

I then call it like this (Example is for a grass tile):

private TextureRegion texture;
	
	public TileGrass(){
		texture = new TextureRegion(Constants.tiles, 16, 0, 16, 16);
	}

Constants.tiles refers to the static texture I showed above.

Now, what did I do to try to solve the issue? I tried reloading the textures in my resume function like this:

@Override
	public void resume() {
		Constants.tiles = new Texture(Gdx.files.internal("data/tiles.png"));
		Tile.initTiles();
		for(Mob m : mobs) {
			m.onResume();
		}
		player.onResume();
	}

Tile.initTiles is this:


public static void initTiles(){
		Grass = new TileGrass();
		Stone = new TileStone();
		StoneWall = new TileStoneWall();
		StoneCracked = new TileStoneCracked();
		StoneCracked1 = new TileStoneCracked1();
		Defense = new TileDefense();
		Seed1 = new TileSeed1();
		Seed2 = new TileSeed2();
		Flower = new TileFlower();
		
		tiles.put((byte) 1, Grass);
		tiles.put((byte) 2, Seed1);
		tiles.put((byte) 3, Seed2); 
		tiles.put((byte) 4, Flower);
		tiles.put((byte) 5, Stone);
		tiles.put((byte) 6, StoneWall);
		tiles.put((byte) 7, StoneCracked);
		tiles.put((byte) 8, StoneCracked1);
		tiles.put((byte) 9, Defense);
	}

It recreates the tiles (therefore recreating the TextureRegions), and adds them to a hashmap.

onResume() is this:

public void onResume() {
		texture = new TextureRegion(Constants.tiles, tx, ty, 16, 16);
	}

Which again, just recreates the TextureRegion from the static Texture. I then call resume from my main class like this (the main class extends Game, the LibGDX class):

@Override
	public void resume() {
		super.resume();
		if(currentState == State.MENU)
			menu.resume();
		if(currentState == State.GAME)
			world.resume();
	}

Now, what can I conclude? It seems texture regions do not reload after the application is “destroyed” by hitting the back button. I hope I am wrong though. It seems that the Texture class handles reloading itself though, because every texture that isn’t a texture region works fine even after resuming after hitting the back key.

Any insight?

Do you mean pressing the back button after entering a menu or something? That’s never broken anything for me.

No, sorry I should have clarified. Hitting the back key to exit out of the app completely is what I’m having issues with.

Just discovered that if I hit the back key and exit the app, then open the app, hit the home button and then open the game, the textures are reloaded perfectly fine. So it has to be an issue with the resume function not being called or something.

Don’t do this.

I had the same problem, hit the back key and then go back onto the game. Textures were all randomly selected from what was loader before lol.

A cheap solution was just to re-load everything every screen change, my game is small anyway.

Here is a stackoverflow question on it:

Nate can you please expland upon your answer? I would like to know why I shouldn’t and what the alternatives are please.

Ok, changing everything over to not using the static texture worked great, thank you. Now my only issue is that when the device resumes after exiting through the back key, my screen’s show method is called again. Anyway to fix that? My game basically resets itself and re-loads a new map through the show method, so that’s obviously not good…

Edit: Never mind, the whole World class (where I create all my mobs and the map) is recreated after resuming.

Well when the user press back or the home button, pause() then hide() is called. Ideally you want to have some code in pause such as saving current progress if it is a score based game just in-case it crashes or GC decides to kill it.

In show(), unless you want to, for whatever reason you should only have code in there that reloads things that may be lost, such as your textures and such.

I’ve seen people put screen initialization code in there, I don’t understand why…if you continuously hide and show the screen you are just going to clog the memory with shite.

Yeah, as I dig into Android more I’m starting to realize how randomly processes can be killed. I think I’ll start saving stuff periodically so I can load it back up easily when the user resumes.

The VM can be reused, in that case your statics won’t be initialized again. Generally avoid statics for Android. If you use them, make sure they are reinitialized every time your app runs.

Ok thank you, my issue was solved!

Well now I have another issue. I have a WAV file that I would like to play, but it only works on the desktop (as in it only plays on the desktop). On my phone there are no errors, no crashes or anything but it simply just doesn’t play…

seems like a codec issue.
make sure the format is absolutely correct. pcm and all

Android normally does not support WAV. Use other format.
[Also wrong topic]

It works fine now, I just had to restart my phone.

What topic do you recommend creating it under then besides engines tools and libraries?

I dont know if im getting you problem/request, but i use this code to unable the back button (on every activity the app has)

try it:

@Override
	public boolean onKeyDown(int keyCode, KeyEvent event)
	{
		boolean ret = true;

		if (keyCode != KeyEvent.KEYCODE_BACK && keyCode != KeyEvent.KEYCODE_SEARCH)
			ret = super.onKeyDown(keyCode, event);

		return ret;
	}

Hope it works for you.

No, sorry that’s not what I was talking about :stuck_out_tongue: On Android, every app has a context, but only one app (I believe) can have the context. So when you hit the back button, the Android developers decided they would assume you wanted to close the app (IE shut it down), so they give the apps memory back to the system, therefore destroying any of your textures in memory. LibGDX deals with this for the programmer, but I was messing up and causing it to screw up.

Good. But remember there is no grantee it is going work well on other devices.

I mean the “WAV-problem” has nothing to do with context loss.

About the context loss: A few years ago I was solving this problem by calling AssetManager.finishLoading() method inside onResume(). Don’t know if it is still works the same way. Currently I handle this myself by forcing unloading of all resources when game goes background, and reloading everything back on resume.