react-native-nitro-compass 0.1.0

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 (105) hide show
  1. package/LICENSE +21 -0
  2. package/NitroCompass.podspec +31 -0
  3. package/README.md +206 -0
  4. package/android/CMakeLists.txt +32 -0
  5. package/android/build.gradle +148 -0
  6. package/android/fix-prefab.gradle +51 -0
  7. package/android/gradle.properties +5 -0
  8. package/android/src/main/AndroidManifest.xml +2 -0
  9. package/android/src/main/cpp/cpp-adapter.cpp +9 -0
  10. package/android/src/main/java/com/margelo/nitro/nitrocompass/HybridNitroCompass.kt +481 -0
  11. package/android/src/main/java/com/margelo/nitro/nitrocompass/NitroCompassPackage.kt +18 -0
  12. package/app.plugin.js +16 -0
  13. package/ios/Bridge.h +8 -0
  14. package/ios/HybridNitroCompass.swift +473 -0
  15. package/lib/commonjs/hook.js +69 -0
  16. package/lib/commonjs/hook.js.map +1 -0
  17. package/lib/commonjs/index.js +39 -0
  18. package/lib/commonjs/index.js.map +1 -0
  19. package/lib/commonjs/multiplex.js +109 -0
  20. package/lib/commonjs/multiplex.js.map +1 -0
  21. package/lib/commonjs/native.js +9 -0
  22. package/lib/commonjs/native.js.map +1 -0
  23. package/lib/commonjs/package.json +1 -0
  24. package/lib/commonjs/specs/NitroCompass.nitro.js +6 -0
  25. package/lib/commonjs/specs/NitroCompass.nitro.js.map +1 -0
  26. package/lib/module/hook.js +65 -0
  27. package/lib/module/hook.js.map +1 -0
  28. package/lib/module/index.js +6 -0
  29. package/lib/module/index.js.map +1 -0
  30. package/lib/module/multiplex.js +103 -0
  31. package/lib/module/multiplex.js.map +1 -0
  32. package/lib/module/native.js +5 -0
  33. package/lib/module/native.js.map +1 -0
  34. package/lib/module/specs/NitroCompass.nitro.js +4 -0
  35. package/lib/module/specs/NitroCompass.nitro.js.map +1 -0
  36. package/lib/typescript/src/hook.d.ts +49 -0
  37. package/lib/typescript/src/hook.d.ts.map +1 -0
  38. package/lib/typescript/src/index.d.ts +8 -0
  39. package/lib/typescript/src/index.d.ts.map +1 -0
  40. package/lib/typescript/src/multiplex.d.ts +38 -0
  41. package/lib/typescript/src/multiplex.d.ts.map +1 -0
  42. package/lib/typescript/src/native.d.ts +3 -0
  43. package/lib/typescript/src/native.d.ts.map +1 -0
  44. package/lib/typescript/src/specs/NitroCompass.nitro.d.ts +176 -0
  45. package/lib/typescript/src/specs/NitroCompass.nitro.d.ts.map +1 -0
  46. package/nitro.json +30 -0
  47. package/nitrogen/generated/.gitattributes +1 -0
  48. package/nitrogen/generated/android/NitroCompass+autolinking.cmake +81 -0
  49. package/nitrogen/generated/android/NitroCompass+autolinking.gradle +27 -0
  50. package/nitrogen/generated/android/NitroCompassOnLoad.cpp +60 -0
  51. package/nitrogen/generated/android/NitroCompassOnLoad.hpp +34 -0
  52. package/nitrogen/generated/android/c++/JAccuracyQuality.hpp +64 -0
  53. package/nitrogen/generated/android/c++/JCompassSample.hpp +61 -0
  54. package/nitrogen/generated/android/c++/JFunc_void_AccuracyQuality.hpp +77 -0
  55. package/nitrogen/generated/android/c++/JFunc_void_CompassSample.hpp +77 -0
  56. package/nitrogen/generated/android/c++/JFunc_void_bool.hpp +75 -0
  57. package/nitrogen/generated/android/c++/JHybridNitroCompassSpec.cpp +143 -0
  58. package/nitrogen/generated/android/c++/JHybridNitroCompassSpec.hpp +75 -0
  59. package/nitrogen/generated/android/c++/JPermissionStatus.hpp +61 -0
  60. package/nitrogen/generated/android/c++/JSensorDiagnostics.hpp +58 -0
  61. package/nitrogen/generated/android/c++/JSensorKind.hpp +61 -0
  62. package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitrocompass/AccuracyQuality.kt +25 -0
  63. package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitrocompass/CompassSample.kt +56 -0
  64. package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitrocompass/Func_void_AccuracyQuality.kt +80 -0
  65. package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitrocompass/Func_void_CompassSample.kt +80 -0
  66. package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitrocompass/Func_void_bool.kt +80 -0
  67. package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitrocompass/HybridNitroCompassSpec.kt +118 -0
  68. package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitrocompass/NitroCompassOnLoad.kt +35 -0
  69. package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitrocompass/PermissionStatus.kt +24 -0
  70. package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitrocompass/SensorDiagnostics.kt +51 -0
  71. package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitrocompass/SensorKind.kt +24 -0
  72. package/nitrogen/generated/ios/NitroCompass+autolinking.rb +62 -0
  73. package/nitrogen/generated/ios/NitroCompass-Swift-Cxx-Bridge.cpp +73 -0
  74. package/nitrogen/generated/ios/NitroCompass-Swift-Cxx-Bridge.hpp +267 -0
  75. package/nitrogen/generated/ios/NitroCompass-Swift-Cxx-Umbrella.hpp +61 -0
  76. package/nitrogen/generated/ios/NitroCompassAutolinking.mm +33 -0
  77. package/nitrogen/generated/ios/NitroCompassAutolinking.swift +26 -0
  78. package/nitrogen/generated/ios/c++/HybridNitroCompassSpecSwift.cpp +11 -0
  79. package/nitrogen/generated/ios/c++/HybridNitroCompassSpecSwift.hpp +180 -0
  80. package/nitrogen/generated/ios/swift/AccuracyQuality.swift +48 -0
  81. package/nitrogen/generated/ios/swift/CompassSample.swift +34 -0
  82. package/nitrogen/generated/ios/swift/Func_void_AccuracyQuality.swift +46 -0
  83. package/nitrogen/generated/ios/swift/Func_void_CompassSample.swift +46 -0
  84. package/nitrogen/generated/ios/swift/Func_void_PermissionStatus.swift +46 -0
  85. package/nitrogen/generated/ios/swift/Func_void_bool.swift +46 -0
  86. package/nitrogen/generated/ios/swift/Func_void_std__exception_ptr.swift +46 -0
  87. package/nitrogen/generated/ios/swift/HybridNitroCompassSpec.swift +67 -0
  88. package/nitrogen/generated/ios/swift/HybridNitroCompassSpec_cxx.swift +309 -0
  89. package/nitrogen/generated/ios/swift/PermissionStatus.swift +44 -0
  90. package/nitrogen/generated/ios/swift/SensorDiagnostics.swift +29 -0
  91. package/nitrogen/generated/ios/swift/SensorKind.swift +44 -0
  92. package/nitrogen/generated/shared/c++/AccuracyQuality.hpp +84 -0
  93. package/nitrogen/generated/shared/c++/CompassSample.hpp +87 -0
  94. package/nitrogen/generated/shared/c++/HybridNitroCompassSpec.cpp +33 -0
  95. package/nitrogen/generated/shared/c++/HybridNitroCompassSpec.hpp +87 -0
  96. package/nitrogen/generated/shared/c++/PermissionStatus.hpp +80 -0
  97. package/nitrogen/generated/shared/c++/SensorDiagnostics.hpp +84 -0
  98. package/nitrogen/generated/shared/c++/SensorKind.hpp +80 -0
  99. package/package.json +136 -0
  100. package/react-native.config.js +11 -0
  101. package/src/hook.ts +118 -0
  102. package/src/index.ts +28 -0
  103. package/src/multiplex.ts +117 -0
  104. package/src/native.ts +5 -0
  105. package/src/specs/NitroCompass.nitro.ts +193 -0
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Omar Sukarieh
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,31 @@
1
+ require "json"
2
+
3
+ package = JSON.parse(File.read(File.join(__dir__, "package.json")))
4
+
5
+ Pod::Spec.new do |s|
6
+ s.name = "NitroCompass"
7
+ s.version = package["version"]
8
+ s.summary = package["description"]
9
+ s.homepage = package["homepage"]
10
+ s.license = package["license"]
11
+ s.authors = package["author"]
12
+
13
+ s.platforms = { :ios => min_ios_version_supported, :visionos => 1.0 }
14
+ s.source = { :git => "https://github.com/omarsdev/react-native-nitro-compass.git", :tag => "#{s.version}" }
15
+
16
+ s.source_files = [
17
+ # Implementation (Swift)
18
+ "ios/**/*.{swift}",
19
+ # Autolinking/Registration (Objective-C++)
20
+ "ios/**/*.{m,mm}",
21
+ # Implementation (C++ objects)
22
+ "cpp/**/*.{hpp,cpp}",
23
+ ]
24
+
25
+ load 'nitrogen/generated/ios/NitroCompass+autolinking.rb'
26
+ add_nitrogen_files(s)
27
+
28
+ s.dependency 'React-jsi'
29
+ s.dependency 'React-callinvoker'
30
+ install_modules_dependencies(s)
31
+ end
package/README.md ADDED
@@ -0,0 +1,206 @@
1
+ # react-native-nitro-compass
2
+
3
+ Fast, accurate compass heading for React Native, powered by [Nitro Modules](https://github.com/mrousavy/nitro).
4
+
5
+ - **Android**: `Sensor.TYPE_ROTATION_VECTOR` (gyro + accel + magnetometer sensor fusion), with `TYPE_GEOMAGNETIC_ROTATION_VECTOR` fallback for gyroless devices. Sensor delivery on a dedicated `HandlerThread` — never blocks the UI thread. Heading accuracy taken from `event.values[4]` of the rotation vector.
6
+ - **iOS**: `CLLocationManager` heading via `CLHeading.magneticHeading`. Apple's stack already handles sensor fusion natively.
7
+ - **JS API**: type-safe Nitro callbacks — no `NativeEventEmitter`, no string event names.
8
+
9
+ ## Why
10
+
11
+ Most React Native compass libraries use the legacy `accelerometer + magnetometer + getRotationMatrix` Android approach, which is laggy, noisy, and requires a figure-8 calibration on every session. This library uses Android's modern fused rotation-vector sensor (recommended by Google since 2013), giving you stable headings without calibration on virtually any modern device.
12
+
13
+ ## Requirements
14
+
15
+ - React Native 0.76.0 or higher
16
+ - Node 18.0.0 or higher
17
+ - `react-native-nitro-modules` peer dependency
18
+
19
+ ## Install
20
+
21
+ ```sh
22
+ npm install react-native-nitro-compass react-native-nitro-modules
23
+ ```
24
+
25
+ iOS:
26
+
27
+ ```sh
28
+ cd ios && pod install
29
+ ```
30
+
31
+ ## Usage
32
+
33
+ ```ts
34
+ import { NitroCompass } from 'react-native-nitro-compass'
35
+
36
+ if (NitroCompass.hasCompass()) {
37
+ NitroCompass.start(1, ({ heading, accuracy }) => {
38
+ console.log(`heading: ${heading.toFixed(1)}°, accuracy: ±${accuracy}°`)
39
+ })
40
+ }
41
+
42
+ // later…
43
+ NitroCompass.stop()
44
+ ```
45
+
46
+ ### API
47
+
48
+ ```ts
49
+ NitroCompass.start(filterDegrees: number, onHeading: (sample: CompassSample) => void): void
50
+ NitroCompass.stop(): void
51
+ NitroCompass.isStarted(): boolean
52
+ NitroCompass.hasCompass(): boolean
53
+
54
+ NitroCompass.setFilter(degrees: number): void
55
+ NitroCompass.getCurrentHeading(): CompassSample | undefined
56
+ NitroCompass.getDiagnostics(): SensorDiagnostics | undefined
57
+ NitroCompass.setDeclination(degrees: number): void
58
+ NitroCompass.setOnCalibrationNeeded(onChange: (quality: AccuracyQuality) => void): void
59
+ NitroCompass.setOnInterferenceDetected(onChange: (interferenceDetected: boolean) => void): void
60
+ NitroCompass.setPauseOnBackground(enabled: boolean): void
61
+
62
+ interface CompassSample {
63
+ heading: number // degrees, [0, 360); magnetic by default, true-north if setDeclination was called
64
+ accuracy: number // degrees, smaller is better; -1 if unknown
65
+ }
66
+
67
+ type AccuracyQuality = 'high' | 'medium' | 'low' | 'unreliable'
68
+ type SensorKind = 'rotationVector' | 'geomagneticRotationVector' | 'coreLocation'
69
+ interface SensorDiagnostics { sensor: SensorKind }
70
+ ```
71
+
72
+ - `filterDegrees` — minimum change between successive samples before the next one is delivered. Pass `0` for "every event"; typical UI values are `1`–`3`. Use `setFilter()` to change live without tearing down the subscription.
73
+ - `start()` is idempotent in the destructive sense — calling it while already started silently replaces the previous subscription with the new callback. `stop()` is idempotent and safe from inside the `onHeading` callback.
74
+ - `getDiagnostics()` reports which sensor would produce headings on this device — useful for explaining quality differences (e.g. a phone falling back to `geomagneticRotationVector` will be more susceptible to magnetic interference than one using `rotationVector`). Safe to call before `start()`.
75
+ - `accuracy` is a numeric uncertainty (degrees). On iOS it comes from `CLHeading.headingAccuracy` directly. On Android it comes from `event.values[4]` of the rotation-vector sensor; if the sensor stack does not publish that (rare), the module falls back to a coarse degree estimate from `SensorManager.SENSOR_STATUS_*` (`HIGH→5°`, `MEDIUM→15°`, `LOW→30°`).
76
+ - `getCurrentHeading()` returns the most recently emitted sample (with declination already applied), or `undefined` if not started yet or no sample has arrived.
77
+
78
+ ### Calibration
79
+
80
+ `setOnCalibrationNeeded(cb)` registers a callback fired whenever the calibration bucket transitions. Buckets are derived from numeric accuracy on both platforms using the same thresholds, so values agree across iOS and Android: `<5°` → `'high'`, `<15°` → `'medium'`, `<30°` → `'low'`, otherwise `'unreliable'`. On iOS, the system's "wave the device in a figure-8" prompt is suppressed and reported to your callback as `'unreliable'` — show your own UI when you receive that bucket.
81
+
82
+ ```ts
83
+ NitroCompass.setOnCalibrationNeeded((q) => {
84
+ if (q === 'unreliable') showCalibrationToast()
85
+ })
86
+ ```
87
+
88
+ ### Magnetic interference
89
+
90
+ `setOnInterferenceDetected(cb)` fires `true` when the raw magnetic field magnitude leaves the normal Earth band (~20–70 µT) and `false` when it returns. Typical sources are laptops, monitors, car engines, and large steel structures — these can skew heading by tens of degrees while the calibration bucket still reads `'medium'` or better, so this is complementary to the calibration callback rather than a replacement.
91
+
92
+ ```ts
93
+ NitroCompass.setOnInterferenceDetected((interfering) => {
94
+ if (interfering) showInterferenceWarning()
95
+ else hideInterferenceWarning()
96
+ })
97
+ ```
98
+
99
+ Android uses `Sensor.TYPE_MAGNETIC_FIELD` at ~5 Hz. iOS uses `CMDeviceMotion.magneticField` (calibrated, with the device's own hard-iron bias subtracted in real time) — note that no transitions are reported on iOS until CoreMotion's bias estimate converges, typically a second or two of normal device movement. Only triggered while `start()` is active; no debounce, so brief excursions still fire.
100
+
101
+ ### Magnetic vs true north
102
+
103
+ Headings are **magnetic** by default. You can either apply declination in JS, or let the native side do it once via `setDeclination(deg)` so every emitted sample (and `getCurrentHeading()`) is true-north.
104
+
105
+ ```ts
106
+ import geomagnetism from 'geomagnetism'
107
+
108
+ const declination = geomagnetism.model().point([lat, lon]).decl
109
+
110
+ // Option A — JS-side
111
+ const trueHeading = (heading + declination + 360) % 360
112
+
113
+ // Option B — native-side (subsequent samples are true-north)
114
+ NitroCompass.setDeclination(declination)
115
+ ```
116
+
117
+ Pass `0` to revert to magnetic. Declination survives `stop()`/`start()` cycles.
118
+
119
+ ### Background pause
120
+
121
+ By default the underlying sensor / location-manager subscription is silently paused while the app is backgrounded and resumed when it returns to the foreground; the JS callback and any declination set via `setDeclination` are preserved across the pause. To opt out (e.g. for a fitness tracker that needs heading while screen-off):
122
+
123
+ ```ts
124
+ NitroCompass.setPauseOnBackground(false)
125
+ ```
126
+
127
+ ### `useCompass()` hook
128
+
129
+ For React consumers, the bundled hook wraps the entire surface — subscription lifecycle, calibration/interference callbacks, and the live-tuneable knobs — into one ergonomic call. Multiple `useCompass()` mounts safely share the same underlying native subscription via JS-side fan-out, so two screens can both consume heading without clobbering each other.
130
+
131
+ ```tsx
132
+ import { useCompass } from 'react-native-nitro-compass'
133
+
134
+ function CompassView() {
135
+ const { reading, quality, interfering, hasCompass } = useCompass({
136
+ filterDegrees: 1,
137
+ declination: 0,
138
+ pauseOnBackground: true,
139
+ })
140
+
141
+ if (!hasCompass) return <Text>No compass on this device.</Text>
142
+ if (!reading) return <Text>Acquiring heading…</Text>
143
+
144
+ return (
145
+ <View>
146
+ <Text>{reading.heading.toFixed(0)}° (±{reading.accuracy.toFixed(0)}°)</Text>
147
+ {quality === 'unreliable' && <Text>Calibration needed</Text>}
148
+ {interfering && <Text>Magnetic interference</Text>}
149
+ </View>
150
+ )
151
+ }
152
+ ```
153
+
154
+ `filterDegrees`, `declination`, and `pauseOnBackground` are global state on `NitroCompass` — multiple hooks setting them are last-write-wins. Pass `enabled: false` to pause a hook's heading subscription without unmounting (calibration / interference observation continues).
155
+
156
+ For non-React state managers, lower-level `addHeadingListener(cb): () => void`, `addCalibrationListener(cb): () => void`, and `addInterferenceListener(cb): () => void` are also exported. They are reference-counted: the first heading listener calls `start()`, the last unsubscribe calls `stop()`. Mixing these helpers with direct `NitroCompass.start()` / `setOnCalibrationNeeded()` / `setOnInterferenceDetected()` will clobber the multiplex's internal callback slot — pick one path.
157
+
158
+ ## Permissions
159
+
160
+ - **iOS**: requires `NSLocationWhenInUseUsageDescription` in `Info.plist`. `CLLocationManager` only emits headings when location permission is granted.
161
+ - **Android**: no permission required for the rotation-vector sensor.
162
+
163
+ ## Example app
164
+
165
+ A bare React Native CLI app under [example/](./example) (RN 0.84.1, New Arch enabled) consumes the library via a local symlink. Use it to test changes on a real device — the iOS Simulator has no compass and the Android emulator's magnetometer is faked.
166
+
167
+ First-time setup:
168
+
169
+ ```sh
170
+ cd example
171
+ npm install # symlinks ../ as react-native-nitro-compass
172
+ cd ios && bundle install && bundle exec pod install && cd ..
173
+ ```
174
+
175
+ Run on a device:
176
+
177
+ ```sh
178
+ # Terminal 1 — Metro
179
+ npm start
180
+
181
+ # Terminal 2 — build & launch
182
+ npm run ios -- --device # physical iPhone
183
+ npm run android # physical device or emulator
184
+ ```
185
+
186
+ If you change the Nitrogen spec or any native source, regenerate and rebuild:
187
+
188
+ ```sh
189
+ # from the repo root
190
+ npm run codegen
191
+ # then in example/
192
+ cd ios && bundle exec pod install && cd .. # iOS only
193
+ npm run ios # or npm run android
194
+ ```
195
+
196
+ The example imports `NitroCompass` directly from the workspace `src/` (via Metro `watchFolders`), so editing TypeScript only requires a Metro reload.
197
+
198
+ ## Acknowledgments
199
+
200
+ The Android rotation-vector pattern (sensor fusion, surface-rotation remapping, `getOrientation` extraction) is adapted from the MIT-licensed [Andromeda](https://github.com/kylecorry31/andromeda) sensor library by Kyle Corry, which powers the [Trail Sense](https://github.com/kylecorry31/Trail-Sense) wilderness navigation app.
201
+
202
+ Bootstrapped with [create-nitro-module](https://github.com/patrickkabwe/create-nitro-module).
203
+
204
+ ## License
205
+
206
+ MIT — see [LICENSE](./LICENSE).
@@ -0,0 +1,32 @@
1
+ project(NitroCompass)
2
+ cmake_minimum_required(VERSION 3.9.0)
3
+
4
+ set (PACKAGE_NAME NitroCompass)
5
+ set (CMAKE_VERBOSE_MAKEFILE ON)
6
+ set (CMAKE_CXX_STANDARD 20)
7
+
8
+ # Enable Raw Props parsing in react-native (for Nitro Views)
9
+ add_compile_options(-DRN_SERIALIZABLE_STATE=1)
10
+
11
+ # Define C++ library and add all sources
12
+ add_library(${PACKAGE_NAME} SHARED
13
+ src/main/cpp/cpp-adapter.cpp
14
+ )
15
+
16
+ # Add Nitrogen specs :)
17
+ include(${CMAKE_SOURCE_DIR}/../nitrogen/generated/android/NitroCompass+autolinking.cmake)
18
+
19
+ # Set up local includes
20
+ include_directories(
21
+ "src/main/cpp"
22
+ "../cpp"
23
+ )
24
+
25
+ find_library(LOG_LIB log)
26
+
27
+ # Link all libraries together
28
+ target_link_libraries(
29
+ ${PACKAGE_NAME}
30
+ ${LOG_LIB}
31
+ android # <-- Android core
32
+ )
@@ -0,0 +1,148 @@
1
+ buildscript {
2
+ repositories {
3
+ google()
4
+ mavenCentral()
5
+ }
6
+
7
+ dependencies {
8
+ classpath "com.android.tools.build:gradle:8.8.0"
9
+ }
10
+ }
11
+
12
+ def reactNativeArchitectures() {
13
+ def value = rootProject.getProperties().get("reactNativeArchitectures")
14
+ return value ? value.split(",") : ["armeabi-v7a", "x86", "x86_64", "arm64-v8a"]
15
+ }
16
+
17
+ def isNewArchitectureEnabled() {
18
+ return rootProject.hasProperty("newArchEnabled") && rootProject.getProperty("newArchEnabled") == "true"
19
+ }
20
+
21
+ apply plugin: "com.android.library"
22
+ apply plugin: 'org.jetbrains.kotlin.android'
23
+ apply from: '../nitrogen/generated/android/NitroCompass+autolinking.gradle'
24
+ apply from: "./fix-prefab.gradle"
25
+
26
+ if (isNewArchitectureEnabled()) {
27
+ apply plugin: "com.facebook.react"
28
+ }
29
+
30
+ def getExtOrDefault(name) {
31
+ return rootProject.ext.has(name) ? rootProject.ext.get(name) : project.properties["NitroCompass_" + name]
32
+ }
33
+
34
+ def getExtOrIntegerDefault(name) {
35
+ return rootProject.ext.has(name) ? rootProject.ext.get(name) : (project.properties["NitroCompass_" + name]).toInteger()
36
+ }
37
+
38
+ android {
39
+ namespace "com.nitrocompass"
40
+
41
+ ndkVersion getExtOrDefault("ndkVersion")
42
+ compileSdkVersion getExtOrIntegerDefault("compileSdkVersion")
43
+
44
+ defaultConfig {
45
+ minSdkVersion getExtOrIntegerDefault("minSdkVersion")
46
+ targetSdkVersion getExtOrIntegerDefault("targetSdkVersion")
47
+ buildConfigField "boolean", "IS_NEW_ARCHITECTURE_ENABLED", isNewArchitectureEnabled().toString()
48
+
49
+ externalNativeBuild {
50
+ cmake {
51
+ cppFlags "-frtti -fexceptions -Wall -Wextra -fstack-protector-all"
52
+ arguments "-DANDROID_STL=c++_shared", "-DANDROID_SUPPORT_FLEXIBLE_PAGE_SIZES=ON"
53
+ abiFilters (*reactNativeArchitectures())
54
+
55
+ buildTypes {
56
+ debug {
57
+ cppFlags "-O1 -g"
58
+ }
59
+ release {
60
+ cppFlags "-O2"
61
+ }
62
+ }
63
+ }
64
+ }
65
+ }
66
+
67
+ externalNativeBuild {
68
+ cmake {
69
+ path "CMakeLists.txt"
70
+ }
71
+ }
72
+
73
+ packagingOptions {
74
+ excludes = [
75
+ "META-INF",
76
+ "META-INF/**",
77
+ "**/libc++_shared.so",
78
+ "**/libfbjni.so",
79
+ "**/libjsi.so",
80
+ "**/libfolly_json.so",
81
+ "**/libfolly_runtime.so",
82
+ "**/libglog.so",
83
+ "**/libhermes.so",
84
+ "**/libhermes-executor-debug.so",
85
+ "**/libhermes_executor.so",
86
+ "**/libreactnative.so",
87
+ "**/libreactnativejni.so",
88
+ "**/libturbomodulejsijni.so",
89
+ "**/libreact_nativemodule_core.so",
90
+ "**/libjscexecutor.so"
91
+ ]
92
+ }
93
+
94
+ buildFeatures {
95
+ buildConfig true
96
+ prefab true
97
+ }
98
+
99
+ buildTypes {
100
+ release {
101
+ minifyEnabled false
102
+ }
103
+ }
104
+
105
+ lintOptions {
106
+ disable "GradleCompatible"
107
+ }
108
+
109
+ compileOptions {
110
+ sourceCompatibility JavaVersion.VERSION_1_8
111
+ targetCompatibility JavaVersion.VERSION_1_8
112
+ }
113
+
114
+ sourceSets {
115
+ main {
116
+ if (isNewArchitectureEnabled()) {
117
+ java.srcDirs += [
118
+ // React Codegen files
119
+ "${project.buildDir}/generated/source/codegen/java"
120
+ ]
121
+ }
122
+ }
123
+ }
124
+ }
125
+
126
+ repositories {
127
+ mavenCentral()
128
+ google()
129
+ }
130
+
131
+
132
+ dependencies {
133
+ // For < 0.71, this will be from the local maven repo
134
+ // For > 0.71, this will be replaced by `com.facebook.react:react-android:$version` by react gradle plugin
135
+ //noinspection GradleDynamicVersion
136
+ implementation "com.facebook.react:react-native:+"
137
+
138
+ // Add a dependency on NitroModules
139
+ implementation project(":react-native-nitro-modules")
140
+ }
141
+
142
+ if (isNewArchitectureEnabled()) {
143
+ react {
144
+ jsRootDir = file("../src/")
145
+ libraryName = "NitroCompass"
146
+ codegenJavaPackageName = "com.nitrocompass"
147
+ }
148
+ }
@@ -0,0 +1,51 @@
1
+ tasks.configureEach { task ->
2
+ // Make sure that we generate our prefab publication file only after having built the native library
3
+ // so that not a header publication file, but a full configuration publication will be generated, which
4
+ // will include the .so file
5
+
6
+ def prefabConfigurePattern = ~/^prefab(.+)ConfigurePackage$/
7
+ def matcher = task.name =~ prefabConfigurePattern
8
+ if (matcher.matches()) {
9
+ def variantName = matcher[0][1]
10
+ task.outputs.upToDateWhen { false }
11
+ task.dependsOn("externalNativeBuild${variantName}")
12
+ }
13
+ }
14
+
15
+ afterEvaluate {
16
+ def abis = reactNativeArchitectures()
17
+ rootProject.allprojects.each { proj ->
18
+ if (proj === rootProject) return
19
+
20
+ def dependsOnThisLib = proj.configurations.findAll { it.canBeResolved }.any { config ->
21
+ config.dependencies.any { dep ->
22
+ dep.group == project.group && dep.name == project.name
23
+ }
24
+ }
25
+ if (!dependsOnThisLib && proj != project) return
26
+
27
+ if (!proj.plugins.hasPlugin('com.android.application') && !proj.plugins.hasPlugin('com.android.library')) {
28
+ return
29
+ }
30
+
31
+ def variants = proj.android.hasProperty('applicationVariants') ? proj.android.applicationVariants : proj.android.libraryVariants
32
+ // Touch the prefab_config.json files to ensure that in ExternalNativeJsonGenerator.kt we will re-trigger the prefab CLI to
33
+ // generate a libnameConfig.cmake file that will contain our native library (.so).
34
+ // See this condition: https://cs.android.com/android-studio/platform/tools/base/+/mirror-goog-studio-main:build-system/gradle-core/src/main/java/com/android/build/gradle/tasks/ExternalNativeJsonGenerator.kt;l=207-219?q=createPrefabBuildSystemGlue
35
+ variants.all { variant ->
36
+ def variantName = variant.name
37
+ abis.each { abi ->
38
+ def searchDir = new File(proj.projectDir, ".cxx/${variantName}")
39
+ if (!searchDir.exists()) return
40
+ def matches = []
41
+ searchDir.eachDir { randomDir ->
42
+ def prefabFile = new File(randomDir, "${abi}/prefab_config.json")
43
+ if (prefabFile.exists()) matches << prefabFile
44
+ }
45
+ matches.each { prefabConfig ->
46
+ prefabConfig.setLastModified(System.currentTimeMillis())
47
+ }
48
+ }
49
+ }
50
+ }
51
+ }
@@ -0,0 +1,5 @@
1
+ ReactNativeNitroCompass_kotlinVersion=2.1.20
2
+ ReactNativeNitroCompass_minSdkVersion=23
3
+ ReactNativeNitroCompass_targetSdkVersion=35
4
+ ReactNativeNitroCompass_compileSdkVersion=34
5
+ ReactNativeNitroCompass_ndkVersion=27.1.12297006
@@ -0,0 +1,2 @@
1
+ <manifest xmlns:android="http://schemas.android.com/apk/res/android">
2
+ </manifest>
@@ -0,0 +1,9 @@
1
+ #include <jni.h>
2
+ #include <fbjni/fbjni.h>
3
+ #include "NitroCompassOnLoad.hpp"
4
+
5
+ JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM* vm, void*) {
6
+ return facebook::jni::initialize(vm, []() {
7
+ margelo::nitro::nitrocompass::registerAllNatives();
8
+ });
9
+ }