package ble /* #cgo LDFLAGS: -landroid -llog #include #include #include static jobject gClassLoader; static jmethodID gFindClassMethod; jclass GetObjectClass(JNIEnv* env, jobject obj) { jclass cls = (*env)->GetObjectClass(env, obj); cls = (*env)->NewGlobalRef(env, cls); return cls; } void SetLoader(JNIEnv* env, jobject context) { jclass cclass = (*env)->GetObjectClass(env, context); jmethodID gcl_id = (*env)->GetMethodID(env, cclass, "getClassLoader", "()Ljava/lang/ClassLoader;"); jobject loader = (*env)->CallObjectMethod(env, context, gcl_id); gClassLoader = (*env)->NewGlobalRef(env, loader); jclass lclass = (*env)->GetObjectClass(env, loader); gFindClassMethod = (*env)->GetMethodID(env, lclass, "findClass", "(Ljava/lang/String;)Ljava/lang/Class;"); } jobject GetBluetoothAdapter(JNIEnv* env, jobject ctx) { jclass cls = (*env)->GetObjectClass(env, ctx); if (cls == NULL) { __android_log_write(ANDROID_LOG_DEBUG, "gio", "GetBluetoothAdapter(): Can't get context class"); return NULL; } jfieldID id = (*env)->GetStaticFieldID(env, cls, "BLUETOOTH_SERVICE", "Ljava/lang/String;"); if (id == NULL) { __android_log_write(ANDROID_LOG_DEBUG, "gio", "GetBluetoothAdapter(): Can't get field ID"); return NULL; } jstring btsrv = (jstring)(*env)->GetStaticObjectField(env, cls, id); if (btsrv == NULL) { __android_log_write(ANDROID_LOG_DEBUG, "gio", "GetBluetoothAdapter(): Can't get static object field"); return NULL; } jmethodID mid = (*env)->GetMethodID(env, cls, "getSystemService", "(Ljava/lang/String;)Ljava/lang/Object;"); if (mid == NULL) { __android_log_write(ANDROID_LOG_DEBUG, "gio", "GetBluetoothAdapter(): Can't get method ID"); return NULL; } jobject manager = (*env)->CallObjectMethod(env, ctx, mid, btsrv); if (manager == NULL) { __android_log_write(ANDROID_LOG_DEBUG, "gio", "GetBluetoothAdapter(): Can't get bluetooth manager"); return NULL; } cls = (*env)->GetObjectClass(env, manager); if (cls == NULL) { __android_log_write(ANDROID_LOG_DEBUG, "gio", "GetBluetoothAdapter(): Can't get class of bluetooth manager"); return NULL; } mid = (*env)->GetMethodID(env, cls, "getAdapter", "()Landroid/bluetooth/BluetoothAdapter;"); if (mid == NULL) { __android_log_write(ANDROID_LOG_DEBUG, "gio", "GetBluetoothAdapter(): Can't get methodID for getAdapter()"); return NULL; } jobject ad = (*env)->CallObjectMethod(env, manager, mid); if (ad == NULL) { __android_log_write(ANDROID_LOG_DEBUG, "gio", "GetBluetoothAdapter(): Can't get adapter"); } else { __android_log_write(ANDROID_LOG_DEBUG, "gio", "GetBluetoothAdapter(): Found"); } ad = (*env)->NewGlobalRef(env, ad); return ad; } jstring GetObjectStaticStringField(JNIEnv* env, jobject obj, char* fld) { jclass cls = (*env)->GetObjectClass(env, obj); if (cls == NULL) { __android_log_write(ANDROID_LOG_DEBUG, "gio", "GetObjectStaticStringField(): Can't get class"); return NULL; } jfieldID id = (*env)->GetStaticFieldID(env, cls, fld, "Ljava/lang/String;"); if (id == NULL) { __android_log_write(ANDROID_LOG_DEBUG, "gio", "GetObjectStaticStringField(): Can't find FieldID"); return NULL; } return (jstring)(*env)->GetStaticObjectField(env, cls, id); } jclass FindClass(JNIEnv* env, char* name) { jstring strClassName = (*env)->NewStringUTF(env, name); return (*env)->CallObjectMethod(env, gClassLoader, gFindClassMethod, strClassName); } JNIEXPORT jobject CreateObject(JNIEnv* env, jclass cls) { jmethodID init = (*env)->GetMethodID(env, cls, "", "()V"); return (*env)->NewObject(env, cls, init); } void CallVoidMethod(JNIEnv *env, jobject obj, jmethodID methodID) { (*env)->CallVoidMethod(env, obj, methodID); } jboolean CallBooleanMethod(JNIEnv *env, jobject obj, jmethodID mid) { return (*env)->CallBooleanMethod(env, obj, mid); } jint CallIntMethod(JNIEnv *env, jobject obj, jmethodID methodID) { return (*env)->CallIntMethod(env, obj, methodID); } jmethodID GetMethodID(JNIEnv *env, jclass clazz, const char *name, const char *sig) { return (*env)->GetMethodID(env, clazz, name, sig); } jint GetEnv(JavaVM *vm, JNIEnv **env, jint version) { return (*vm)->GetEnv(vm, (void **)env, version); } jint AttachCurrentThread(JavaVM *vm, JNIEnv **p_env, void *thr_args) { return (*vm)->AttachCurrentThread(vm, p_env, thr_args); } jint DetachCurrentThread(JavaVM *vm) { return (*vm)->DetachCurrentThread(vm); } */ import "C" import ( "errors" "fmt" "log" "runtime" "unsafe" ) var theJVM *C.JavaVM type JNIEnv = C.JNIEnv func setJVM(jvm, context uintptr) { log.Print("set theJVM") theJVM = (*C.JavaVM)(unsafe.Pointer(jvm)) //log.Printf("theJVM = %d", uintptr(unsafe.Pointer(theJVM))) 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 JniGetObjectClass(env *C.JNIEnv, obj C.jobject) C.jclass { return C.GetObjectClass(env, obj) } func JniGetObjectStaticStringField(env *C.JNIEnv, obj C.jobject, fld string) C.jstring { cstring := C.CString(fld) defer C.free(unsafe.Pointer(cstring)) return C.GetObjectStaticStringField(env, obj, cstring) } func GetBluetoothAdapter(env *C.JNIEnv, ctx uintptr) C.jobject { return C.GetBluetoothAdapter(env, (C.jobject)(ctx)) } func JniCallVoidMethod(env *C.JNIEnv, obj C.jobject, methodID C.jmethodID) { C.CallVoidMethod(env, obj, methodID) } func JniCallBooleanMethod(env *C.JNIEnv, obj C.jobject, methodID C.jmethodID) bool { return C.CallBooleanMethod(env, obj, methodID) == 0 } 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)) } func RunInJVM(f func(env *C.JNIEnv)) { runtime.LockOSThread() defer runtime.UnlockOSThread() var env *C.JNIEnv var detach bool //log.Printf("RunInJVM(): theJVM = %d", uintptr(unsafe.Pointer(theJVM))) 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) }