Skip to content
Development
Skill

/mobile-development

Use when targeting Android/iOS — export and signing, permissions, plugins, in-app purchases, ads, app lifecycle, device features, and mobile performance

From plugin
godot-prompter
54157 skills9 agents1 hook
Install
$ npx -y skills add jame581/GodotPrompter --skill mobile-development --agent claude-code

How it fires

How this skill gets triggered: by you, by Claude, or both.

  • Fires itselfAuto-invocation. Claude auto-loads it when your prompt matches the work.Auto-invocation is when the right skill fires by itself at the right moment, driven by a FLOW.md router and a hook, instead of you invoking it by name. It is the difference between a skill being installed and a skill actually getting used.Read the full definition →
  • You can call itInvoke it directly when you want it.
  • Slash command/mobile-development

Context preview

The summary Claude sees to decide when to auto-load this skill.

Use when targeting Android/iOS — export and signing, permissions, plugins, in-app purchases, ads, app lifecycle, device features, and mobile performance

SKILL.md

mobile-development.SKILL.md
name: mobile-development
description: Use when targeting Android/iOS — export and signing, permissions, plugins, in-app purchases, ads, app lifecycle, device features, and mobile performance

Mobile Development

Ship a Godot 4.x game to Android and iOS. This covers the platform-specific deltas beyond a generic export: signing, lifecycle, permissions, plugins, IAP, device features, and the mobile renderer/perf budget.

> **Related skills:** **export-pipeline** for the generic export flow and CI/CD, **responsive-ui** for safe-area layout, **input-handling** for touch, **godot-optimization** for mobile performance, **csharp-godot** for C# mobile caveats.

---

1. Export & signing

**Android:** OpenJDK 17 and the Android SDK; set `Java SDK Path` + `Android SDK Path` in **Editor Settings** (per-user, not per-project). Generate a release keystore:

keytool -v -genkey -keystore mygame.keystore -alias mygame -keyalg RSA -validity 10000

Preset fields: **Release / Release User / Release Password** (keystore and key passwords must currently match); uncheck **Export With Debug**. **AAB is mandatory for new Play uploads.** CI env overrides: `GODOT_ANDROID_KEYSTORE_RELEASE_{PATH,USER,PASSWORD}`.

**iOS:** macOS + Xcode. Export needs an **App Store Team ID** + a reverse-DNS bundle **Identifier**; Godot generates an `.xcodeproj` you build from Xcode. The iOS **simulator supports the Compatibility renderer only**.

A **custom Gradle build** (*Project → Install the Gradle Build template*) is **required for v2 plugins and IAP** (Godot 4.2+). Since Godot 4.7 the **Use Gradle Build** export option is no longer marked experimental ([GH-119172](https://github.com/godotengine/godot/pull/119172)) — treat it as the standard path when you need plugins or IAP.

> ⚠️ **Changed in Godot 4.7:** Deprecated Google Play OBB expansion-file support was removed from the Android export. Projects still relying on APK expansion files must migrate to Play Asset Delivery or PCK patching. See [GH-118283](https://github.com/godotengine/godot/pull/118283).

---

2. App lifecycle

Real `Node` notification constants: `NOTIFICATION_APPLICATION_PAUSED` (2015), `NOTIFICATION_APPLICATION_RESUMED` (2014), `NOTIFICATION_APPLICATION_FOCUS_IN`/`_OUT` (2016/2017), `NOTIFICATION_WM_GO_BACK_REQUEST` (1007, Android Back). **There is no `WM_CLOSE_REQUEST` on mobile.** Autosave on PAUSED; **iOS gives ~5 s** after pause to finish work before it kills the app.

GDScript

func _notification(what: int) -> void:
    match what:
        NOTIFICATION_APPLICATION_PAUSED:
            SaveManager.save_game() # App backgrounded — persist now.
        NOTIFICATION_WM_GO_BACK_REQUEST:
            _confirm_quit()         # Android Back button.

C# Equivalent

The docs only show `NotificationWMCloseRequest` verbatim; these PascalCase names follow the same convention.

public override void _Notification(int what)
{
    switch ((long)what)
    {
        case NotificationApplicationPaused:
            SaveManager.SaveGame(); // App backgrounded — persist now.
            break;
        case NotificationWMGoBackRequest:
            ConfirmQuit();          // Android Back button.
            break;
    }
}

Picture-in-Picture (Android, Godot 4.7+)

`DisplayServer.pip_mode_enter(window_id = 0)` enters picture-in-picture mode; `is_in_pip_mode(window_id = 0)` reports the current state; `pip_mode_set_aspect_ratio(numerator, denominator, window_id = 0)` sets the PiP window's aspect ratio; `pip_mode_set_auto_enter_on_background(auto_enter_on_background, window_id = 0)` enters PiP automatically when the app goes to the background. Transitions arrive as `Node` notifications: `NOTIFICATION_APPLICATION_PIP_MODE_ENTERED` (2019) / `NOTIFICATION_APPLICATION_PIP_MODE_EXITED` (2020). All Android-only.

func _ready() -> void:
    DisplayServer.pip_mode_set_aspect_ratio(16, 9)
    DisplayServer.pip_mode_set_auto_enter_on_background(true)

func _notification(what: int) -> void:
    match what:
        NOTIFICATION_APPLICATION_PIP_MODE_ENTERED:
            _set_minimal_hud(true)  # PiP window is tiny — hide non-essential UI.
        NOTIFICATION_APPLICATION_PIP_MODE_EXITED:
            _set_minimal_hud(false)
public override void _Ready()
{
    DisplayServer.PipModeSetAspectRatio(16, 9);
    DisplayServer.PipModeSetAutoEnterOnBackground(true);
}

public override void _Notification(int what)
{
    switch ((long)what)
    {
        case NotificationApplicationPipModeEntered:
            SetMinimalHud(true);  // PiP window is tiny — hide non-essential UI.
            break;
        case NotificationApplicationPipModeExited:
            SetMinimalHud(false);
            break;
    }
}

---

3. Permissions

Declare each permission in the export preset as `permissions/<name>`; request it at runtime with `OS.request_permission(name)`. The result arrives via `MainLoop`'s `on_request_permissions_result(permission, granted)`. The permission **must also be enabled in the preset**, not just requested.

GDScript

func _ready():
    if "android.permission.POST_NOTIFICATIONS" not in OS.get_granted_permissions():
        OS.request_permission("android.permission.POST_NOTIFICATIONS")
    get_tree().on_request_permissions_result.connect(_on_perm_result)

func _on_perm_result(permission: String, granted: bool):
    print("%s granted: %s" % [permission, granted])

C# Equivalent

public override void _Ready()
{
    if (!OS.GetGrantedPermissions().Contains("android.permission.POST_NOTIFICATIONS"))
        OS.RequestPermission("android.permission.POST_NOTIFICATIONS");
    GetTree().OnRequestPermissionsResult += OnPermResult;
}

private void OnPermResult(string permission, bool granted)
    => GD.Print($"{permission} granted: {granted}");

---

4. Calling Android APIs (JavaClassWrapper) — Godot 4.4+

**Godot 4.4+ only.** `JavaClassWrapper.wrap("<java.class>")` calls

Read more
Ships withgodot-prompter

Agentic skills framework for Godot 4.x game development. Gives AI coding agents domain-specific expertise for GDScript and C# projects.

Get the whole plugin