Android Life Cycle Issues

I been playing around with a test app and must say I am very impressed so far. While playing around trying to learn the engine, I noticed some issues with handling the life cycle events.


  1. When I hit the home button and then resume the app, the game would resume correctly. However, when I added a picture to the guiNode, when I resumed the game I recevied the following:



    09-13 20:46:35.124: ERROR/AndroidHarness(12672): java.lang.RuntimeException: Canvas: trying to use a recycled bitmap android.graphics.Bitmap@4065af78

    09-13 20:46:35.140: ERROR/AndroidHarness(12672): SEVERE AndroidHarness 8:46:35 PM Exception thrown in Thread[GLThread 9,5,main]: at android.graphics.Canvas.throwIfRecycled(955)

    09-13 20:46:35.140: ERROR/AndroidHarness(12672): at android.graphics.Canvas.drawBitmap(1012)

    09-13 20:46:35.140: ERROR/AndroidHarness(12672): at android.graphics.Bitmap.createBitmap(492)

    09-13 20:46:35.140: ERROR/AndroidHarness(12672): at android.graphics.Bitmap.createScaledBitmap(379)

    09-13 20:46:35.140: ERROR/AndroidHarness(12672): at com.jme3.renderer.android.TextureUtil.uploadTextureBitmap(95)

    09-13 20:46:35.140: ERROR/AndroidHarness(12672): at com.jme3.renderer.android.TextureUtil.uploadTexture(123)

    09-13 20:46:35.140: ERROR/AndroidHarness(12672): at com.jme3.renderer.android.OGLESShaderRenderer.updateTexImageData(1946)

    09-13 20:46:35.140: ERROR/AndroidHarness(12672): at com.jme3.renderer.android.OGLESShaderRenderer.setTexture(1981)

    09-13 20:46:35.140: ERROR/AndroidHarness(12672): at com.jme3.material.MatParamTexture.apply(46)

    09-13 20:46:35.140: ERROR/AndroidHarness(12672): at com.jme3.material.Material.render(997)

    09-13 20:46:35.140: ERROR/AndroidHarness(12672): at com.jme3.renderer.RenderManager.renderGeometry(656)

    09-13 20:46:35.140: ERROR/AndroidHarness(12672): at com.jme3.renderer.queue.RenderQueue.renderGeometryList(301)

    09-13 20:46:35.140: ERROR/AndroidHarness(12672): at com.jme3.renderer.queue.RenderQueue.renderQueue(354)

    09-13 20:46:35.140: ERROR/AndroidHarness(12672): at com.jme3.renderer.RenderManager.renderViewPortQueues(918)

    09-13 20:46:35.140: ERROR/AndroidHarness(12672): at com.jme3.renderer.RenderManager.flushQueue(849)

    09-13 20:46:35.140: ERROR/AndroidHarness(12672): at com.jme3.renderer.RenderManager.renderViewPort(1125)

    09-13 20:46:35.140: ERROR/AndroidHarness(12672): at com.jme3.renderer.RenderManager.render(1173)

    09-13 20:46:35.140: ERROR/AndroidHarness(12672): at com.jme3.app.SimpleApplication.update(263)

    09-13 20:46:35.140: ERROR/AndroidHarness(12672): at com.jme3.system.android.OGLESContext.onDrawFrame(418)

    09-13 20:46:35.140: ERROR/AndroidHarness(12672): at android.opengl.GLSurfaceView$GLThread.guardedRun(1363)

    09-13 20:46:35.140: ERROR/AndroidHarness(12672): at android.opengl.GLSurfaceView$GLThread.run(1118)



    While searching through the jme3 source code for android, I found that OGLESShaderRenderer.setTexture had some commented-out code to handle recycled images. When I uncommented the code, the error went away and the games would resume correctly.



    Is there a reason why this code was commented-out?


  2. When the orientation mode in main game class (the class I have that extends AndroidHarness) is set to SCREEN_ORIENTATION_SENSOR, the game restarts when the phone is rotated and the orientation changes. I tried to figure out if there was a way to make the game pause and resume when the orientation changes, but I’m afraid that might be beyond what I understand about jme.



    Is there a way to make the game pause/resume when the orientation changes instead of restarting the game?

Hi



