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.
65 lines
1.2 KiB
Go
65 lines
1.2 KiB
Go
//go:build android
|
|
|
|
package main
|
|
|
|
import (
|
|
"os"
|
|
|
|
"gioui.org/app"
|
|
"gioui.org/io/event"
|
|
"git.wow.st/gmp/passgo"
|
|
)
|
|
|
|
var (
|
|
noidLabelText = "Enter a GPG key ID above"
|
|
)
|
|
|
|
func init() {
|
|
log(Info, "Android start")
|
|
// Use a larger font on Android
|
|
fontSize = 24
|
|
}
|
|
|
|
func handleEvent(e event.Event) {
|
|
switch e := e.(type) {
|
|
case app.AndroidViewEvent:
|
|
// A zero View means the view is detached (e.g. the activity going
|
|
// away on a recents-wipe); there is nothing to register for a
|
|
// detached view. A re-attach arrives as a fresh event with a live
|
|
// view.
|
|
if e.View != 0 {
|
|
initPgp(e.View)
|
|
initPermissions(e.View)
|
|
}
|
|
}
|
|
}
|
|
|
|
func initPgp(view uintptr) {
|
|
passgo.InitPgp(view)
|
|
}
|
|
|
|
func initPermissions(view uintptr) {
|
|
passgo.InitPermissions(view)
|
|
}
|
|
|
|
func getConfDir() (string, error) {
|
|
ret, err := app.DataDir()
|
|
if err != nil {
|
|
log(Error, "Cannot get data directory:", err)
|
|
return "", err
|
|
}
|
|
if _, err := os.Stat(ret); os.IsNotExist(err) {
|
|
err = os.MkdirAll(ret, 0700)
|
|
if err != nil {
|
|
log(Error, "Cannot create configuration directory ", ret)
|
|
return "", err
|
|
} else {
|
|
log(Info, "Configuration directory created")
|
|
return ret, nil
|
|
}
|
|
} else {
|
|
log(Info, "Configuration directory found")
|
|
return ret, nil
|
|
}
|
|
}
|