159 lines
3.6 KiB
Go
159 lines
3.6 KiB
Go
package main
|
|
|
|
/*
|
|
#cgo LDFLAGS: -landroid
|
|
|
|
#include <stdlib.h>
|
|
#include "jni_android.h"
|
|
*/
|
|
import "C"
|
|
|
|
import (
|
|
"errors"
|
|
"fmt"
|
|
"log"
|
|
"runtime"
|
|
"unsafe"
|
|
"sync"
|
|
)
|
|
|
|
var theJVM *C.JavaVM
|
|
type JNIEnv = C.JNIEnv
|
|
|
|
func SetJVM(jvm, context uintptr) {
|
|
log.Print("set theJVM")
|
|
theJVM = (*C.JavaVM)(unsafe.Pointer(jvm))
|
|
RunInJVM(func(env *C.JNIEnv) {
|
|
C.SetLoader(env, (C.jobject)(context))
|
|
})
|
|
}
|
|
|
|
func FindClass(env *C.JNIEnv, name string) C.jclass {
|
|
cname := C.CString(name)
|
|
defer C.free(unsafe.Pointer(cname))
|
|
return C.FindClass((*C.JNIEnv)(env), cname)
|
|
}
|
|
|
|
func AddFragment(env *C.JNIEnv, act C.jobject, frag C.jobject) {
|
|
C.AddFragment(env, act, frag);
|
|
}
|
|
|
|
func JniCallVoidMethod(env *C.JNIEnv, obj C.jobject, methodID C.jmethodID) {
|
|
C.CallVoidMethod(env, obj, methodID)
|
|
}
|
|
|
|
func JniCallVoidMethod1(env *C.JNIEnv, obj C.jobject, methodID C.jmethodID, arg uintptr) {
|
|
C.CallVoidMethod1(env, obj, methodID, C.jobject(unsafe.Pointer(arg)))
|
|
}
|
|
|
|
func JniCallIntMethod(env *C.JNIEnv, obj C.jobject, methodID C.jmethodID) int {
|
|
return (int)(C.CallIntMethod(env, obj, methodID))
|
|
}
|
|
|
|
func JniGetMethodID(env *C.JNIEnv, cls C.jclass, name, sig string) C.jmethodID {
|
|
cname := C.CString(name)
|
|
defer C.free(unsafe.Pointer(cname))
|
|
csig := C.CString(sig)
|
|
defer C.free(unsafe.Pointer(csig))
|
|
return C.GetMethodID(env, cls, cname, csig)
|
|
}
|
|
|
|
func CreateObject(env *C.JNIEnv, cls C.jclass) C.jobject {
|
|
return C.CreateObject(env, (C.jclass)(cls))
|
|
}
|
|
|
|
type PGP C.jobject
|
|
|
|
func NewPgpConnect(env *C.JNIEnv, act uintptr) PGP {
|
|
return (PGP)(C.NewPgpConnect(env, (C.jobject)(unsafe.Pointer(act))))
|
|
}
|
|
|
|
var (
|
|
fragChans map[int]chan string
|
|
chmux sync.Mutex
|
|
chint int
|
|
)
|
|
|
|
func (p PGP) Decrypt(data string) string {
|
|
ch := make(chan string)
|
|
chmux.Lock()
|
|
if fragChans == nil {
|
|
fragChans = make(map[int]chan string)
|
|
}
|
|
fragChans[chint] = ch
|
|
curint := chint
|
|
chint++
|
|
chmux.Unlock()
|
|
|
|
cdata := C.CString(data)
|
|
defer C.free(unsafe.Pointer(cdata))
|
|
var ret string
|
|
RunInJVM(func(env *JNIEnv) {
|
|
retc := C.Decrypt(env, (C.jobject)(p), (*C.char)(unsafe.Pointer(cdata)), (C.int)(len(data)), C.int(curint))
|
|
defer C.free(unsafe.Pointer(retc))
|
|
ret = C.GoString(retc)
|
|
})
|
|
return ret
|
|
}
|
|
|
|
func (p PGP) Encrypt(id, data string) string {
|
|
ch := make(chan string)
|
|
chmux.Lock()
|
|
if fragChans == nil {
|
|
fragChans = make(map[int]chan string)
|
|
}
|
|
fragChans[chint] = ch
|
|
curint := chint
|
|
chint++
|
|
chmux.Unlock()
|
|
|
|
cid := C.CString(id)
|
|
defer C.free(unsafe.Pointer(cid))
|
|
cdata := C.CString(data)
|
|
defer C.free(unsafe.Pointer(cdata))
|
|
var ret string
|
|
RunInJVM(func(env *JNIEnv) {
|
|
retc := C.Encrypt(env, (C.jobject)(p), (*C.char)(unsafe.Pointer(cid)), (C.int)(len(id)), (*C.char)(unsafe.Pointer(cdata)), (C.int)(len(data)), C.int(curint))
|
|
defer C.free(unsafe.Pointer(retc))
|
|
ret = C.GoString(retc)
|
|
})
|
|
return ret
|
|
}
|
|
|
|
func RunInJVM(f func(env *C.JNIEnv)) {
|
|
runtime.LockOSThread()
|
|
defer runtime.UnlockOSThread()
|
|
var env *C.JNIEnv
|
|
var detach bool
|
|
if res := C.GetEnv(theJVM, &env, C.JNI_VERSION_1_6); res != C.JNI_OK {
|
|
if res != C.JNI_EDETACHED {
|
|
panic(fmt.Errorf("JNI GetEnv failed with error %d", res))
|
|
}
|
|
if C.AttachCurrentThread(theJVM, &env, nil) != C.JNI_OK {
|
|
panic(errors.New("runInJVM: AttachCurrentThread failed"))
|
|
}
|
|
detach = true
|
|
}
|
|
|
|
if detach {
|
|
defer func() {
|
|
C.DetachCurrentThread(theJVM)
|
|
}()
|
|
}
|
|
f(env)
|
|
}
|
|
|
|
//export activityResult
|
|
func activityResult(env *C.JNIEnv, class C.jclass, request, result C.jint) {
|
|
log.Printf("activityResult (%d): %d", request, result)
|
|
}
|
|
|
|
//export goStringResult
|
|
func goStringResult(env *C.JNIEnv, class C.jclass, request C.jint, str *C.char) {
|
|
fragChans[int(request)] <- C.GoString(str)
|
|
C.free(unsafe.Pointer(str))
|
|
chmux.Lock()
|
|
delete(fragChans, int(request))
|
|
chmux.Unlock()
|
|
}
|