MANAGE_EXTERNAL_STORAGE (needed to read the store at /storage/emulated/0/...) cannot be requested with a runtime permission dialog; the user must toggle it in system settings. Port the mechanism from the pad app: - Permissions.java: a Fragment registered at window attach that launches Settings.ACTION_MANAGE_APP_ALL_FILES_ACCESS_PERMISSION (per-app settings screen) when Environment.isExternalStorageManager() is false on API 30+ (runtime READ_EXTERNAL_STORAGE request on older APIs). The guard means the screen appears only until the user grants it. - The compiled classes ship in PgpConnect.jar's directory jar (Permissions.jar); gogio picks *.jar up from the package dir and dexes them. go:generate now rebuilds it. - jni_android.c/h: registerPermissionsFragment(), mirroring registerFragment() for PgpConnect. - Impl wiring: call it from the AndroidViewEvent handler right after InitPgp. Verified on the x86_64 emulator: with the appop denied the system settings screen opens automatically on launch; after granting it, launch is clean and list + OpenKeychain decryption from /sdcard/Pass work end to end.
92 lines
3.1 KiB
Java
92 lines
3.1 KiB
Java
package st.wow.git.passgo;
|
|
|
|
import java.lang.Runnable;
|
|
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.pm.PackageManager;
|
|
import android.net.Uri;
|
|
import android.provider.Settings;
|
|
import android.view.View;
|
|
|
|
// Requests the storage permissions the app needs to read the password
|
|
// store in shared storage. On Android 11+ (API 30+) the
|
|
// MANAGE_EXTERNAL_STORAGE ("All files access") permission cannot be
|
|
// requested with a dialog; the user must toggle it in the system
|
|
// settings, so we launch that settings screen directly for this app.
|
|
public class Permissions extends Fragment {
|
|
Context ctx;
|
|
Handler handler;
|
|
final int PERMISSIONS_REQUEST = 1;
|
|
|
|
public Permissions(View view) {
|
|
Log.d("passgo", "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("passgo", "Permissions onAttach()");
|
|
|
|
if (!(context instanceof Activity)) {
|
|
Log.w("passgo", "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("passgo", "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("passgo", "No activity found for all files access settings");
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
@Override public void onActivityResult(int requestCode, int resultCode, Intent data) {
|
|
Log.d("passgo", "Permissions onActivityResult(" + requestCode + "): " + resultCode);
|
|
super.onActivityResult(requestCode, resultCode, data);
|
|
}
|
|
}
|