[SOLVED] Unable to start app with offscreen rendering on Android

Well, by logging the update()

This approach would render only the first frame and stops.

But, INVISIBLE would keep updating the game.

If you aren’t using xml then your code should look similar like this :

  @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
        /*define the android view with it's id from xml*/
        JmeSurfaceView jmeSurfaceView=new JmeSurfaceView(this);
        jmeSurfaceView.setLayoutParams(new FrameLayout.LayoutParams(1, 1));
        jmeSurfaceView.setVisibility(View.INVISIBLE);

        /*set the jme game*/
        jmeSurfaceView.setLegacyApplication(new MyGame());
        jmeSurfaceView.setOnExceptionThrown(this);
        jmeSurfaceView.setOnRendererCompleted(this);
        /*start the game*/

        jmeSurfaceView.startRenderer(JmeSurfaceView.NO_DELAY);
        setContentView(jmeSurfaceView);
    }

Well, it seems I’ve ended with the next approach.

I’ve set output buffer to a ViewPort using ViewPort.setOutputFrameBuffer(). So JME starts to render to my FrameBuffer.
Also I’ve added a SceneProcessor to a ViewPort (viewPort.addProcessor()). In SceneProcessor.postFrame() I extract image from FrameBuffer.

To make engine to start rendering I’ve created a GLSurfaceView and added it to a layout. If I’m trying to make in INVISIBLE then jme does not starts render for me. So when I need to render a frame I make SurfaceView VISIBLE and on SceneProcessor.postFrame() I send callback to my activity and make SurfaceView INVISIBLE there. But sometimes it renders a SurfaceView on a screen for one frame. I think it because I set INVISIBLE flag for a view using runOnUIThread() and sometimes a delay can occur and Android render SurfaceVIew for one frame before it became invisible.

So I did another “trick” and used a View.setTranslationX() and setTranslationY() for my GLSurfaceView and just moved it out of the screen.

So now jme renders to FrameBuffer, so I use the same code on Desktop and Android. And to make rendering works on Android I use a “dummy” GLSurfaceView (which I just placed out of the screen) to initialize and process rendering loop.

1 Like

Nice hack, but beware of different screen sizes so, use getDisplayMetrics(); to get the screen width and height, btw you had better use JmeSurfaceView because it takes care of jme life cycle in which you will need to implement yourself if you will use a GlSurfaceView, JmeSurfaceView wraps a GlSurfaceView and its renderer in OGLESContext so you can still use the same maneuver there.

1 Like

I set Surface x position to its -width so it always will be over the left border of the screen.
And I picked GlSurfaceView over JmeSurfaceView because I do not need any audio or input handling. All what I need is to render a scene and save a single image. So all extra functionality in JmeSurfaceView is redurant for me.

1 Like