Skip to content

Commit 31a566d

Browse files
feat: [SDK-4768] support disabling location module (#29)
Co-authored-by: Cursor <cursoragent@cursor.com>
1 parent e999a5b commit 31a566d

5 files changed

Lines changed: 130 additions & 18 deletions

File tree

OneSignalCapacitorPlugin.podspec

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,9 @@
11
require 'json'
22

33
package = JSON.parse(File.read(File.join(__dir__, 'package.json')))
4+
onesignal_xcframework_version = '5.5.2'
5+
onesignal_disable_location_env = ENV['ONESIGNAL_DISABLE_LOCATION'].to_s.strip.downcase
6+
onesignal_disable_location = ['true', '1'].include?(onesignal_disable_location_env)
47

58
Pod::Spec.new do |s|
69
s.name = 'OnesignalCapacitorPlugin'
@@ -20,5 +23,10 @@ Pod::Spec.new do |s|
2023
s.swift_version = '5.9'
2124

2225
s.dependency 'Capacitor'
23-
s.dependency 'OneSignalXCFramework', '5.5.2'
26+
if onesignal_disable_location
27+
s.dependency 'OneSignalXCFramework/OneSignal', onesignal_xcframework_version
28+
s.dependency 'OneSignalXCFramework/OneSignalInAppMessages', onesignal_xcframework_version
29+
else
30+
s.dependency 'OneSignalXCFramework', onesignal_xcframework_version
31+
end
2432
end

Package.swift

Lines changed: 29 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,34 @@
11
// swift-tools-version: 5.9
22

33
import PackageDescription
4+
import Foundation
5+
6+
func oneSignalEnvFlag(_ name: String) -> Bool {
7+
let value = Context.environment[name]?.trimmingCharacters(in: .whitespacesAndNewlines).lowercased()
8+
return value == "true" || value == "1"
9+
}
10+
11+
let oneSignalDisableLocation = oneSignalEnvFlag("ONESIGNAL_DISABLE_LOCATION")
12+
13+
// InAppMessages, Location, and Extension are separate library products in
14+
// OneSignal-XCFramework and must be linked explicitly under SPM. Location can
15+
// be omitted for apps that do not use OneSignal.Location.
16+
var oneSignalDependencies: [Target.Dependency] = [
17+
.product(name: "OneSignalFramework", package: "OneSignal-XCFramework"),
18+
.product(name: "OneSignalInAppMessages", package: "OneSignal-XCFramework"),
19+
.product(name: "OneSignalExtension", package: "OneSignal-XCFramework"),
20+
]
21+
22+
if !oneSignalDisableLocation {
23+
oneSignalDependencies.append(.product(name: "OneSignalLocation", package: "OneSignal-XCFramework"))
24+
}
25+
26+
var capacitorPluginDependencies: [Target.Dependency] = [
27+
.product(name: "Capacitor", package: "capacitor-swift-pm"),
28+
.product(name: "Cordova", package: "capacitor-swift-pm"),
29+
]
30+
capacitorPluginDependencies.append(contentsOf: oneSignalDependencies)
31+
capacitorPluginDependencies.append("OSCapacitorLaunchOptions")
432

533
let package = Package(
634
name: "OnesignalCapacitorPlugin",
@@ -28,19 +56,7 @@ let package = Package(
2856
),
2957
.target(
3058
name: "OnesignalCapacitorPlugin",
31-
dependencies: [
32-
.product(name: "Capacitor", package: "capacitor-swift-pm"),
33-
.product(name: "Cordova", package: "capacitor-swift-pm"),
34-
// InAppMessages and Location are separate library products in
35-
// OneSignal-XCFramework and must be linked explicitly under SPM,
36-
// otherwise their xcframeworks aren't loaded and the namespaces
37-
// are silent no-ops at runtime.
38-
.product(name: "OneSignalFramework", package: "OneSignal-XCFramework"),
39-
.product(name: "OneSignalInAppMessages", package: "OneSignal-XCFramework"),
40-
.product(name: "OneSignalLocation", package: "OneSignal-XCFramework"),
41-
.product(name: "OneSignalExtension", package: "OneSignal-XCFramework"),
42-
"OSCapacitorLaunchOptions"
43-
],
59+
dependencies: capacitorPluginDependencies,
4460
path: "ios/Sources/OneSignalCapacitorPlugin"
4561
)
4662
]

README.md

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,60 @@ bunx cap sync
3030
npx cap sync
3131
```
3232

33+
## Disabling OneSignal Location
34+
35+
If your app does not use `OneSignal.Location`, you can exclude the native OneSignal location module from iOS and Android builds.
36+
37+
Set `ONESIGNAL_DISABLE_LOCATION=true` in the environment before resolving or building native dependencies. The value is case-insensitive, and `1` is also accepted.
38+
39+
```bash
40+
ONESIGNAL_DISABLE_LOCATION=true npx cap sync
41+
```
42+
43+
In GitHub Actions, set it once at the job or step level so Swift Package Manager, CocoaPods, and Gradle builds inherit it:
44+
45+
```yaml
46+
env:
47+
ONESIGNAL_DISABLE_LOCATION: true
48+
```
49+
50+
With the location module disabled, calls to `OneSignal.Location` are ignored on Android and `OneSignal.Location.isShared()` resolves `false`.
51+
52+
### Applying the change
53+
54+
The environment variable is read when native dependencies are resolved. If you change the variable in an existing project, clear the relevant cache and re-resolve in a shell where the variable is exported.
55+
56+
> [!IMPORTANT]
57+
> When using Xcode or Android Studio, launch the IDE from a terminal that has `ONESIGNAL_DISABLE_LOCATION` exported. An IDE launched from the Dock/Finder does not inherit variables set only in your shell profile.
58+
59+
Swift Package Manager:
60+
61+
```bash
62+
rm -rf ~/Library/Caches/org.swift.swiftpm ~/Library/Developer/Xcode/DerivedData/*
63+
ONESIGNAL_DISABLE_LOCATION=true npx cap sync ios
64+
```
65+
66+
In Xcode, you can instead use **File -> Packages -> Reset Package Caches** with the variable exported, then build.
67+
68+
CocoaPods:
69+
70+
```bash
71+
cd ios/App
72+
pod deintegrate
73+
rm -rf Pods Podfile.lock
74+
ONESIGNAL_DISABLE_LOCATION=true pod install
75+
```
76+
77+
Android Gradle, which re-reads the variable on each configuration:
78+
79+
```bash
80+
ONESIGNAL_DISABLE_LOCATION=true npx cap sync android
81+
cd android
82+
ONESIGNAL_DISABLE_LOCATION=true ./gradlew assembleDebug
83+
```
84+
85+
On CI, key any DerivedData, SwiftPM, CocoaPods, or Gradle caches on the value of `ONESIGNAL_DISABLE_LOCATION` so a restored cache does not resurrect the location module.
86+
3387
## Usage
3488

3589
```ts

android/build.gradle.kts

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -84,8 +84,16 @@ fun propertyOrCatalog(propertyName: String, catalogKey: String): String =
8484
fun intPropertyOrCatalog(propertyName: String, catalogKey: String): Int =
8585
project.findProperty(propertyName)?.toString()?.toInt() ?: catalogVersion(catalogKey).toInt()
8686

87+
fun envFlag(envName: String): Boolean {
88+
val value = System.getenv(envName)
89+
val normalizedValue = value?.trim()
90+
return normalizedValue.equals("true", ignoreCase = true) || normalizedValue == "1"
91+
}
92+
8793
val junitVersion: String = propertyOrCatalog("junitVersion", "junit")
8894
val androidxAppCompatVersion: String = propertyOrCatalog("androidxAppCompatVersion", "androidxAppCompat")
95+
val oneSignalVersion: String = catalogVersion("onesignal")
96+
val oneSignalDisableLocation: Boolean = envFlag("ONESIGNAL_DISABLE_LOCATION")
8997

9098
extra["junitVersion"] = junitVersion
9199
extra["androidxAppCompatVersion"] = androidxAppCompatVersion
@@ -126,7 +134,13 @@ repositories {
126134
dependencies {
127135
"implementation"(project(":capacitor-android"))
128136
"implementation"("androidx.appcompat:appcompat:$androidxAppCompatVersion")
129-
"implementation"("com.onesignal:OneSignal:${catalogVersion("onesignal")}")
137+
if (oneSignalDisableLocation) {
138+
"implementation"("com.onesignal:core:$oneSignalVersion")
139+
"implementation"("com.onesignal:notifications:$oneSignalVersion")
140+
"implementation"("com.onesignal:in-app-messages:$oneSignalVersion")
141+
} else {
142+
"implementation"("com.onesignal:OneSignal:$oneSignalVersion")
143+
}
130144
"testImplementation"("junit:junit:$junitVersion")
131145
"androidTestImplementation"("androidx.test.ext:junit:${catalogVersion("androidxTestJunit")}")
132146
"androidTestImplementation"("androidx.test.espresso:espresso-core:${catalogVersion("androidxEspresso")}")

android/src/main/kotlin/com/onesignal/capacitor/OneSignalCapacitorPlugin.kt

Lines changed: 23 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import com.getcapacitor.PluginMethod
77
import com.getcapacitor.annotation.CapacitorPlugin
88
import com.onesignal.OneSignal
99
import com.onesignal.common.OneSignalWrapper
10+
import com.onesignal.debug.internal.logging.Logging
1011
import com.onesignal.inAppMessages.IInAppMessageClickEvent
1112
import com.onesignal.inAppMessages.IInAppMessageClickListener
1213
import com.onesignal.inAppMessages.IInAppMessageDidDismissEvent
@@ -44,6 +45,8 @@ class OneSignalCapacitorPlugin : Plugin(),
4445
// provisional (3), and ephemeral (4) states do not apply here.
4546
private const val PERMISSION_DENIED = 1
4647
private const val PERMISSION_AUTHORIZED = 2
48+
private const val LOCATION_MODULE_NOT_AVAILABLE =
49+
"OneSignal location module is not available. Add the location dependency to use OneSignal.Location."
4750
}
4851

4952
private val notificationWillDisplayCache = mutableMapOf<String, INotificationWillDisplayEvent>()
@@ -56,6 +59,10 @@ class OneSignalCapacitorPlugin : Plugin(),
5659
// call into the dead Capacitor bridge.
5760
private val pluginScope = MainScope()
5861

62+
private fun logLocationModuleNotAvailable(throwable: Throwable) {
63+
Logging.error(LOCATION_MODULE_NOT_AVAILABLE, throwable)
64+
}
65+
5966
private val permissionObserver = object : IPermissionObserver {
6067
override fun onNotificationPermissionChange(permission: Boolean) {
6168
val ret = JSObject()
@@ -640,22 +647,35 @@ class OneSignalCapacitorPlugin : Plugin(),
640647
@PluginMethod
641648
fun requestLocationPermission(call: PluginCall) {
642649
pluginScope.launch {
643-
OneSignal.Location.requestPermission()
650+
try {
651+
OneSignal.Location.requestPermission()
652+
} catch (t: Throwable) {
653+
logLocationModuleNotAvailable(t)
654+
}
644655
call.resolve()
645656
}
646657
}
647658

648659
@PluginMethod
649660
fun setLocationShared(call: PluginCall) {
650661
val shared = call.getBoolean("shared") ?: false
651-
OneSignal.Location.isShared = shared
662+
try {
663+
OneSignal.Location.isShared = shared
664+
} catch (t: Throwable) {
665+
logLocationModuleNotAvailable(t)
666+
}
652667
call.resolve()
653668
}
654669

655670
@PluginMethod
656671
fun isLocationShared(call: PluginCall) {
657672
val ret = JSObject()
658-
ret.put("shared", OneSignal.Location.isShared)
673+
try {
674+
ret.put("shared", OneSignal.Location.isShared)
675+
} catch (t: Throwable) {
676+
logLocationModuleNotAvailable(t)
677+
ret.put("shared", false)
678+
}
659679
call.resolve(ret)
660680
}
661681

0 commit comments

Comments
 (0)