I just checked the simple textured demo - send it to the background with the home key - do some stuff - go back to beta1 demo:

It works - i remember to have fixed the recycled bitmap issue - thats why the code in the renderer is commented out.



But i didnt try it with a guiNode - i only tested it with normal textures.



Could you please post a simple test case, so im faster in reproducing it, because im rather occupied currently with a new job.

While creating the test case for you, I found out that using an image from the test-data jar file (Interfaces/icons/SmartMonkey128.png) does not have the issue while using my own picture from the assets directory does have the problem. I left both in for you below. When the app first displays, both pictures show correctly. After I hit the home key and then go back, I get the issue, but only if the second picture (the only from the assets directory) is used.



Hope this helps.





[java]

package com.interstatewebgroup.jmonkeytutorials;



import android.util.Log;



import com.jme3.app.SimpleApplication;

import com.jme3.ui.Picture;



public class RecycleTestGame extends SimpleApplication {



private String TAG = "RecycleTestGame";



private float iconWidth=128;

private float iconHeight = 128;

private float iconLocX = 0;

private float iconLocY = 0;



@Override

public void simpleInitApp() {

{

Picture pic = new Picture("pic");

pic.setImage(assetManager, "Interface/icons/SmartMonkey128.png", true);

iconLocX = settings.getWidth()/2 - iconWidth/2;

iconLocY = settings.getHeight()/2 - iconHeight/2;

pic.setWidth(iconWidth);

pic.setHeight(iconHeight);

pic.setPosition(iconLocX, iconLocY);

int picID = guiNode.attachChild(pic);

Log.d(TAG, "pic " + picID + " Loc: " + iconLocX + ", " + iconLocY);

}

{

Picture pic = new Picture("pic");

pic.setImage(assetManager, "DoubleUpOff.png", true);

iconLocX = 0 + 48;

iconLocY = settings.getHeight()/2 - 48;

pic.setWidth(iconWidth);

pic.setHeight(iconHeight);

pic.setPosition(iconLocX, iconLocY);

int picID = guiNode.attachChild(pic);

Log.d(TAG, "pic " + picID + " Loc: " + iconLocX + ", " + iconLocY);

}



}



@Override

public void simpleUpdate(float tpf) {

}



}

[/java]

Forget to add that even when I use pictures from the assests directory, when I add back in the code from OGLESShaderRenderer.setTexture both pictures display fine on the resume.

Perhaps your letter case is wrong? Is it “Interface/icons” or “Interface/Icons”?

I don’t think it is a path issue. The image from that directory works fine.



@larynx - Were you able to reproduce this?

I’m still having frequent issues with gui trying to use recycled bitmaps on resume of the app. If no one has any issues, can it be applied?



[java]

This patch file was generated by NetBeans IDE

Following Index: paths are relative to: D:UserspotterecDocumentsjMonkeyProjectsjME3srcandroidcomjme3rendererandroid

This patch can be applied using context Tools: Patch action on respective folder.

It uses platform neutral UTF-8 encoding and n newlines.

Above lines and this line are ignored by the patching process.

Index: OGLESShaderRenderer.java

— OGLESShaderRenderer.java Base (BASE)

+++ OGLESShaderRenderer.java Locally Modified (Based On LOCAL)

@@ -82,6 +82,8 @@

import android.opengl.GLES11;

import android.opengl.GLES20;

import android.os.Build;

+import com.jme3.asset.TextureKey;

+import com.jme3.system.JmeSystem;

import java.util.ArrayList;



