Pad/cmd/pad/Permissions.java
Greg Pomerantz 7bffc7ffda 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).
2026-10-12 16:43:10 -04:00

104 lines
3.4 KiB
Java

package st.wow.git.logbook;
import java.lang.Runnable;
import java.lang.String;
import android.os.Build;
import android.os.Environment;
import android.os.Handler;
import android.content.Context;
import android.util.Log;
import android.app.Activity;
import android.app.Fragment;
import android.app.FragmentManager;
import android.app.FragmentTransaction;
import android.content.Intent;
import android.Manifest;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.net.Uri;
import android.provider.Settings;
import android.view.View;
public class Permissions extends Fragment {
Context ctx;
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();
this.handler = new Handler(this.ctx.getMainLooper());
Permissions inst = this;
handler.post(new Runnable() {
public void run() {
Activity act = (Activity)ctx;
FragmentTransaction ft = act.getFragmentManager().beginTransaction();
ft.add(inst, "Permissions");
ft.commitNow();
}
});
}
@Override
public void onAttach(Context context) {
super.onAttach(context);
Log.d("gio", "onAttach()");
if (!(context instanceof Activity)) {
Log.w("gio", "Context is not an Activity");
return;
}
Activity activity = (Activity) context;
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.R) {
if (context.checkSelfPermission(Manifest.permission.READ_EXTERNAL_STORAGE)
!= PackageManager.PERMISSION_GRANTED) {
requestPermissions(
new String[]{Manifest.permission.READ_EXTERNAL_STORAGE},
PERMISSIONS_REQUEST
);
}
}
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R
&& !Environment.isExternalStorageManager()) {
Log.d("gio", "Requesting all files access");
Intent intent = new Intent(
Settings.ACTION_MANAGE_APP_ALL_FILES_ACCESS_PERMISSION,
Uri.parse("package:" + activity.getPackageName())
);
if (intent.resolveActivity(activity.getPackageManager()) != null) {
startActivity(intent);
} else {
Intent fallback = new Intent(Settings.ACTION_MANAGE_ALL_FILES_ACCESS_PERMISSION);
if (fallback.resolveActivity(activity.getPackageManager()) != null) {
startActivity(fallback);
} else {
Log.e("gio", "No activity found for all files access settings");
}
}
}
Log.d("gio", "Loading gio library");
System.loadLibrary("gio");
}
@Override public void onActivityResult(int requestCode, int resultCode, Intent data) {
Log.d("gio", "onActivityResult(" + requestCode + "): " + resultCode);
super.onActivityResult(requestCode, resultCode, data);
}
}