libgdx-application-lifecycle — independently scanned and version-tracked by SaferSkills.
SaferSkills independently audited libgdx-application-lifecycle (Agent Skill) and scored it 100/100 (green). The audit ran 55 deterministic rules across Security, Supply Chain, Maintenance, Transparency, and Community; it found 0 high-severity and 0 lower-severity findings. The full rule-by-rule trace and per-finding evidence are below. Free, methodology-open.
Findings & checks · 0 flagged
Every scanned point with the score it earned and what moved between them.
First recorded scan — no prior version to compare against.
The primary manifest — the file an agent reads to learn what this artifact does.
Reference for ApplicationListener, ApplicationAdapter, lifecycle method order, frame-independent updates, resource disposal, and platform-specific pause/resume behavior.
public interface ApplicationListener {
void create(); // App created — OpenGL context now available
void resize(int w, int h); // Window/viewport resized
void render(); // Called every frame (update + draw combined)
void pause(); // App losing focus / going to background
void resume(); // App regaining focus / returning to foreground
void dispose(); // App shutting down — release all resources
}There is no `update()` method. All game logic and drawing happen in render().
ApplicationAdapter implements ApplicationListener with empty defaults. Extend it and override only what you need — avoids boilerplate empty methods.
// YES — extend ApplicationAdapter
public class MyGame extends ApplicationAdapter { ... }
// NO — don't implement ApplicationListener directly unless you need all 6 methods
public class MyGame implements ApplicationListener { ... }create() → resize(w,h) → [render() loop] → pause() → dispose()
↕
pause() ↔ resume()Startup: create() → resize(w, h) → render() ... Exit: pause() → dispose()
On Android, dispose() may not be called if the OS kills the process while backgrounded. Save critical state in pause(), not dispose().
All GPU/audio/file initialization must happen inside `create()`. The OpenGL context and libGDX subsystems (Gdx.graphics, Gdx.audio, Gdx.files, etc.) do not exist until create() is called. Constructing a Texture, SpriteBatch, or any GL-dependent object as a field initializer or in the constructor will crash.
// WRONG — crashes: no GL context at field-init time
public class MyGame extends ApplicationAdapter {
SpriteBatch batch = new SpriteBatch(); // CRASH
Texture img = new Texture("pic.png"); // CRASH
}
// RIGHT — create() has a valid GL context
public class MyGame extends ApplicationAdapter {
SpriteBatch batch;
Texture img;
@Override
public void create() {
batch = new SpriteBatch();
img = new Texture("pic.png");
}
}There is no separate update() callback. Combine logic and rendering in render():
@Override
public void render() {
// 1. Delta time for frame-independent movement
float dt = Gdx.graphics.getDeltaTime(); // seconds since last frame
// 2. Update
x += 100 * dt; // 100 pixels/second regardless of frame rate
// 3. Draw — ScreenUtils.clear() is the modern shorthand (since 1.10.0)
// replacing the verbose Gdx.gl.glClearColor() + Gdx.gl.glClear() pattern
ScreenUtils.clear(0, 0, 0, 1);
batch.begin();
batch.draw(img, x, 0);
batch.end();
}getDeltaTime() is on `Gdx.graphics`, not Gdx.app.
| Event | Desktop (LWJGL3) | Android | iOS (RoboVM) |
|---|---|---|---|
| Window minimized / Home button | pause() fires | pause() fires | pause() fires |
| Window loses focus (Alt+Tab) | Nothing — render continues | — | — |
| Incoming call / screen off | — | pause() fires | pause() fires |
| render() during pause | Continues running | Stops entirely | Stops entirely |
| GL context on pause | Retained | Destroyed — managed resources auto-reloaded | Retained |
| dispose() on kill | Called | May not be called | Called |
Desktop: pause() only fires on iconification, not on focus loss. render() keeps running even when iconified — if you have network timers or other continuous work in render(), it won't stop on desktop. Check the pause state explicitly if needed.
Android: The render loop stops entirely during pause. Any work in render() (heartbeats, timers, network pings) ceases. Use a background thread or Android service for work that must continue. The GL context is destroyed during pause; libGDX automatically reloads managed resources on resume. Only raw, unmanaged GL handles need manual recreation.
iOS (RoboVM): Behaves like Android for pause triggers (home button, incoming call, app switcher), but the GL context is retained like desktop. render() stops during pause.
On Android, device rotation triggers resize() only if android:configChanges includes orientation|screenSize in the manifest. Without it, Android destroys and recreates the Activity — a full dispose() → create() cycle, not a resize(). The Android backend skill covers manifest setup.
Gdx.app.exit() schedules a graceful shutdown — it is NOT immediate. Code after exit() still executes in the current frame. The shutdown triggers pause() → dispose(). On Android, it calls finish() on the Activity.
if (Gdx.input.isKeyJustPressed(Input.Keys.ESCAPE)) {
Gdx.app.exit();
return; // necessary — exit() is non-blocking
}These types allocate native memory or GPU resources outside the JVM heap. The garbage collector cannot free them — you must call dispose() explicitly, typically in your ApplicationAdapter.dispose().
| Type | Resource held |
|---|---|
Texture | GPU texture |
SpriteBatch | Mesh + shader |
BitmapFont | Texture(s) |
ShaderProgram | GL shader program |
FrameBuffer | GL framebuffer + texture |
Sound | Native audio buffer |
Music | Native audio stream |
Pixmap | Native pixel buffer |
TextureAtlas | Texture(s) |
Skin | Textures + fonts |
Stage | SpriteBatch (if owns it) |
Rule of thumb: if you created it, dispose it. Dispose in reverse order of creation when possible. In non-trivial projects, AssetManager handles disposal via unload() and clear() — prefer it over manual tracking.
Gdx.app.setLogLevel(Application.LOG_DEBUG); // in create()
Gdx.app.log("Game", "info message"); // LOG_INFO level
Gdx.app.debug("Game", "debug message"); // LOG_DEBUG level
Gdx.app.error("Game", "error message"); // LOG_ERROR levelLog level constants (com.badlogic.gdx.Application):
| Constant | Value | Shows |
|---|---|---|
LOG_NONE | 0 | Nothing |
LOG_ERROR | 1 | error() only |
LOG_INFO | 2 | error() + log() |
LOG_DEBUG | 3 | All messages |
Default level is LOG_INFO. Output goes to stdout (desktop), LogCat (Android), or NSLog (iOS).
import com.badlogic.gdx.ApplicationAdapter;
import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.graphics.Color;
import com.badlogic.gdx.utils.ScreenUtils;
public class MyGame extends ApplicationAdapter {
@Override
public void create() {
Gdx.app.log("MyGame", "create()");
}
@Override
public void render() {
// ScreenUtils.clear() replaces the old glClearColor()+glClear() pattern (since 1.10.0)
ScreenUtils.clear(Color.CORAL);
}
@Override
public void dispose() {
Gdx.app.log("MyGame", "dispose()");
}
}create().render().Gdx.graphics.getDeltaTime().AssetManager for non-trivial projects.ApplicationAdapter to avoid empty method stubs.exit() still executes in the current frame.orientation|screenSize in android:configChanges, rotation destroys and recreates the Activity instead of calling resize().~30 seconds. Free. No account. Every finding cites a rule and a line of evidence.