file_android.go 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162
  1. //go:build android
  2. // +build android
  3. package mobile
  4. /*
  5. #cgo LDFLAGS: -landroid -llog
  6. #include <stdlib.h>
  7. #include <stdbool.h>
  8. bool existsURI(uintptr_t jni_env, uintptr_t ctx, char* uriCstr);
  9. void* openStream(uintptr_t jni_env, uintptr_t ctx, char* uriCstr);
  10. char* readStream(uintptr_t jni_env, uintptr_t ctx, void* stream, int len, int* total);
  11. void* saveStream(uintptr_t jni_env, uintptr_t ctx, char* uriCstr);
  12. void writeStream(uintptr_t jni_env, uintptr_t ctx, void* stream, char* data, int len);
  13. void closeStream(uintptr_t jni_env, uintptr_t ctx, void* stream);
  14. */
  15. import "C"
  16. import (
  17. "errors"
  18. "io"
  19. "os"
  20. "unsafe"
  21. "fyne.io/fyne/v2"
  22. "fyne.io/fyne/v2/internal/driver/mobile/app"
  23. "fyne.io/fyne/v2/storage/repository"
  24. )
  25. type javaStream struct {
  26. stream unsafe.Pointer // java.io.InputStream
  27. }
  28. // Declare conformity to ReadCloser interface
  29. var _ io.ReadCloser = (*javaStream)(nil)
  30. func (s *javaStream) Read(p []byte) (int, error) {
  31. count := 0
  32. err := app.RunOnJVM(func(_, env, ctx uintptr) error {
  33. cCount := C.int(0)
  34. cBytes := unsafe.Pointer(C.readStream(C.uintptr_t(env), C.uintptr_t(ctx), s.stream, C.int(len(p)), &cCount))
  35. if cCount == -1 {
  36. return io.EOF
  37. }
  38. defer C.free(cBytes)
  39. count = int(cCount) // avoid sending -1 instead of 0 on completion
  40. bytes := C.GoBytes(cBytes, cCount)
  41. for i := 0; i < int(count); i++ {
  42. p[i] = bytes[i]
  43. }
  44. return nil
  45. })
  46. return int(count), err
  47. }
  48. func (s *javaStream) Close() error {
  49. app.RunOnJVM(func(_, env, ctx uintptr) error {
  50. C.closeStream(C.uintptr_t(env), C.uintptr_t(ctx), s.stream)
  51. return nil
  52. })
  53. return nil
  54. }
  55. func openStream(uri string) unsafe.Pointer {
  56. uriStr := C.CString(uri)
  57. defer C.free(unsafe.Pointer(uriStr))
  58. var stream unsafe.Pointer
  59. app.RunOnJVM(func(_, env, ctx uintptr) error {
  60. streamPtr := C.openStream(C.uintptr_t(env), C.uintptr_t(ctx), uriStr)
  61. if streamPtr == C.NULL {
  62. return os.ErrNotExist
  63. }
  64. stream = unsafe.Pointer(streamPtr)
  65. return nil
  66. })
  67. return stream
  68. }
  69. func nativeFileOpen(f *fileOpen) (io.ReadCloser, error) {
  70. if f.uri == nil || f.uri.String() == "" {
  71. return nil, nil
  72. }
  73. ret := openStream(f.uri.String())
  74. if ret == nil {
  75. return nil, errors.New("resource not found at URI")
  76. }
  77. stream := &javaStream{}
  78. stream.stream = ret
  79. return stream, nil
  80. }
  81. func saveStream(uri string) unsafe.Pointer {
  82. uriStr := C.CString(uri)
  83. defer C.free(unsafe.Pointer(uriStr))
  84. var stream unsafe.Pointer
  85. app.RunOnJVM(func(_, env, ctx uintptr) error {
  86. streamPtr := C.saveStream(C.uintptr_t(env), C.uintptr_t(ctx), uriStr)
  87. if streamPtr == C.NULL {
  88. return os.ErrNotExist
  89. }
  90. stream = unsafe.Pointer(streamPtr)
  91. return nil
  92. })
  93. return stream
  94. }
  95. func nativeFileSave(f *fileSave) (io.WriteCloser, error) {
  96. if f.uri == nil || f.uri.String() == "" {
  97. return nil, nil
  98. }
  99. ret := saveStream(f.uri.String())
  100. if ret == nil {
  101. return nil, errors.New("resource not found at URI")
  102. }
  103. stream := &javaStream{}
  104. stream.stream = ret
  105. return stream, nil
  106. }
  107. // Declare conformity to WriteCloser interface
  108. var _ io.WriteCloser = (*javaStream)(nil)
  109. func (s *javaStream) Write(p []byte) (int, error) {
  110. err := app.RunOnJVM(func(_, env, ctx uintptr) error {
  111. C.writeStream(C.uintptr_t(env), C.uintptr_t(ctx), s.stream, (*C.char)(C.CBytes(p)), C.int(len(p)))
  112. return nil
  113. })
  114. return len(p), err
  115. }
  116. func existsURI(uri fyne.URI) (bool, error) {
  117. uriStr := C.CString(uri.String())
  118. defer C.free(unsafe.Pointer(uriStr))
  119. ok := false
  120. app.RunOnJVM(func(_, env, ctx uintptr) error {
  121. ok = bool(C.existsURI(C.uintptr_t(env), C.uintptr_t(ctx), uriStr))
  122. return nil
  123. })
  124. return ok, nil
  125. }
  126. func registerRepository(d *mobileDriver) {
  127. repo := &mobileFileRepo{}
  128. repository.Register("file", repo)
  129. repository.Register("content", repo)
  130. }