public class OGLESShaderRenderer implements Renderer {

@@ -1973,7 +1975,7 @@

public void setTexture(int unit, Texture tex) {

Image image = tex.getImage();

if (image.isUpdateNeeded()) {

  •        /*<br />
    

+// /*

Bitmap bmp = (Bitmap)image.getEfficentData();

if (bmp != null)

{

@@ -1985,7 +1987,7 @@

image.setEfficentData( textureReloaded.getImage().getEfficentData());

}

}

  •         */<br />
    

+// */

updateTexImageData(image, tex.getType(), tex.getMinFilter().usesMipMapLevels());

}





[/java]

I am seeing the same issue using Nifty GUI on Android. I am testing on a Motorola Xoom.



I see this crash when I resume the app:



E/AndroidHarness( 1879): java.lang.RuntimeException: Canvas: trying to use a recycled bitmap android.graphics.Bitmap@408d7908

E/AndroidHarness( 1879): SEVERE AndroidHarness 10:19:35 PM Exception thrown in Thread[GLThread 15,5,main]: at android.graphics.Canvas.throwIfRecycled(1012)

E/AndroidHarness( 1879): at android.graphics.Canvas.drawBitmap(1084)

E/AndroidHarness( 1879): at android.graphics.Bitmap.createBitmap(569)

E/AndroidHarness( 1879): at android.graphics.Bitmap.createScaledBitmap(437)

E/AndroidHarness( 1879): at com.jme3.renderer.android.TextureUtil.uploadTextureBitmap(95)

E/AndroidHarness( 1879): at com.jme3.renderer.android.TextureUtil.uploadTexture(123)

E/AndroidHarness( 1879): at com.jme3.renderer.android.OGLESShaderRenderer.updateTexImageData(1954)

E/AndroidHarness( 1879): at com.jme3.renderer.android.OGLESShaderRenderer.setTexture(1989)

E/AndroidHarness( 1879): at com.jme3.material.MatParamTexture.apply(46)

E/AndroidHarness( 1879): at com.jme3.material.Material.render(1002)

E/AndroidHarness( 1879): at com.jme3.font.BitmapText.render(360)

E/AndroidHarness( 1879): at com.jme3.niftygui.RenderDeviceJme.renderFont(225)

E/AndroidHarness( 1879): at de.lessvoid.nifty.render.NiftyRenderEngineImpl.renderText(258)

E/AndroidHarness( 1879): at de.lessvoid.nifty.elements.render.TextRenderer.renderLine(291)

E/AndroidHarness( 1879): at de.lessvoid.nifty.elements.render.TextRenderer.renderLines(192)

E/AndroidHarness( 1879): at de.lessvoid.nifty.elements.render.TextRenderer.render(173)

E/AndroidHarness( 1879): at de.lessvoid.nifty.elements.Element.renderElement(599)

E/AndroidHarness( 1879): at de.lessvoid.nifty.elements.Element.render(584)

E/AndroidHarness( 1879): at de.lessvoid.nifty.elements.Element.renderInternalChildElements(616)

E/AndroidHarness( 1879): at de.lessvoid.nifty.elements.Element.renderChildren(609)

E/AndroidHarness( 1879): at de.lessvoid.nifty.elements.Element.render(578)

E/AndroidHarness( 1879): at de.lessvoid.nifty.elements.Element.renderInternalChildElements(616)

E/AndroidHarness( 1879): at de.lessvoid.nifty.elements.Element.renderChildren(609)

E/AndroidHarness( 1879): at de.lessvoid.nifty.elements.Element.render(578)

E/AndroidHarness( 1879): at de.lessvoid.nifty.screen.Screen.renderLayers(313)

E/AndroidHarness( 1879): at de.lessvoid.nifty.Nifty.render(276)

E/AndroidHarness( 1879): at com.jme3.niftygui.NiftyJmeDisplay.postQueue(170)

E/AndroidHarness( 1879): at com.jme3.renderer.RenderManager.renderViewPort(1121)

E/AndroidHarness( 1879): at com.jme3.renderer.RenderManager.render(1167)

E/AndroidHarness( 1879): at com.jme3.app.SimpleApplication.update(266)

E/AndroidHarness( 1879): at com.jme3.system.android.OGLESContext.onDrawFrame(418)

E/AndroidHarness( 1879): at android.opengl.GLSurfaceView$GLThread.guardedRun(1425)

E/AndroidHarness( 1879): at android.opengl.GLSurfaceView$GLThread.run(1180)



I tried the above fix, but my jmonkey built from source had other issues so I went back to the Beta (nightly) release.

I finally got this resolved. The problem seems to be that my images were not sized with a power of 2. The original pictures were 48x48 pixels. When I resized the images to 64x64 pixels, the issues with trying to display recycled images on the GUI node when the game resumes went away. Does that make sense?

1 Like

@iwgeric Thanks a lot for the work around.



I have the same issue in the rootNode. Resizing the images to pot worked flawlessly.



Regards,

EsKoR.

@eskor glad it helped. took me a while to figure that one out.