diff --git a/ui/app/GioActivity.java b/ui/app/GioActivity.java index 669292a4..537a693f 100644 --- a/ui/app/GioActivity.java +++ b/ui/app/GioActivity.java @@ -12,16 +12,14 @@ import android.view.WindowManager; public class GioActivity extends Activity { private GioView view; - static { - System.loadLibrary("gio"); - } - @Override public void onCreate(Bundle state) { super.onCreate(state); + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) { Window w = getWindow(); w.setFlags(WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS, WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS); } + this.view = new GioView(this); setContentView(view); } diff --git a/ui/app/GioView.java b/ui/app/GioView.java index fc7fd0ac..bbaf7124 100644 --- a/ui/app/GioView.java +++ b/ui/app/GioView.java @@ -20,18 +20,46 @@ import android.view.inputmethod.InputConnection; import android.view.inputmethod.InputMethodManager; import android.view.inputmethod.EditorInfo; +import java.io.UnsupportedEncodingException; + public class GioView extends SurfaceView implements Choreographer.FrameCallback { + private final static Object initLock = new Object(); + private static boolean jniLoaded; + private static String dataDir; + private final SurfaceHolder.Callback callbacks; private final InputMethodManager imm; private final Handler handler; private long nhandle; + private static synchronized void initialize(Context appCtx) { + synchronized (initLock) { + if (jniLoaded) { + return; + } + dataDir = appCtx.getFilesDir().getAbsolutePath(); + System.loadLibrary("gio"); + jniLoaded = true; + } + } + + static byte[] dataDir() { + try { + return dataDir.getBytes("UTF-8"); + } catch (UnsupportedEncodingException e) { + throw new RuntimeException(e); + } + } + public GioView(Context context) { this(context, null); } public GioView(Context context, AttributeSet attrs) { super(context, attrs); + // Late initialization of the Go runtime to wait for a valid context. + initialize(context.getApplicationContext()); + nhandle = onCreateView(this); handler = new Handler(); imm = (InputMethodManager)context.getSystemService(Context.INPUT_METHOD_SERVICE); diff --git a/ui/app/app.go b/ui/app/app.go index 54f46375..5051cb7c 100644 --- a/ui/app/app.go +++ b/ui/app/app.go @@ -118,3 +118,12 @@ func init() { args := strings.Split(extraArgs, "|") os.Args = append(os.Args, args...) } + +// DataDir returns a path to use for application-specific +// configuration data. +// On desktop systems, DataDir use os.UserConfigDir. +// On iOS NSDocumentDirectory is queried. +// For Android Context.getFilesDir is used. +func DataDir() (string, error) { + return dataDir() +} diff --git a/ui/app/datadir.go b/ui/app/datadir.go new file mode 100644 index 00000000..31e5453f --- /dev/null +++ b/ui/app/datadir.go @@ -0,0 +1,11 @@ +// SPDX-License-Identifier: Unlicense OR MIT + +// +build !android + +package app + +import "os" + +func dataDir() (string, error) { + return os.UserConfigDir() +} diff --git a/ui/app/datadir_android.go b/ui/app/datadir_android.go new file mode 100644 index 00000000..e4a02891 --- /dev/null +++ b/ui/app/datadir_android.go @@ -0,0 +1,18 @@ +// SPDX-License-Identifier: Unlicense OR MIT + +// +build android + +package app + +import "C" + +var dataDir func() (string, error) + +//export setDataDir +func setDataDir(cdir *C.char) { + dir := C.GoString(cdir) + dataDir = func() (string, error) { + return dir, nil + } +} + diff --git a/ui/app/os_android.c b/ui/app/os_android.c index c27f7553..7aafb106 100644 --- a/ui/app/os_android.c +++ b/ui/app/os_android.c @@ -4,7 +4,7 @@ #include "os_android.h" #include "_cgo_export.h" -JNIEXPORT jint JNI_OnLoad(JavaVM *vm, void *reserver) { +JNIEXPORT jint JNI_OnLoad(JavaVM *vm, void *reserved) { JNIEnv *env; if ((*vm)->GetEnv(vm, (void**)&env, JNI_VERSION_1_6) != JNI_OK) { return -1; @@ -87,6 +87,23 @@ JNIEXPORT jint JNI_OnLoad(JavaVM *vm, void *reserver) { if ((*env)->RegisterNatives(env, viewClass, methods, sizeof(methods)/sizeof(methods[0])) != 0) { return -1; } + + // Initialize data dir. + jmethodID dataDirMethod = (*env)->GetStaticMethodID(env, viewClass, "dataDir", "()[B"); + if (dataDirMethod == NULL) { + return -1; + } + jbyteArray dirArr = (*env)->CallStaticObjectMethod(env, viewClass, dataDirMethod); + if (dirArr == NULL) { + return -1; + } + jbyte *dir = (*env)->GetByteArrayElements(env, dirArr, NULL); + if (dir == NULL) { + return -1; + } + setDataDir((char *)dir); + (*env)->ReleaseByteArrayElements(env, dirArr, dir, JNI_ABORT); + return JNI_VERSION_1_6; }