Fix activity-recreation crash: give Permissions a no-arg constructor

On any activity recreation with saved state (config changes such as
night mode), the FragmentManager restores the Permissions fragment
reflectively and requires a no-arg constructor; it only had
Permissions(View), so the activity failed to start with
Fragment$InstantiationException.

Also regenerate cmd/pad/Permissions.jar from the .java source in both
build scripts: gogio does not compile the app's own .java files - it
silently merges any *.jar in the Go package dirs into the dex, so the
stale Aug-16 jar shadowed source edits (which is how this bug went
unnoticed).

This crash is separate from the black-screen hang after relaunch,
which is fixed in the gioui fork (app/os_android.go: skip the window
handshake ack on re-attach).
This commit is contained in:
Greg Pomerantz 2026-10-12 16:43:10 -04:00
parent c6fb426282
commit 7bffc7ffda
3 changed files with 45 additions and 0 deletions

View File

@ -25,6 +25,17 @@ public class Permissions extends Fragment {
Handler handler;
final int PERMISSIONS_REQUEST = 1;
// No-arg constructor required by the FragmentManager when restoring
// this fragment from the activity's saved state (activity recreation
// on config changes). Without it the restore throws
// Fragment$InstantiationException and the activity fails to start.
// Only the first-creation path uses the (View) constructor below;
// on restore the framework adds the fragment itself, and ctx/handler
// stay null — onAttach uses its own context parameter, so nothing on
// the restore path needs them.
public Permissions() {
}
public Permissions(View view) {
Log.d("gio", "Permissions()");
this.ctx = view.getContext();

View File

@ -54,6 +54,23 @@ fi
WORK=$(mktemp -d)
trap 'rm -rf "$WORK"' EXIT
echo "=== compile Permissions.java -> Permissions.jar ==="
# gogio does NOT compile the app's own .java files; it silently merges any
# *.jar found in the Go package dirs (extraJars) into the dex. The
# Permissions fragment is therefore shipped from cmd/pad/Permissions.jar.
# Regenerate it from the .java source on every build, or source edits are
# silently ignored (the stale jar wins) — that is how the missing no-arg
# constructor (Fragment$InstantiationException on activity recreation) went
# unnoticed.
ANDROID_JAR="$ANDROID_HOME/platforms/android-35/android.jar"
[ -f "$ANDROID_JAR" ] || die "android.jar missing: $ANDROID_JAR"
PERMCLS=$(mktemp -d)
javac -source 1.8 -target 1.8 -nowarn \
-bootclasspath "$ANDROID_JAR" \
-d "$PERMCLS" "$REPO/cmd/pad/Permissions.java" || die "Permissions.java failed to compile"
jar cf "$REPO/cmd/pad/Permissions.jar" -C "$PERMCLS" st
rm -rf "$PERMCLS"
echo "=== gogio (Go -> APK) ==="
# targetSdk 34: targeting 35 makes Android 15 force edge-to-edge. We keep 34
# and instead consume the IME insets ourselves (PadInsetsListener patch below);

View File

@ -52,6 +52,23 @@ fi
WORK=$(mktemp -d)
trap 'rm -rf "$WORK"' EXIT
echo "=== compile Permissions.java -> Permissions.jar ==="
# gogio does NOT compile the app's own .java files; it silently merges any
# *.jar found in the Go package dirs (extraJars) into the dex. The
# Permissions fragment is therefore shipped from cmd/pad/Permissions.jar.
# Regenerate it from the .java source on every build, or source edits are
# silently ignored (the stale jar wins) — that is how the missing no-arg
# constructor (Fragment$InstantiationException on activity recreation) went
# unnoticed.
ANDROID_JAR="$ANDROID_HOME/platforms/android-35/android.jar"
[ -f "$ANDROID_JAR" ] || die "android.jar missing: $ANDROID_JAR"
PERMCLS=$(mktemp -d)
javac -source 1.8 -target 1.8 -nowarn \
-bootclasspath "$ANDROID_JAR" \
-d "$PERMCLS" "$REPO/cmd/pad/Permissions.java" || die "Permissions.java failed to compile"
jar cf "$REPO/cmd/pad/Permissions.jar" -C "$PERMCLS" st
rm -rf "$PERMCLS"
echo "=== gogio (Go -> APK, arm64+arm) ==="
# targetSdk 34: targeting 35 makes Android 15 force edge-to-edge. We keep 34
# and instead consume the IME insets ourselves (PadInsetsListener patch below);