github.com/SahandAslani/gomobile@v0.0.0-20210909130135-2cb2d44c09b2/asset/asset_android.go (about) 1 // Copyright 2015 The Go Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 5 package asset 6 7 /* 8 #cgo LDFLAGS: -landroid 9 #include <android/asset_manager.h> 10 #include <android/asset_manager_jni.h> 11 #include <jni.h> 12 #include <stdlib.h> 13 14 static AAssetManager* asset_manager_init(uintptr_t java_vm, uintptr_t jni_env, jobject ctx) { 15 JavaVM* vm = (JavaVM*)java_vm; 16 JNIEnv* env = (JNIEnv*)jni_env; 17 18 // Equivalent to: 19 // assetManager = ctx.getResources().getAssets(); 20 jclass ctx_clazz = (*env)->FindClass(env, "android/content/Context"); 21 jmethodID getres_id = (*env)->GetMethodID(env, ctx_clazz, "getResources", "()Landroid/content/res/Resources;"); 22 jobject res = (*env)->CallObjectMethod(env, ctx, getres_id); 23 jclass res_clazz = (*env)->FindClass(env, "android/content/res/Resources"); 24 jmethodID getam_id = (*env)->GetMethodID(env, res_clazz, "getAssets", "()Landroid/content/res/AssetManager;"); 25 jobject am = (*env)->CallObjectMethod(env, res, getam_id); 26 27 // Pin the AssetManager and load an AAssetManager from it. 28 am = (*env)->NewGlobalRef(env, am); 29 return AAssetManager_fromJava(env, am); 30 } 31 */ 32 import "C" 33 import ( 34 "fmt" 35 "io" 36 "log" 37 "os" 38 "sync" 39 "unsafe" 40 41 "github.com/SahandAslani/gomobile/internal/mobileinit" 42 ) 43 44 var assetOnce sync.Once 45 46 // asset_manager is the asset manager of the app. 47 var assetManager *C.AAssetManager 48 49 func assetInit() { 50 err := mobileinit.RunOnJVM(func(vm, env, ctx uintptr) error { 51 assetManager = C.asset_manager_init(C.uintptr_t(vm), C.uintptr_t(env), C.jobject(ctx)) 52 return nil 53 }) 54 if err != nil { 55 log.Fatalf("asset: %v", err) 56 } 57 } 58 59 func openAsset(name string) (File, error) { 60 assetOnce.Do(assetInit) 61 cname := C.CString(name) 62 defer C.free(unsafe.Pointer(cname)) 63 a := &asset{ 64 ptr: C.AAssetManager_open(assetManager, cname, C.AASSET_MODE_UNKNOWN), 65 name: name, 66 } 67 if a.ptr == nil { 68 return nil, a.errorf("open", "bad asset") 69 } 70 return a, nil 71 } 72 73 type asset struct { 74 ptr *C.AAsset 75 name string 76 } 77 78 func (a *asset) errorf(op string, format string, v ...interface{}) error { 79 return &os.PathError{ 80 Op: op, 81 Path: a.name, 82 Err: fmt.Errorf(format, v...), 83 } 84 } 85 86 func (a *asset) Read(p []byte) (n int, err error) { 87 n = int(C.AAsset_read(a.ptr, unsafe.Pointer(&p[0]), C.size_t(len(p)))) 88 if n == 0 && len(p) > 0 { 89 return 0, io.EOF 90 } 91 if n < 0 { 92 return 0, a.errorf("read", "negative bytes: %d", n) 93 } 94 return n, nil 95 } 96 97 func (a *asset) Seek(offset int64, whence int) (int64, error) { 98 // TODO(crawshaw): use AAsset_seek64 if it is available. 99 off := C.AAsset_seek(a.ptr, C.off_t(offset), C.int(whence)) 100 if off == -1 { 101 return 0, a.errorf("seek", "bad result for offset=%d, whence=%d", offset, whence) 102 } 103 return int64(off), nil 104 } 105 106 func (a *asset) Close() error { 107 C.AAsset_close(a.ptr) 108 return nil 109 }