Further restructuring and add stub implementation for Android.
This commit is contained in:
parent
206bd70461
commit
f036c5e134
2
ble.go
2
ble.go
|
@ -245,7 +245,7 @@ func (b *BLE) Connect(p Peripheral) bool {
|
|||
return false
|
||||
}
|
||||
b.Unlock()
|
||||
if p.p == nil {
|
||||
if p.IsIncomplete() {
|
||||
var ok bool
|
||||
p, ok = b.knownPeripheral(p)
|
||||
if !ok {
|
||||
|
|
103
ble_android.go
Normal file
103
ble_android.go
Normal file
|
@ -0,0 +1,103 @@
|
|||
package ble
|
||||
|
||||
import (
|
||||
"gioui.org/app"
|
||||
)
|
||||
|
||||
// Types required for ble.go
|
||||
|
||||
type bleState string
|
||||
|
||||
type bleHandle struct {
|
||||
}
|
||||
|
||||
type Peripheral struct {
|
||||
Name string
|
||||
RSSI int
|
||||
Identifier string
|
||||
}
|
||||
|
||||
type Service string
|
||||
type Characteristic string
|
||||
|
||||
// Internal global variables
|
||||
|
||||
// Functions required by API
|
||||
|
||||
//Init needs to be called before the BLE library can be used. On Android we
|
||||
//need to set up the JVM by calling setJVM in jni_android.go.
|
||||
func Init() {
|
||||
h := app.PlatformHandle()
|
||||
setJVM(h.JVM, h.Context)
|
||||
}
|
||||
|
||||
//peripheralLookup returns a pointer to a BLE struct related to the given
|
||||
//Peripheral.
|
||||
func peripheralLookup(p Peripheral) *BLE {
|
||||
return &BLE{}
|
||||
}
|
||||
|
||||
//newPeripheral creates a new Peripheral struct
|
||||
func newPeripheral() Peripheral {
|
||||
return Peripheral{}
|
||||
}
|
||||
|
||||
func (p Peripheral) IsIncomplete() bool {
|
||||
return false
|
||||
}
|
||||
|
||||
func (p Peripheral) Retain() {
|
||||
}
|
||||
|
||||
//stringState returns a string version of the BLE state
|
||||
func (b *BLE) stringState() string {
|
||||
return ""
|
||||
}
|
||||
|
||||
//readyToScan returns true if the hardware is ready to initiate a scan
|
||||
func (b *BLE) readyToScan() bool {
|
||||
return true
|
||||
}
|
||||
|
||||
//scan puts the BLE hardware into scanning mode
|
||||
func (b *BLE) scan() {
|
||||
}
|
||||
|
||||
//stopScan stops a scan in progress
|
||||
func (b *BLE) stopScan() {
|
||||
}
|
||||
|
||||
//connectPeripheral attempts to connect to a Peripheral
|
||||
func (b *BLE) connectPeripheral(x Peripheral) {
|
||||
}
|
||||
|
||||
//cancelConnection cancels an in-progress connection attempt
|
||||
func (b *BLE) cancelConnection(p Peripheral) {
|
||||
}
|
||||
|
||||
//knownPeripheral returns a Peripheral that is known to the system without
|
||||
//scanning
|
||||
func (b *BLE) knownPeripheral(p Peripheral) (Peripheral, bool) {
|
||||
return Peripheral{}, false
|
||||
}
|
||||
|
||||
//DiscoverServices asks a Peripheral for its Services
|
||||
func (x Peripheral) DiscoverServices() {
|
||||
}
|
||||
|
||||
//DiscoverCharacteristics asks a Peripheral for the Characteristics related
|
||||
//to a Service
|
||||
func (p Peripheral) DiscoverCharacteristics(serv Service) {
|
||||
}
|
||||
|
||||
//SetNotifyValue subscribes to a characteristic
|
||||
func (p Peripheral) SetNotifyValue(c Characteristic) {
|
||||
}
|
||||
|
||||
//NewBLE returns a pointer to a BLE struct after setting up the OS
|
||||
//Bluetooth API.
|
||||
func NewBLE() *BLE {
|
||||
ps := Peripherals{items: make([]PeripheralListItem, 0)}
|
||||
return &BLE{events: make(chan interface{}), peripherals: ps}
|
||||
}
|
||||
|
|
@ -21,10 +21,6 @@ type bleHandle struct {
|
|||
cm *ns.CBCentralManager
|
||||
}
|
||||
|
||||
var cdLookup map[unsafe.Pointer]*BLE
|
||||
var pdLookup map[unsafe.Pointer]*BLE
|
||||
var pcache map[unsafe.Pointer]*Peripheral
|
||||
|
||||
type Peripheral struct {
|
||||
Name string
|
||||
RSSI int
|
||||
|
@ -36,11 +32,13 @@ type Peripheral struct {
|
|||
type Service *ns.CBService
|
||||
type Characteristic *ns.CBCharacteristic
|
||||
|
||||
// Functions required by API
|
||||
// Internal global variables
|
||||
|
||||
func peripheralLookup(p Peripheral) *BLE {
|
||||
return pdLookup[p.p.Ptr()]
|
||||
}
|
||||
var cdLookup map[unsafe.Pointer]*BLE
|
||||
var pdLookup map[unsafe.Pointer]*BLE
|
||||
var pcache map[unsafe.Pointer]*Peripheral
|
||||
|
||||
// Functions required by API
|
||||
|
||||
//Init needs to be called before the BLE library can be used. No setup needed
|
||||
//on Darwin.
|
||||
|
@ -48,6 +46,12 @@ func Init() {
|
|||
|
||||
}
|
||||
|
||||
//peripheralLookup returns a pointer to a BLE struct related to the given
|
||||
//Peripheral.
|
||||
func peripheralLookup(p Peripheral) *BLE {
|
||||
return pdLookup[p.p.Ptr()]
|
||||
}
|
||||
|
||||
//newPeripheral creates a new Peripheral struct
|
||||
func newPeripheral(x *ns.CBPeripheral) Peripheral {
|
||||
if pcache == nil {
|
||||
|
@ -66,6 +70,19 @@ func newPeripheral(x *ns.CBPeripheral) Peripheral {
|
|||
return ret
|
||||
}
|
||||
|
||||
func (p Peripheral) IsIncomplete() bool {
|
||||
return p.p == nil
|
||||
}
|
||||
|
||||
func (x Peripheral) Retain() {
|
||||
//NOTE: ns.ObjectAtIndex() calls SetFinalizer for us, which will be a problem
|
||||
//later when we call GC(), so we always first clear the finalizer before
|
||||
//setting a new one.
|
||||
runtime.SetFinalizer(x.p, nil)
|
||||
x.p.Retain()
|
||||
x.p.GC()
|
||||
}
|
||||
|
||||
//stringState returns a string version of the BLE state
|
||||
func (b *BLE) stringState() string {
|
||||
x := b.state
|
||||
|
@ -319,15 +336,6 @@ func peripheralName(p *ns.CBPeripheral) string {
|
|||
return ret
|
||||
}
|
||||
|
||||
func (x *Peripheral) Retain() {
|
||||
//NOTE: ns.ObjectAtIndex() calls SetFinalizer for us, which will be a problem
|
||||
//later when we call GC(), so we always first clear the finalizer before
|
||||
//setting a new one.
|
||||
runtime.SetFinalizer(x.p, nil)
|
||||
x.p.Retain()
|
||||
x.p.GC()
|
||||
}
|
||||
|
||||
func (b *BLE) setState(x ns.CBManagerState) {
|
||||
b.Lock()
|
||||
defer b.Unlock()
|
||||
|
|
131
jni_android.go
Normal file
131
jni_android.go
Normal file
|
@ -0,0 +1,131 @@
|
|||
package ble
|
||||
|
||||
/*
|
||||
#cgo LDFLAGS: -landroid
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <jni.h>
|
||||
#include <android/log.h>
|
||||
|
||||
static jobject gClassLoader;
|
||||
static jmethodID gFindClassMethod;
|
||||
|
||||
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;");
|
||||
}
|
||||
|
||||
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, "<init>", "()V");
|
||||
return (*env)->NewObject(env, cls, init);
|
||||
}
|
||||
|
||||
void CallVoidMethod(JNIEnv *env, jobject obj, jmethodID methodID) {
|
||||
(*env)->CallVoidMethod(env, obj, methodID);
|
||||
}
|
||||
|
||||
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 JniCallVoidMethod(env *C.JNIEnv, obj C.jobject, methodID C.jmethodID) {
|
||||
C.CallVoidMethod(env, obj, methodID)
|
||||
}
|
||||
|
||||
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)
|
||||
}
|
Loading…
Reference in New Issue
Block a user