replate-camera 0.17.2 → 0.18.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (236) hide show
  1. package/android/app/build.gradle +76 -0
  2. package/android/app/src/debug/AndroidManifest.xml +4 -0
  3. package/android/app/src/main/AndroidManifest.xml +30 -0
  4. package/android/app/src/main/assets/unlit_color.filamat +0 -0
  5. package/android/app/src/main/java/com/lucarinaldii/replatecamera/MainActivity.kt +13 -0
  6. package/android/app/src/main/java/com/lucarinaldii/replatecamera/MainApplication.kt +50 -0
  7. package/android/app/src/main/java/com/replatecamera/FocusNode.kt +131 -0
  8. package/android/app/src/main/java/com/replatecamera/HighQualityPhotoCapture.kt +361 -0
  9. package/android/app/src/main/java/com/replatecamera/ReplateCameraCaptureController.kt +353 -0
  10. package/android/app/src/main/java/com/replatecamera/ReplateCameraController.kt +286 -0
  11. package/android/app/src/main/java/com/replatecamera/ReplateCameraPackage.kt +17 -0
  12. package/android/app/src/main/java/com/replatecamera/ReplateCameraView.kt +1826 -0
  13. package/android/app/src/main/java/com/replatecamera/ReplateCameraViewManager.kt +25 -0
  14. package/android/build.gradle +19 -74
  15. package/android/gradle.properties +15 -5
  16. package/android/lib/build/generated/source/buildConfig/debug/com/replatecamera/BuildConfig.java +10 -0
  17. package/android/lib/build/intermediates/aapt_friendly_merged_manifests/debug/aapt/AndroidManifest.xml +18 -0
  18. package/android/lib/build/intermediates/aapt_friendly_merged_manifests/debug/aapt/output-metadata.json +18 -0
  19. package/android/lib/build/intermediates/aar_metadata/debug/aar-metadata.properties +5 -0
  20. package/android/lib/build/intermediates/annotation_processor_list/debug/annotationProcessors.json +1 -0
  21. package/android/lib/build/intermediates/compile_library_classes_jar/debug/classes.jar +0 -0
  22. package/android/lib/build/intermediates/compile_r_class_jar/debug/R.jar +0 -0
  23. package/android/lib/build/intermediates/compile_symbol_list/debug/R.txt +0 -0
  24. package/android/lib/build/intermediates/incremental/debug/packageDebugResources/compile-file-map.properties +1 -0
  25. package/android/lib/build/intermediates/incremental/debug/packageDebugResources/merger.xml +2 -0
  26. package/android/lib/build/intermediates/incremental/mergeDebugJniLibFolders/merger.xml +2 -0
  27. package/android/lib/build/intermediates/incremental/mergeDebugShaders/merger.xml +2 -0
  28. package/android/lib/build/intermediates/incremental/packageDebugAssets/merger.xml +2 -0
  29. package/android/lib/build/intermediates/java_res/debug/out/META-INF/replate-camera_debug.kotlin_module +0 -0
  30. package/android/lib/build/intermediates/javac/debug/classes/com/replatecamera/BuildConfig.class +0 -0
  31. package/android/lib/build/intermediates/library_assets/debug/out/unlit_color.filamat +0 -0
  32. package/android/lib/build/intermediates/local_only_symbol_list/debug/R-def.txt +2 -0
  33. package/android/lib/build/intermediates/manifest_merge_blame_file/debug/manifest-merger-blame-debug-report.txt +28 -0
  34. package/android/lib/build/intermediates/merged_manifest/debug/AndroidManifest.xml +18 -0
  35. package/android/lib/build/intermediates/navigation_json/debug/navigation.json +1 -0
  36. package/android/lib/build/intermediates/runtime_library_classes_dir/debug/META-INF/replate-camera_debug.kotlin_module +0 -0
  37. package/android/lib/build/intermediates/runtime_library_classes_dir/debug/com/replatecamera/ARError$CaptureError.class +0 -0
  38. package/android/lib/build/intermediates/runtime_library_classes_dir/debug/com/replatecamera/ARError$InvalidAnchor.class +0 -0
  39. package/android/lib/build/intermediates/runtime_library_classes_dir/debug/com/replatecamera/ARError$NoAnchor.class +0 -0
  40. package/android/lib/build/intermediates/runtime_library_classes_dir/debug/com/replatecamera/ARError$NotInFocus.class +0 -0
  41. package/android/lib/build/intermediates/runtime_library_classes_dir/debug/com/replatecamera/ARError$NotInRange.class +0 -0
  42. package/android/lib/build/intermediates/runtime_library_classes_dir/debug/com/replatecamera/ARError$ProcessingError.class +0 -0
  43. package/android/lib/build/intermediates/runtime_library_classes_dir/debug/com/replatecamera/ARError$SavingError.class +0 -0
  44. package/android/lib/build/intermediates/runtime_library_classes_dir/debug/com/replatecamera/ARError$TooManyImages.class +0 -0
  45. package/android/lib/build/intermediates/runtime_library_classes_dir/debug/com/replatecamera/ARError$TransformError.class +0 -0
  46. package/android/lib/build/intermediates/runtime_library_classes_dir/debug/com/replatecamera/ARError$Unknown.class +0 -0
  47. package/android/lib/build/intermediates/runtime_library_classes_dir/debug/com/replatecamera/ARError.class +0 -0
  48. package/android/lib/build/intermediates/runtime_library_classes_dir/debug/com/replatecamera/BuildConfig.class +0 -0
  49. package/android/lib/build/intermediates/runtime_library_classes_dir/debug/com/replatecamera/DeviceTargetInfo.class +0 -0
  50. package/android/lib/build/intermediates/runtime_library_classes_dir/debug/com/replatecamera/FocusNode$Companion.class +0 -0
  51. package/android/lib/build/intermediates/runtime_library_classes_dir/debug/com/replatecamera/FocusNode$buildSquare$1.class +0 -0
  52. package/android/lib/build/intermediates/runtime_library_classes_dir/debug/com/replatecamera/FocusNode$loadUnlitMaterial$1.class +0 -0
  53. package/android/lib/build/intermediates/runtime_library_classes_dir/debug/com/replatecamera/FocusNode.class +0 -0
  54. package/android/lib/build/intermediates/runtime_library_classes_dir/debug/com/replatecamera/HighQualityPhotoCapture$Companion.class +0 -0
  55. package/android/lib/build/intermediates/runtime_library_classes_dir/debug/com/replatecamera/HighQualityPhotoCapture$capture$1$1$1.class +0 -0
  56. package/android/lib/build/intermediates/runtime_library_classes_dir/debug/com/replatecamera/HighQualityPhotoCapture$takeSensorJpeg$sessionCallback$1$onConfigured$1.class +0 -0
  57. package/android/lib/build/intermediates/runtime_library_classes_dir/debug/com/replatecamera/HighQualityPhotoCapture$takeSensorJpeg$sessionCallback$1.class +0 -0
  58. package/android/lib/build/intermediates/runtime_library_classes_dir/debug/com/replatecamera/HighQualityPhotoCapture$takeSensorJpeg$stateCallback$1.class +0 -0
  59. package/android/lib/build/intermediates/runtime_library_classes_dir/debug/com/replatecamera/HighQualityPhotoCapture.class +0 -0
  60. package/android/lib/build/intermediates/runtime_library_classes_dir/debug/com/replatecamera/ReplateCameraCaptureController$Companion.class +0 -0
  61. package/android/lib/build/intermediates/runtime_library_classes_dir/debug/com/replatecamera/ReplateCameraCaptureController$processAndSaveImage$1.class +0 -0
  62. package/android/lib/build/intermediates/runtime_library_classes_dir/debug/com/replatecamera/ReplateCameraCaptureController$processTargetedDevice$1$1.class +0 -0
  63. package/android/lib/build/intermediates/runtime_library_classes_dir/debug/com/replatecamera/ReplateCameraCaptureController$triggerAutoCaptureIfNewAngle$1$1.class +0 -0
  64. package/android/lib/build/intermediates/runtime_library_classes_dir/debug/com/replatecamera/ReplateCameraCaptureController$triggerAutoCaptureIfNewAngle$1.class +0 -0
  65. package/android/lib/build/intermediates/runtime_library_classes_dir/debug/com/replatecamera/ReplateCameraCaptureController.class +0 -0
  66. package/android/lib/build/intermediates/runtime_library_classes_dir/debug/com/replatecamera/ReplateCameraController$Companion.class +0 -0
  67. package/android/lib/build/intermediates/runtime_library_classes_dir/debug/com/replatecamera/ReplateCameraController.class +0 -0
  68. package/android/lib/build/intermediates/runtime_library_classes_dir/debug/com/replatecamera/ReplateCameraPackage.class +0 -0
  69. package/android/lib/build/intermediates/runtime_library_classes_dir/debug/com/replatecamera/ReplateCameraView$Companion.class +0 -0
  70. package/android/lib/build/intermediates/runtime_library_classes_dir/debug/com/replatecamera/ReplateCameraView$GestureListener.class +0 -0
  71. package/android/lib/build/intermediates/runtime_library_classes_dir/debug/com/replatecamera/ReplateCameraView$ScaleListener.class +0 -0
  72. package/android/lib/build/intermediates/runtime_library_classes_dir/debug/com/replatecamera/ReplateCameraView$WhenMappings.class +0 -0
  73. package/android/lib/build/intermediates/runtime_library_classes_dir/debug/com/replatecamera/ReplateCameraView$initializeSceneView$1$1.class +0 -0
  74. package/android/lib/build/intermediates/runtime_library_classes_dir/debug/com/replatecamera/ReplateCameraView$makeUnlitMaterial$1.class +0 -0
  75. package/android/lib/build/intermediates/runtime_library_classes_dir/debug/com/replatecamera/ReplateCameraView$makeUnlitMaterial$2$1.class +0 -0
  76. package/android/lib/build/intermediates/runtime_library_classes_dir/debug/com/replatecamera/ReplateCameraView$makeUnlitMaterial$3.class +0 -0
  77. package/android/lib/build/intermediates/runtime_library_classes_dir/debug/com/replatecamera/ReplateCameraView$prebuildBaseMaterial$1.class +0 -0
  78. package/android/lib/build/intermediates/runtime_library_classes_dir/debug/com/replatecamera/ReplateCameraView$selectBestCameraConfig$$inlined$compareBy$1.class +0 -0
  79. package/android/lib/build/intermediates/runtime_library_classes_dir/debug/com/replatecamera/ReplateCameraView$selectBestCameraConfig$$inlined$thenBy$1.class +0 -0
  80. package/android/lib/build/intermediates/runtime_library_classes_dir/debug/com/replatecamera/ReplateCameraView$updateSphereColor$4.class +0 -0
  81. package/android/lib/build/intermediates/runtime_library_classes_dir/debug/com/replatecamera/ReplateCameraView.class +0 -0
  82. package/android/lib/build/intermediates/runtime_library_classes_dir/debug/com/replatecamera/ReplateCameraViewManager.class +0 -0
  83. package/android/lib/build/intermediates/runtime_library_classes_dir/debug/com/replatecamera/SafeCallbackHandler.class +0 -0
  84. package/android/lib/build/intermediates/runtime_library_classes_jar/debug/classes.jar +0 -0
  85. package/android/lib/build/intermediates/symbol_list_with_package_name/debug/package-aware-r.txt +1 -0
  86. package/android/lib/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/inputs/source-to-output.tab +0 -0
  87. package/android/lib/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/inputs/source-to-output.tab.keystream +0 -0
  88. package/android/lib/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/inputs/source-to-output.tab.keystream.len +0 -0
  89. package/android/lib/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/inputs/source-to-output.tab.len +0 -0
  90. package/android/lib/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/inputs/source-to-output.tab.values.at +0 -0
  91. package/android/lib/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/inputs/source-to-output.tab_i +0 -0
  92. package/android/lib/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/inputs/source-to-output.tab_i.len +0 -0
  93. package/android/lib/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/class-attributes.tab +0 -0
  94. package/android/lib/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/class-attributes.tab.keystream +0 -0
  95. package/android/lib/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/class-attributes.tab.keystream.len +0 -0
  96. package/android/lib/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/class-attributes.tab.len +0 -0
  97. package/android/lib/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/class-attributes.tab.values.at +0 -0
  98. package/android/lib/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/class-attributes.tab_i +0 -0
  99. package/android/lib/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/class-attributes.tab_i.len +0 -0
  100. package/android/lib/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/class-fq-name-to-source.tab +0 -0
  101. package/android/lib/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/class-fq-name-to-source.tab.keystream +0 -0
  102. package/android/lib/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/class-fq-name-to-source.tab.keystream.len +0 -0
  103. package/android/lib/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/class-fq-name-to-source.tab.len +0 -0
  104. package/android/lib/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/class-fq-name-to-source.tab.values.at +0 -0
  105. package/android/lib/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/class-fq-name-to-source.tab_i +0 -0
  106. package/android/lib/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/class-fq-name-to-source.tab_i.len +0 -0
  107. package/android/lib/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/internal-name-to-source.tab +0 -0
  108. package/android/lib/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/internal-name-to-source.tab.keystream +0 -0
  109. package/android/lib/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/internal-name-to-source.tab.keystream.len +0 -0
  110. package/android/lib/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/internal-name-to-source.tab.len +0 -0
  111. package/android/lib/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/internal-name-to-source.tab.values.at +0 -0
  112. package/android/lib/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/internal-name-to-source.tab_i +0 -0
  113. package/android/lib/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/internal-name-to-source.tab_i.len +0 -0
  114. package/android/lib/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/proto.tab +0 -0
  115. package/android/lib/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/proto.tab.keystream +0 -0
  116. package/android/lib/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/proto.tab.keystream.len +0 -0
  117. package/android/lib/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/proto.tab.len +0 -0
  118. package/android/lib/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/proto.tab.values +0 -0
  119. package/android/lib/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/proto.tab.values.at +0 -0
  120. package/android/lib/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/proto.tab.values.s +1 -0
  121. package/android/lib/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/proto.tab_i +0 -0
  122. package/android/lib/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/proto.tab_i.len +0 -0
  123. package/android/lib/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/source-to-classes.tab +0 -0
  124. package/android/lib/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/source-to-classes.tab.keystream +0 -0
  125. package/android/lib/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/source-to-classes.tab.keystream.len +0 -0
  126. package/android/lib/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/source-to-classes.tab.len +0 -0
  127. package/android/lib/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/source-to-classes.tab.values.at +0 -0
  128. package/android/lib/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/source-to-classes.tab_i +0 -0
  129. package/android/lib/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/source-to-classes.tab_i.len +0 -0
  130. package/android/lib/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/subtypes.tab +0 -0
  131. package/android/lib/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/subtypes.tab.keystream +0 -0
  132. package/android/lib/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/subtypes.tab.keystream.len +0 -0
  133. package/android/lib/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/subtypes.tab.len +0 -0
  134. package/android/lib/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/subtypes.tab.values.at +0 -0
  135. package/android/lib/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/subtypes.tab_i +0 -0
  136. package/android/lib/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/subtypes.tab_i.len +0 -0
  137. package/android/lib/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/supertypes.tab +0 -0
  138. package/android/lib/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/supertypes.tab.keystream +0 -0
  139. package/android/lib/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/supertypes.tab.keystream.len +0 -0
  140. package/android/lib/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/supertypes.tab.len +0 -0
  141. package/android/lib/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/supertypes.tab.values.at +0 -0
  142. package/android/lib/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/supertypes.tab_i +0 -0
  143. package/android/lib/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/supertypes.tab_i.len +0 -0
  144. package/android/lib/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/counters.tab +2 -0
  145. package/android/lib/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/file-to-id.tab +0 -0
  146. package/android/lib/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/file-to-id.tab.keystream +0 -0
  147. package/android/lib/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/file-to-id.tab.keystream.len +0 -0
  148. package/android/lib/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/file-to-id.tab.len +0 -0
  149. package/android/lib/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/file-to-id.tab.values.at +0 -0
  150. package/android/lib/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/file-to-id.tab_i +0 -0
  151. package/android/lib/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/file-to-id.tab_i.len +0 -0
  152. package/android/lib/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/id-to-file.tab +0 -0
  153. package/android/lib/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/id-to-file.tab.keystream +0 -0
  154. package/android/lib/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/id-to-file.tab.keystream.len +0 -0
  155. package/android/lib/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/id-to-file.tab.len +0 -0
  156. package/android/lib/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/id-to-file.tab.values.at +0 -0
  157. package/android/lib/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/id-to-file.tab_i +0 -0
  158. package/android/lib/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/id-to-file.tab_i.len +0 -0
  159. package/android/lib/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/lookups.tab +0 -0
  160. package/android/lib/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/lookups.tab.keystream +0 -0
  161. package/android/lib/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/lookups.tab.keystream.len +0 -0
  162. package/android/lib/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/lookups.tab.len +0 -0
  163. package/android/lib/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/lookups.tab.values +0 -0
  164. package/android/lib/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/lookups.tab.values.at +0 -0
  165. package/android/lib/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/lookups.tab.values.s +1 -0
  166. package/android/lib/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/lookups.tab_i +0 -0
  167. package/android/lib/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/lookups.tab_i.len +0 -0
  168. package/android/lib/build/kotlin/compileDebugKotlin/cacheable/last-build.bin +0 -0
  169. package/android/lib/build/kotlin/compileDebugKotlin/local-state/build-history.bin +0 -0
  170. package/android/lib/build/outputs/logs/manifest-merger-debug-report.txt +37 -0
  171. package/android/lib/build/tmp/compileDebugJavaWithJavac/previous-compilation-data.bin +0 -0
  172. package/android/lib/build/tmp/kotlin-classes/debug/META-INF/replate-camera_debug.kotlin_module +0 -0
  173. package/android/lib/build/tmp/kotlin-classes/debug/com/replatecamera/ARError$CaptureError.class +0 -0
  174. package/android/lib/build/tmp/kotlin-classes/debug/com/replatecamera/ARError$InvalidAnchor.class +0 -0
  175. package/android/lib/build/tmp/kotlin-classes/debug/com/replatecamera/ARError$NoAnchor.class +0 -0
  176. package/android/lib/build/tmp/kotlin-classes/debug/com/replatecamera/ARError$NotInFocus.class +0 -0
  177. package/android/lib/build/tmp/kotlin-classes/debug/com/replatecamera/ARError$NotInRange.class +0 -0
  178. package/android/lib/build/tmp/kotlin-classes/debug/com/replatecamera/ARError$ProcessingError.class +0 -0
  179. package/android/lib/build/tmp/kotlin-classes/debug/com/replatecamera/ARError$SavingError.class +0 -0
  180. package/android/lib/build/tmp/kotlin-classes/debug/com/replatecamera/ARError$TooManyImages.class +0 -0
  181. package/android/lib/build/tmp/kotlin-classes/debug/com/replatecamera/ARError$TransformError.class +0 -0
  182. package/android/lib/build/tmp/kotlin-classes/debug/com/replatecamera/ARError$Unknown.class +0 -0
  183. package/android/lib/build/tmp/kotlin-classes/debug/com/replatecamera/ARError.class +0 -0
  184. package/android/lib/build/tmp/kotlin-classes/debug/com/replatecamera/DeviceTargetInfo.class +0 -0
  185. package/android/lib/build/tmp/kotlin-classes/debug/com/replatecamera/FocusNode$Companion.class +0 -0
  186. package/android/lib/build/tmp/kotlin-classes/debug/com/replatecamera/FocusNode$buildSquare$1.class +0 -0
  187. package/android/lib/build/tmp/kotlin-classes/debug/com/replatecamera/FocusNode$loadUnlitMaterial$1.class +0 -0
  188. package/android/lib/build/tmp/kotlin-classes/debug/com/replatecamera/FocusNode.class +0 -0
  189. package/android/lib/build/tmp/kotlin-classes/debug/com/replatecamera/HighQualityPhotoCapture$Companion.class +0 -0
  190. package/android/lib/build/tmp/kotlin-classes/debug/com/replatecamera/HighQualityPhotoCapture$capture$1$1$1.class +0 -0
  191. package/android/lib/build/tmp/kotlin-classes/debug/com/replatecamera/HighQualityPhotoCapture$takeSensorJpeg$sessionCallback$1$onConfigured$1.class +0 -0
  192. package/android/lib/build/tmp/kotlin-classes/debug/com/replatecamera/HighQualityPhotoCapture$takeSensorJpeg$sessionCallback$1.class +0 -0
  193. package/android/lib/build/tmp/kotlin-classes/debug/com/replatecamera/HighQualityPhotoCapture$takeSensorJpeg$stateCallback$1.class +0 -0
  194. package/android/lib/build/tmp/kotlin-classes/debug/com/replatecamera/HighQualityPhotoCapture.class +0 -0
  195. package/android/lib/build/tmp/kotlin-classes/debug/com/replatecamera/ReplateCameraCaptureController$Companion.class +0 -0
  196. package/android/lib/build/tmp/kotlin-classes/debug/com/replatecamera/ReplateCameraCaptureController$processAndSaveImage$1.class +0 -0
  197. package/android/lib/build/tmp/kotlin-classes/debug/com/replatecamera/ReplateCameraCaptureController$processTargetedDevice$1$1.class +0 -0
  198. package/android/lib/build/tmp/kotlin-classes/debug/com/replatecamera/ReplateCameraCaptureController$triggerAutoCaptureIfNewAngle$1$1.class +0 -0
  199. package/android/lib/build/tmp/kotlin-classes/debug/com/replatecamera/ReplateCameraCaptureController$triggerAutoCaptureIfNewAngle$1.class +0 -0
  200. package/android/lib/build/tmp/kotlin-classes/debug/com/replatecamera/ReplateCameraCaptureController.class +0 -0
  201. package/android/lib/build/tmp/kotlin-classes/debug/com/replatecamera/ReplateCameraController$Companion.class +0 -0
  202. package/android/lib/build/tmp/kotlin-classes/debug/com/replatecamera/ReplateCameraController.class +0 -0
  203. package/android/lib/build/tmp/kotlin-classes/debug/com/replatecamera/ReplateCameraPackage.class +0 -0
  204. package/android/lib/build/tmp/kotlin-classes/debug/com/replatecamera/ReplateCameraView$Companion.class +0 -0
  205. package/android/lib/build/tmp/kotlin-classes/debug/com/replatecamera/ReplateCameraView$GestureListener.class +0 -0
  206. package/android/lib/build/tmp/kotlin-classes/debug/com/replatecamera/ReplateCameraView$ScaleListener.class +0 -0
  207. package/android/lib/build/tmp/kotlin-classes/debug/com/replatecamera/ReplateCameraView$WhenMappings.class +0 -0
  208. package/android/lib/build/tmp/kotlin-classes/debug/com/replatecamera/ReplateCameraView$initializeSceneView$1$1.class +0 -0
  209. package/android/lib/build/tmp/kotlin-classes/debug/com/replatecamera/ReplateCameraView$makeUnlitMaterial$1.class +0 -0
  210. package/android/lib/build/tmp/kotlin-classes/debug/com/replatecamera/ReplateCameraView$makeUnlitMaterial$2$1.class +0 -0
  211. package/android/lib/build/tmp/kotlin-classes/debug/com/replatecamera/ReplateCameraView$makeUnlitMaterial$3.class +0 -0
  212. package/android/lib/build/tmp/kotlin-classes/debug/com/replatecamera/ReplateCameraView$prebuildBaseMaterial$1.class +0 -0
  213. package/android/lib/build/tmp/kotlin-classes/debug/com/replatecamera/ReplateCameraView$selectBestCameraConfig$$inlined$compareBy$1.class +0 -0
  214. package/android/lib/build/tmp/kotlin-classes/debug/com/replatecamera/ReplateCameraView$selectBestCameraConfig$$inlined$thenBy$1.class +0 -0
  215. package/android/lib/build/tmp/kotlin-classes/debug/com/replatecamera/ReplateCameraView$updateSphereColor$4.class +0 -0
  216. package/android/lib/build/tmp/kotlin-classes/debug/com/replatecamera/ReplateCameraView.class +0 -0
  217. package/android/lib/build/tmp/kotlin-classes/debug/com/replatecamera/ReplateCameraViewManager.class +0 -0
  218. package/android/lib/build/tmp/kotlin-classes/debug/com/replatecamera/SafeCallbackHandler.class +0 -0
  219. package/android/lib/build.gradle +85 -0
  220. package/android/lib/gradle.properties +6 -0
  221. package/android/lib/src/main/AndroidManifest.xml +11 -0
  222. package/android/lib/src/main/assets/unlit_color.filamat +0 -0
  223. package/android/lib/src/main/java/com/replatecamera/ReplateCameraPackage.kt +14 -0
  224. package/android/settings.gradle +5 -0
  225. package/android/src/main/java/com/replatecamera/FocusNode.kt +2 -2
  226. package/android/src/main/java/com/replatecamera/ReplateCameraController.kt +14 -44
  227. package/android/src/main/java/com/replatecamera/ReplateCameraModule.kt +1 -1
  228. package/android/src/main/java/com/replatecamera/ReplateCameraView.kt +133 -79
  229. package/lib/commonjs/index.js +12 -0
  230. package/lib/commonjs/index.js.map +1 -1
  231. package/lib/module/index.js +9 -0
  232. package/lib/module/index.js.map +1 -1
  233. package/package.json +6 -1
  234. package/src/index.tsx +25 -1
  235. package/lib/typescript/src/index.d.ts +0 -28
  236. package/lib/typescript/src/index.d.ts.map +0 -1
