diff --git a/src/bundle.nim b/src/bundle.nim index b50e2a9..ca6c897 100644 --- a/src/bundle.nim +++ b/src/bundle.nim @@ -97,5 +97,7 @@ when defined(android): export platform.myouAndroidGetJniEnv export platform.myouAndroidGetInternalDataPath export platform.myouAndroidGetExternalDataPath + export platform.myouAndroidAPKFilePointerLength + export platform.myouCloseMobileApp export platform.myouSetKeyboardVisible diff --git a/src/platform/glfm_wrap.nim b/src/platform/glfm_wrap.nim index 7532650..fc1088d 100644 --- a/src/platform/glfm_wrap.nim +++ b/src/platform/glfm_wrap.nim @@ -324,8 +324,17 @@ proc myouAndroidGetJniEnv*(): pointer = # Ussing offsets from ANativeActivity let vm = cast[ptr ptr array[7, pointer]](activity[1]) # Using offsets from jni.h - let GetEnv = cast[proc(vm: pointer, penv: var pointer, version: int32): int32 {.cdecl, gcsafe.}](vm[][6]) - discard GetEnv(vm, result, 0x00010006'i32) + let getEnv = cast[proc(vm: pointer, penv: var pointer, version: int32): int32 {.cdecl, gcsafe.}](vm[][6]) + let attachCurrentThread = cast[proc(vm: pointer, penv: ptr pointer, args: pointer): int32 {.cdecl, gcsafe.}](vm[][4]) + let status = getEnv(vm, result, 0x00010006'i32) + if status == -2: # JNI_EDETACHED + # Attach thread to VM + if attachCurrentThread(vm, result.addr, nil) != 0: + echo "could not attach thread to VM" + result = nil + elif status != 0: # JNI_OK + result = nil + # TODO: do we ever need to detach a thread from the VM? proc myouAndroidGetInternalDataPath*(): string = when defined(android): @@ -337,5 +346,39 @@ proc myouAndroidGetExternalDataPath*(): string = let activity = cast[ptr array[6, cstring]](window.glfmAndroidGetActivity()) return $activity[5] +when defined(android): + proc AAssetManager_open(asset_manager: pointer, filename: cstring, mode: int32): pointer {.importc,cdecl.} + proc AAsset_close(asset: pointer) {.importc,cdecl.} + proc AAsset_getBuffer(asset: pointer): pointer {.importc,cdecl.} + proc AAsset_getLength64(asset: pointer): int64 {.importc,cdecl.} + proc ANativeActivity_finish(activity: pointer) {.importc,cdecl.} + +type myouAAssetObj = object + asset: pointer + p*: pointer + len*: int + +type myouAAsset* = ref myouAAssetObj + +proc `=destroy`(x: var myouAAssetObj) = + if x.asset != nil: + AAsset_close(x.asset) + x.asset = nil + +proc myouAndroidAPKFilePointerLength*(path: string): myouAAsset = + let activity = cast[ptr array[9, pointer]](window.glfmAndroidGetActivity()) + # Ussing offsets from ANativeActivity, assuming all pointers are aligned + let asset_manager = activity[8] + let asset = AAssetManager_open(asset_manager, path.cstring, 3) # 3 = buffer mode + if asset == nil: + echo "not found in APK: ", path + return myouAAsset() + let p = AAsset_getBuffer(asset) + let len = AAsset_getLength64(asset).int + myouAAsset(asset: asset, p: p, len: len) + proc myouSetKeyboardVisible*(show: bool) = window.glfmSetKeyboardVisible(show) + +proc myouCloseMobileApp*() = + ANativeActivity_finish(window.glfmAndroidGetActivity())