app: add RunOnJVM to allow Cgo access to the Android JVM and context

CL 122897 changed the visibility of the global JavaVM, JNIEnv and
android.context.Context variables to be internal to gomobile.
However, users of gomobile build programs used those internal
variables to access Java API through Cgo and JNI without Java code.

Make an exported version of mobileinit.RunOnJVM available. This is
quite possibly not the right API for this, but I don't have the
bandwidth to design a better solution. On the other hand, without
access to Java APIs, gomobile build programs are unfairly forced to
add Java code where before there were no need.

Fixes golang/go#26815

Change-Id: I655fb858ffff03a0d542aa9bf97eefc7a22dd5d0
Reviewed-by: Hyang-Ah Hana Kim <>
diff --git a/app/android.go b/app/android.go
index 27e33d4..b6402e0 100644
--- a/app/android.go
+++ b/app/android.go
@@ -60,6 +60,18 @@
+// RunOnJVM runs fn on a new goroutine locked to an OS thread with a JNIEnv.
+// RunOnJVM blocks until the call to fn is complete. Any Java
+// exception or failure to attach to the JVM is returned as an error.
+// The function fn takes vm, the current JavaVM*,
+// env, the current JNIEnv*, and
+// ctx, a jobject representing the global android.context.Context.
+func RunOnJVM(fn func(vm, jniEnv, ctx uintptr) error) error {
+	return mobileinit.RunOnJVM(fn)
 //export setCurrentContext
 func setCurrentContext(vm *C.JavaVM, ctx C.jobject) {
 	mobileinit.SetCurrentContext(unsafe.Pointer(vm), uintptr(ctx))