@@ -0,0 +1,76 @@
1
+ apply plugin: "com.android.application"
2
+ apply plugin: "org.jetbrains.kotlin.android"
3
+ apply plugin: "com.facebook.react"
4
+
5
+ def projectRoot = rootDir.getAbsoluteFile().getParentFile().getAbsolutePath()
6
+
7
+ react {
8
+ def reactNativePackageDir = new File(["node", "--print", "require.resolve('react-native/package.json')"].execute(null, rootDir).text.trim()).getParentFile()
9
+ entryFile = file("../../index.js")
10
+ reactNativeDir = reactNativePackageDir
11
+ hermesCommand = new File(reactNativePackageDir, "sdks/hermesc/%OS-BIN%/hermesc").getAbsolutePath()
12
+ codegenDir = new File(["node", "--print", "require.resolve('@react-native/codegen/package.json', { paths: [require.resolve('react-native/package.json')] })"].execute(null, rootDir).text.trim()).getParentFile().getAbsoluteFile()
13
+ }
14
+
15
+ def enableMinifyInReleaseBuilds = (findProperty('android.enableMinifyInReleaseBuilds') ?: false).toBoolean()
16
+ def jscFlavor = 'io.github.react-native-community:jsc-android:2026004.+'
17
+
18
+ android {
19
+ ndkVersion rootProject.ext.ndkVersion
20
+ buildToolsVersion rootProject.ext.buildToolsVersion
21
+ compileSdk rootProject.ext.compileSdkVersion
22
+
23
+ namespace 'com.lucarinaldii.replatecamera'
24
+ defaultConfig {
25
+ applicationId 'com.lucarinaldii.replatecamera'
26
+ minSdkVersion rootProject.ext.minSdkVersion
27
+ targetSdkVersion rootProject.ext.targetSdkVersion
28
+ versionCode 1
29
+ versionName "0.18.2"
30
+ buildConfigField "String", "REACT_NATIVE_RELEASE_LEVEL", "\"${findProperty('reactNativeReleaseLevel') ?: 'stable'}\""
31
+ }
32
+ signingConfigs {
33
+ debug {
34
+ storeFile file('debug.keystore')
35
+ storePassword 'android'
36
+ keyAlias 'androiddebugkey'
37
+ keyPassword 'android'
38
+ }
39
+ }
40
+ buildTypes {
41
+ debug {
42
+ signingConfig signingConfigs.debug
43
+ }
44
+ release {
45
+ signingConfig signingConfigs.debug
46
+ minifyEnabled enableMinifyInReleaseBuilds
47
+ proguardFiles getDefaultProguardFile("proguard-android.txt"), "proguard-rules.pro"
48
+ }
49
+ }
50
+ compileOptions {
51
+ sourceCompatibility JavaVersion.VERSION_17
52
+ targetCompatibility JavaVersion.VERSION_17
53
+ }
54
+ kotlinOptions {
55
+ jvmTarget = "17"
56
+ }
57
+ }
58
+
59
+ dependencies {
60
+ implementation("com.facebook.react:react-android")
61
+ implementation("com.google.ar:core:1.31.0")
62
+ implementation("com.gorisse.thomas.sceneform:sceneform:1.23.0")
63
+ implementation("com.gorisse.thomas.sceneform:ux:1.23.0")
64
+ implementation("androidx.exifinterface:exifinterface:1.3.7")
65
+ implementation("androidx.lifecycle:lifecycle-process:2.8.5")
66
+ implementation("com.google.android.material:material:1.12.0")
67
+
68
+ if (hermesEnabled.toBoolean()) {
69
+ implementation("com.facebook.react:hermes-android")
70
+ } else {
71
+ implementation jscFlavor
72
+ }
73
+ }
74
+
75
+ apply from: file("../../node_modules/@react-native-community/cli-platform-android/native_modules.gradle")
76
+ applyNativeModulesAppBuildGradle(project)
@@ -0,0 +1,4 @@
1
+ <manifest xmlns:android="http://schemas.android.com/apk/res/android"
2
+ xmlns:tools="http://schemas.android.com/tools">
3
+ <uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW"/>
4
+ </manifest>
@@ -0,0 +1,30 @@
1
+ <manifest xmlns:android="http://schemas.android.com/apk/res/android">
2
+
3
+ <uses-permission android:name="android.permission.INTERNET" />
4
+ <uses-permission android:name="android.permission.CAMERA" />
5
+ <uses-permission android:name="android.permission.VIBRATE" />
6
+ <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
7
+
8
+ <uses-feature android:name="android.hardware.camera.ar" android:required="true" />
9
+
10
+ <application
11
+ android:name=".MainApplication"
12
+ android:label="@string/app_name"
13
+ android:icon="@mipmap/ic_launcher"
14
+ android:roundIcon="@mipmap/ic_launcher_round"
15
+ android:allowBackup="false"
16
+ android:theme="@style/AppTheme">
17
+ <activity
18
+ android:name=".MainActivity"
19
+ android:label="@string/app_name"
20
+ android:configChanges="keyboard|keyboardHidden|orientation|screenLayout|screenSize|smallestScreenSize|uiMode"
21
+ android:launchMode="singleTask"
22
+ android:windowSoftInputMode="adjustResize"
23
+ android:exported="true">
24
+ <intent-filter>
25
+ <action android:name="android.intent.action.MAIN" />
26
+ <category android:name="android.intent.category.LAUNCHER" />
27
+ </intent-filter>
28
+ </activity>
29
+ </application>
30
+ </manifest>
@@ -0,0 +1,13 @@
1
+ package com.lucarinaldii.replatecamera
2
+
3
+ import com.facebook.react.ReactActivity
4
+ import com.facebook.react.ReactActivityDelegate
5
+ import com.facebook.react.defaults.DefaultNewArchitectureEntryPoint.fabricEnabled
6
+ import com.facebook.react.defaults.DefaultReactActivityDelegate
7
+
8
+ class MainActivity : ReactActivity() {
9
+ override fun getMainComponentName(): String = "ReplateCameraApp"
10
+
11
+ override fun createReactActivityDelegate(): ReactActivityDelegate =
12
+ DefaultReactActivityDelegate(this, mainComponentName, fabricEnabled)
13
+ }
@@ -0,0 +1,50 @@
1
+ package com.lucarinaldii.replatecamera
2
+
3
+ import android.app.Application
4
+ import android.content.res.Configuration
5
+ import android.util.Log
6
+
7
+ import com.facebook.react.PackageList
8
+ import com.facebook.react.ReactApplication
9
+ import com.facebook.react.ReactPackage
10
+ import com.facebook.react.ReactHost
11
+ import com.facebook.react.ReactNativeHost
12
+ import com.facebook.react.defaults.DefaultNewArchitectureEntryPoint
13
+ import com.facebook.react.defaults.DefaultReactHost
14
+ import com.facebook.react.defaults.DefaultReactNativeHost
15
+ import com.facebook.soloader.SoLoader
16
+ import com.replatecamera.ReplateCameraPackage
17
+
18
+ class MainApplication : Application(), ReactApplication {
19
+
20
+ companion object {
21
+ private const val TAG = "ReplateMainApplication"
22
+ }
23
+
24
+ override val reactNativeHost: ReactNativeHost =
25
+ object : DefaultReactNativeHost(this) {
26
+ override fun getPackages(): List<ReactPackage> =
27
+ PackageList(this).packages.apply {
28
+ add(ReplateCameraPackage())
29
+ }
30
+
31
+ override fun getJSMainModuleName(): String = "index"
32
+
33
+ override fun getUseDeveloperSupport(): Boolean = BuildConfig.DEBUG
34
+
35
+ override val isNewArchEnabled: Boolean = BuildConfig.IS_NEW_ARCHITECTURE_ENABLED
36
+ override val isHermesEnabled: Boolean = BuildConfig.IS_HERMES_ENABLED
37
+ }
38
+
39
+ override val reactHost: ReactHost
40
+ get() = DefaultReactHost.getDefaultReactHost(this.applicationContext, reactNativeHost)
41
+
42
+ override fun onCreate() {
43
+ super.onCreate()
44
+ Log.i(TAG, "onCreate newArch=${BuildConfig.IS_NEW_ARCHITECTURE_ENABLED} hermes=${BuildConfig.IS_HERMES_ENABLED}")
45
+ SoLoader.init(this, false)
46
+ if (BuildConfig.IS_NEW_ARCHITECTURE_ENABLED) {
47
+ DefaultNewArchitectureEntryPoint.load()
48
+ }
49
+ }
50
+ }
@@ -0,0 +1,131 @@
1
+ package com.replatecamera
2
+
3
+ import android.content.Context
4
+ import com.google.ar.core.Frame
5
+ import com.google.ar.core.HitResult
6
+ import com.google.ar.core.Plane
7
+ import com.google.ar.core.TrackingState
8
+ import com.google.ar.sceneform.ArSceneView
9
+ import com.google.ar.sceneform.Node
10
+ import com.google.ar.sceneform.math.Quaternion
11
+ import com.google.ar.sceneform.math.Vector3
12
+ import com.google.ar.sceneform.rendering.Color
13
+ import com.google.ar.sceneform.rendering.Material
14
+ import com.google.ar.sceneform.rendering.MaterialFactory
15
+ import com.google.ar.sceneform.rendering.ShapeFactory
16
+ import kotlin.math.sqrt
17
+
18
+ /**
19
+ * A white unfilled square that sits flat on detected horizontal planes,
20
+ * centered on the hit point from screen centre.
21
+ * Hidden entirely when no plane is found (no "searching" animation).
22
+ */
23
+ class FocusNode(private val context: Context) : Node() {
24
+
25
+ companion object {
26
+ // Half-size of the square in metres (actual size is scaled by distance)
27
+ private const val HALF = 0.12f
28
+ // Thickness of each side bar
29
+ private const val BAR_THICKNESS = 0.004f
30
+ // Vertical height of the bar (flat on the plane)
31
+ private const val BAR_HEIGHT = 0.002f
32
+ }
33
+
34
+ private val sideNodes = mutableListOf<Node>()
35
+
36
+ init {
37
+ buildSquare()
38
+ isEnabled = false
39
+ }
40
+
41
+ private fun buildSquare() {
42
+ loadUnlitMaterial { material ->
43
+ // Top and Bottom bars — extend along X
44
+ for (z in listOf(-HALF, HALF)) {
45
+ val node = Node()
46
+ node.renderable = ShapeFactory.makeCube(
47
+ Vector3(HALF * 2, BAR_HEIGHT, BAR_THICKNESS),
48
+ Vector3.zero(),
49
+ material.makeCopy()
50
+ )
51
+ node.localPosition = Vector3(0f, 0f, z)
52
+ addChild(node)
53
+ sideNodes.add(node)
54
+ }
55
+ // Left and Right bars — extend along Z
56
+ for (x in listOf(-HALF, HALF)) {
57
+ val node = Node()
58
+ node.renderable = ShapeFactory.makeCube(
59
+ Vector3(BAR_THICKNESS, BAR_HEIGHT, HALF * 2),
60
+ Vector3.zero(),
61
+ material.makeCopy()
62
+ )
63
+ node.localPosition = Vector3(x, 0f, 0f)
64
+ addChild(node)
65
+ sideNodes.add(node)
66
+ }
67
+ }
68
+ }
69
+
70
+ private fun loadUnlitMaterial(onReady: (Material) -> Unit) {
71
+ try {
72
+ val bytes = context.assets.open("unlit_color.filamat").use { it.readBytes() }
73
+ val buffer = java.nio.ByteBuffer.wrap(bytes)
74
+ Material.builder()
75
+ .setSource(buffer)
76
+ .build()
77
+ .thenAccept { material ->
78
+ material.setFloat4("baseColor", 1f, 1f, 1f, 1f)
79
+ try { material.setFloat(MaterialFactory.MATERIAL_METALLIC, 0f) } catch (_: Exception) {}
80
+ try { material.setFloat(MaterialFactory.MATERIAL_ROUGHNESS, 1f) } catch (_: Exception) {}
81
+ try { material.setFloat(MaterialFactory.MATERIAL_REFLECTANCE, 0f) } catch (_: Exception) {}
82
+ onReady(material)
83
+ }
84
+ .exceptionally {
85
+ MaterialFactory.makeOpaqueWithColor(context, Color(1f, 1f, 1f, 1f))
86
+ .thenAccept(onReady)
87
+ null
88
+ }
89
+ } catch (e: Exception) {
90
+ MaterialFactory.makeOpaqueWithColor(context, Color(1f, 1f, 1f, 1f))
91
+ .thenAccept(onReady)
92
+ }
93
+ }
94
+
95
+ fun updateFromFrame(frame: Frame, sceneView: ArSceneView) {
96
+ val hit = getCenterHitResult(frame, sceneView)
97
+ if (hit != null) {
98
+ isEnabled = true
99
+ worldPosition = Vector3(hit.hitPose.tx(), hit.hitPose.ty(), hit.hitPose.tz())
100
+ worldRotation = Quaternion(
101
+ hit.hitPose.qx(),
102
+ hit.hitPose.qy(),
103
+ hit.hitPose.qz(),
104
+ hit.hitPose.qw()
105
+ )
106
+ // Scale square with distance so it stays visually consistent
107
+ val pose = frame.camera.pose
108
+ val dx = pose.tx() - hit.hitPose.tx()
109
+ val dy = pose.ty() - hit.hitPose.ty()
110
+ val dz = pose.tz() - hit.hitPose.tz()
111
+ val distance = sqrt(dx * dx + dy * dy + dz * dz)
112
+ val scale = (distance * 0.55f).coerceIn(0.4f, 1.6f)
113
+ localScale = Vector3.one().scaled(scale)
114
+ } else {
115
+ isEnabled = false
116
+ }
117
+ }
118
+
119
+ private fun getCenterHitResult(frame: Frame, sceneView: ArSceneView): HitResult? {
120
+ if (sceneView.width <= 0 || sceneView.height <= 0) return null
121
+ val cx = sceneView.width / 2f
122
+ val cy = sceneView.height / 2f
123
+ return frame.hitTest(cx, cy).firstOrNull { hit ->
124
+ val trackable = hit.trackable
125
+ trackable is Plane &&
126
+ trackable.trackingState == TrackingState.TRACKING &&
127
+ trackable.isPoseInPolygon(hit.hitPose) &&
128
+ trackable.type == Plane.Type.HORIZONTAL_UPWARD_FACING
129
+ }
130
+ }
131
+ }
@@ -0,0 +1,361 @@
1
+ package com.replatecamera
2
+
3
+ import android.content.ContentValues
4
+ import android.content.Context
5
+ import android.graphics.ImageFormat
6
+ import android.hardware.camera2.CameraAccessException
7
+ import android.hardware.camera2.CameraCaptureSession
8
+ import android.hardware.camera2.CameraCharacteristics
9
+ import android.hardware.camera2.CameraDevice
10
+ import android.hardware.camera2.CameraManager
11
+ import android.hardware.camera2.CaptureFailure
12
+ import android.hardware.camera2.CaptureRequest
13
+ import android.media.ImageReader
14
+ import android.os.Build
15
+ import android.os.Environment
16
+ import android.os.Handler
17
+ import android.os.HandlerThread
18
+ import android.os.Looper
19
+ import android.provider.MediaStore
20
+ import android.util.Log
21
+ import java.io.File
22
+ import java.io.FileOutputStream
23
+ import java.util.concurrent.Semaphore
24
+ import java.util.concurrent.TimeUnit
25
+
26
+ /**
27
+ * Captures a high-quality JPEG from the raw camera sensor via Camera2
28
+ * TEMPLATE_STILL_CAPTURE, completely independent of ARCore rendering.
29
+ *
30
+ * The resulting JPEG contains ONLY the native sensor image — no AR overlays,
31
+ * no 3D nodes, no anchor, no spheres.
32
+ *
33
+ * Usage:
34
+ * 1. call start() once (e.g. in initializeSceneView)
35
+ * 2. call capture() each time a still is needed
36
+ * 3. call stop() on destroy
37
+ */
38
+ class HighQualityPhotoCapture(private val context: Context) {
39
+
40
+ companion object {
41
+ private const val TAG = "HighQualityCapture"
42
+
43
+ /**
44
+ * When true, every saved JPEG is also inserted into the device gallery
45
+ * via MediaStore so it is visible in the Photos app.
46
+ * Flip to false for production builds.
47
+ */
48
+ var debugSaveToGallery: Boolean = false
49
+ }
50
+
51
+ private var backgroundThread: HandlerThread? = null
52
+ private var backgroundHandler: Handler? = null
53
+
54
+ fun start() {
55
+ backgroundThread = HandlerThread("HQCaptureThread").also { it.start() }
56
+ backgroundHandler = Handler(backgroundThread!!.looper)
57
+ Log.i(TAG, "HighQualityPhotoCapture started")
58
+ }
59
+
60
+ fun stop() {
61
+ backgroundThread?.quitSafely()
62
+ try { backgroundThread?.join() } catch (_: InterruptedException) { }
63
+ backgroundThread = null
64
+ backgroundHandler = null
65
+ Log.i(TAG, "HighQualityPhotoCapture stopped")
66
+ }
67
+
68
+ // -------------------------------------------------------------------------
69
+ // Public capture API
70
+ // -------------------------------------------------------------------------
71
+
72
+ /**
73
+ * Pause [arSession] (releases the camera to the system), take a Camera2
74
+ * JPEG still capture, then resume [arSession].
75
+ *
76
+ * [onResume] is called on the MAIN THREAD once the ARCore session has been
77
+ * resumed — the caller is responsible for restoring gorisse / ArSceneView
78
+ * state (see ReplateCameraView.captureHighQuality).
79
+ *
80
+ * [onResult] is called with the saved File (or null + exception on failure).
81
+ * It is called AFTER the ARCore session has been resumed.
82
+ */
83
+ fun capture(
84
+ arSceneView: com.google.ar.sceneform.ArSceneView,
85
+ onResume: () -> Unit,
86
+ onResult: (File?, Exception?) -> Unit
87
+ ) {
88
+ val handler = backgroundHandler
89
+ if (handler == null) {
90
+ Log.e(TAG, "capture() called but HighQualityPhotoCapture was not started")
91
+ onResult(null, IllegalStateException("HighQualityPhotoCapture not started"))
92
+ return
93
+ }
94
+
95
+ // arSceneView.pause() must run on the main thread.
96
+ // It stops the Choreographer frame callback AND pauses the ARCore session
97
+ // atomically — preventing SessionPausedException from onBeginFrame.
98
+ Handler(Looper.getMainLooper()).post {
99
+ try {
100
+ Log.i(TAG, "TRIGGER: pausing ArSceneView (Choreographer + ARCore) for Camera2 capture")
101
+ arSceneView.pause()
102
+ Log.i(TAG, "ArSceneView paused — camera released to system")
103
+ } catch (e: Exception) {
104
+ Log.e(TAG, "Failed to pause ArSceneView before Camera2 capture", e)
105
+ onResult(null, e)
106
+ return@post
107
+ }
108
+
109
+ // Give the camera driver a moment to fully release
110
+ handler.postDelayed({
111
+ takeSensorJpeg { file, error ->
112
+ // session.resume() must also run on the main thread
113
+ Handler(Looper.getMainLooper()).post {
114
+ onResume() // caller resumes gorisse / ArSceneView
115
+ onResult(file, error)
116
+ }
117
+ }
118
+ }, 150L)
119
+ }
120
+ }
121
+
122
+ // -------------------------------------------------------------------------
123
+ // Camera2 still capture
124
+ // -------------------------------------------------------------------------
125
+
126
+ private fun takeSensorJpeg(onResult: (File?, Exception?) -> Unit) {
127
+ val cameraManager = context.getSystemService(Context.CAMERA_SERVICE) as CameraManager
128
+
129
+ // Find back-facing camera
130
+ val cameraId = try {
131
+ cameraManager.cameraIdList.firstOrNull { id ->
132
+ cameraManager.getCameraCharacteristics(id)
133
+ .get(CameraCharacteristics.LENS_FACING) == CameraCharacteristics.LENS_FACING_BACK
134
+ }
135
+ } catch (e: CameraAccessException) {
136
+ Log.e(TAG, "Cannot enumerate cameras", e)
137
+ onResult(null, e)
138
+ return
139
+ } ?: run {
140
+ val e = IllegalStateException("No back-facing camera found")
141
+ Log.e(TAG, e.message!!)
142
+ onResult(null, e)
143
+ return
144
+ }
145
+
146
+ val characteristics = cameraManager.getCameraCharacteristics(cameraId)
147
+ val sensorOrientation = characteristics.get(CameraCharacteristics.SENSOR_ORIENTATION) ?: 90
148
+ val streamMap = characteristics.get(CameraCharacteristics.SCALER_STREAM_CONFIGURATION_MAP)!!
149
+ val maxJpegSize = streamMap.getOutputSizes(ImageFormat.JPEG)
150
+ .maxByOrNull { it.width * it.height }
151
+ ?: run {
152
+ onResult(null, IllegalStateException("No JPEG output sizes available"))
153
+ return
154
+ }
155
+
156
+ Log.i(TAG, "Camera2 still: cameraId=$cameraId size=${maxJpegSize.width}x${maxJpegSize.height} sensorOrientation=$sensorOrientation")
157
+
158
+ val imageReader = ImageReader.newInstance(
159
+ maxJpegSize.width, maxJpegSize.height,
160
+ ImageFormat.JPEG, 2
161
+ )
162
+
163
+ val openSemaphore = Semaphore(0)
164
+ var cameraDevice: CameraDevice? = null
165
+ var openError: Exception? = null
166
+
167
+ val stateCallback = object : CameraDevice.StateCallback() {
168
+ override fun onOpened(device: CameraDevice) {
169
+ Log.i(TAG, "CameraDevice opened — starting TEMPLATE_STILL_CAPTURE session")
170
+ cameraDevice = device
171
+ openSemaphore.release()
172
+ }
173
+ override fun onDisconnected(device: CameraDevice) {
174
+ Log.w(TAG, "CameraDevice disconnected before capture")
175
+ device.close()
176
+ openError = IllegalStateException("Camera disconnected")
177
+ openSemaphore.release()
178
+ }
179
+ override fun onError(device: CameraDevice, error: Int) {
180
+ Log.e(TAG, "CameraDevice error=$error")
181
+ device.close()
182
+ openError = IllegalStateException("CameraDevice error: $error")
183
+ openSemaphore.release()
184
+ }
185
+ }
186
+
187
+ try {
188
+ cameraManager.openCamera(cameraId, stateCallback, backgroundHandler)
189
+ } catch (e: Exception) {
190
+ Log.e(TAG, "openCamera failed", e)
191
+ imageReader.close()
192
+ onResult(null, e)
193
+ return
194
+ }
195
+
196
+ if (!openSemaphore.tryAcquire(4, TimeUnit.SECONDS)) {
197
+ Log.e(TAG, "Camera open timed out after 4s")
198
+ imageReader.close()
199
+ onResult(null, Exception("Camera open timed out"))
200
+ return
201
+ }
202
+
203
+ val device = cameraDevice
204
+ if (device == null || openError != null) {
205
+ imageReader.close()
206
+ onResult(null, openError ?: Exception("Camera did not open"))
207
+ return
208
+ }
209
+
210
+ // ---- Capture session -----------------------------------------------
211
+ val captureSemaphore = Semaphore(0)
212
+ var captureFile: File? = null
213
+ var captureError: Exception? = null
214
+
215
+ imageReader.setOnImageAvailableListener({ reader ->
216
+ var image: android.media.Image? = null
217
+ try {
218
+ image = reader.acquireLatestImage()
219
+ if (image == null) {
220
+ captureError = Exception("acquireLatestImage returned null")
221
+ captureSemaphore.release()
222
+ return@setOnImageAvailableListener
223
+ }
224
+ val buffer = image.planes[0].buffer
225
+ val bytes = ByteArray(buffer.remaining()).also { buffer.get(it) }
226
+ captureFile = saveJpegBytes(bytes)
227
+ Log.i(TAG, "JPEG saved — camera-only, zero AR overlays: ${captureFile?.absolutePath} (${bytes.size} bytes, ${maxJpegSize.width}x${maxJpegSize.height})")
228
+
229
+ if (debugSaveToGallery) {
230
+ saveToGallery(bytes, captureFile!!.name)
231
+ }
232
+ } catch (e: Exception) {
233
+ Log.e(TAG, "Error saving JPEG from ImageReader", e)
234
+ captureError = e
235
+ } finally {
236
+ image?.close()
237
+ captureSemaphore.release()
238
+ }
239
+ }, backgroundHandler)
240
+
241
+ val sessionCallback = object : CameraCaptureSession.StateCallback() {
242
+ override fun onConfigured(session: CameraCaptureSession) {
243
+ try {
244
+ val request = device.createCaptureRequest(CameraDevice.TEMPLATE_STILL_CAPTURE).apply {
245
+ addTarget(imageReader.surface)
246
+ set(CaptureRequest.CONTROL_AF_MODE, CaptureRequest.CONTROL_AF_MODE_CONTINUOUS_PICTURE)
247
+ set(CaptureRequest.CONTROL_AE_MODE, CaptureRequest.CONTROL_AE_MODE_ON)
248
+ set(CaptureRequest.CONTROL_AWB_MODE, CaptureRequest.CONTROL_AWB_MODE_AUTO)
249
+ // Correct JPEG orientation so the image is upright without external rotation
250
+ set(CaptureRequest.JPEG_ORIENTATION, sensorOrientation)
251
+ set(CaptureRequest.JPEG_QUALITY, 95.toByte())
252
+ }.build()
253
+
254
+ session.capture(request, object : CameraCaptureSession.CaptureCallback() {
255
+ override fun onCaptureFailed(
256
+ session: CameraCaptureSession,
257
+ request: CaptureRequest,
258
+ failure: CaptureFailure
259
+ ) {
260
+ Log.e(TAG, "TEMPLATE_STILL_CAPTURE failed reason=${failure.reason}")
261
+ captureError = Exception("Capture failed: reason=${failure.reason}")
262
+ captureSemaphore.release()
263
+ }
264
+ }, backgroundHandler)
265
+
266
+ Log.i(TAG, "TEMPLATE_STILL_CAPTURE submitted (ImageReader target only — no AR surfaces)")
267
+ } catch (e: Exception) {
268
+ Log.e(TAG, "Failed to submit capture request", e)
269
+ captureError = e
270
+ captureSemaphore.release()
271
+ }
272
+ }
273
+
274
+ override fun onConfigureFailed(session: CameraCaptureSession) {
275
+ Log.e(TAG, "CameraCaptureSession configuration failed")
276
+ captureError = Exception("CaptureSession configure failed")
277
+ captureSemaphore.release()
278
+ }
279
+ }
280
+
281
+ try {
282
+ device.createCaptureSession(listOf(imageReader.surface), sessionCallback, backgroundHandler)
283
+ } catch (e: Exception) {
284
+ Log.e(TAG, "createCaptureSession failed", e)
285
+ imageReader.close()
286
+ device.close()
287
+ onResult(null, e)
288
+ return
289
+ }
290
+
291
+ // Wait for image (max 10s)
292
+ if (!captureSemaphore.tryAcquire(10, TimeUnit.SECONDS)) {
293
+ captureError = Exception("Still capture timed out after 10s")
294
+ Log.e(TAG, captureError!!.message!!)
295
+ }
296
+
297
+ // Always close Camera2 before handing camera back to ARCore
298
+ try {
299
+ imageReader.close()
300
+ device.close()
301
+ Log.i(TAG, "Camera2 device closed — camera available for ARCore resume")
302
+ } catch (e: Exception) {
303
+ Log.w(TAG, "Error closing Camera2 resources", e)
304
+ }
305
+
306
+ onResult(captureFile, captureError)
307
+ }
308
+
309
+ // -------------------------------------------------------------------------
310
+ // Storage helpers
311
+ // -------------------------------------------------------------------------
312
+
313
+ private fun saveJpegBytes(bytes: ByteArray): File {
314
+ val dir = File(context.getExternalFilesDir(null), "photos")
315
+ if (!dir.exists()) dir.mkdirs()
316
+ val file = File(dir, "replate_${System.currentTimeMillis()}.jpg")
317
+ FileOutputStream(file).use { it.write(bytes) }
318
+ return file
319
+ }
320
+
321
+ /**
322
+ * DEBUG: copies the JPEG bytes into the device gallery (MediaStore).
323
+ * The file will be visible in the Photos / Gallery app.
324
+ * Only called when [debugSaveToGallery] == true.
325
+ */
326
+ private fun saveToGallery(bytes: ByteArray, displayName: String) {
327
+ try {
328
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
329
+ val values = ContentValues().apply {
330
+ put(MediaStore.Images.Media.DISPLAY_NAME, displayName)
331
+ put(MediaStore.Images.Media.MIME_TYPE, "image/jpeg")
332
+ put(MediaStore.Images.Media.RELATIVE_PATH, "${Environment.DIRECTORY_PICTURES}/Replate")
333
+ put(MediaStore.Images.Media.IS_PENDING, 1)
334
+ }
335
+ val resolver = context.contentResolver
336
+ val uri = resolver.insert(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, values)
337
+ if (uri != null) {
338
+ resolver.openOutputStream(uri)?.use { it.write(bytes) }
339
+ values.clear()
340
+ values.put(MediaStore.Images.Media.IS_PENDING, 0)
341
+ resolver.update(uri, values, null, null)
342
+ Log.i(TAG, "DEBUG: JPEG saved to gallery via MediaStore uri=$uri")
343
+ }
344
+ } else {
345
+ @Suppress("DEPRECATION")
346
+ val dir = File(
347
+ Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES),
348
+ "Replate"
349
+ )
350
+ dir.mkdirs()
351
+ val file = File(dir, displayName)
352
+ FileOutputStream(file).use { it.write(bytes) }
353
+ // Notify media scanner
354
+ android.media.MediaScannerConnection.scanFile(context, arrayOf(file.absolutePath), null, null)
355
+ Log.i(TAG, "DEBUG: JPEG saved to gallery (legacy) path=${file.absolutePath}")
356
+ }
357
+ } catch (e: Exception) {
358
+ Log.e(TAG, "DEBUG: Failed to save JPEG to gallery", e)
359
+ }
360
+ }
361
+ }