diff --git a/examples/demo-no-location/.env.example b/examples/demo-no-location/.env.example
new file mode 100644
index 00000000..69d154c0
--- /dev/null
+++ b/examples/demo-no-location/.env.example
@@ -0,0 +1,4 @@
+# Used by run-android.sh and run-ios.sh during scripted builds.
+# For Play Mode in the Unity Editor, set the same value on the
+# NoLocationDemo component in Assets/Scenes/Main.unity.
+ONESIGNAL_APP_ID=YOUR-ONESIGNAL-APP-ID
diff --git a/examples/demo-no-location/.gitignore b/examples/demo-no-location/.gitignore
new file mode 100644
index 00000000..55b9b40c
--- /dev/null
+++ b/examples/demo-no-location/.gitignore
@@ -0,0 +1,54 @@
+# Unity generated folders
+/.utmp/
+/[Ll]ibrary/
+/[Tt]emp/
+/[Oo]bj/
+/[Bb]uild/
+/[Bb]uilds/
+/[Ll]ogs/
+/[Mm]emoryCaptures/
+/[Uu]serSettings/
+
+# Keep this demo project minimal. Unity regenerates the rest of ProjectSettings.
+/ProjectSettings/*
+!/ProjectSettings/AndroidResolverDependencies.xml
+!/ProjectSettings/EditorBuildSettings.asset
+!/ProjectSettings/OneSignalSettings.json
+!/ProjectSettings/ProjectSettings.asset
+!/ProjectSettings/ProjectVersion.txt
+
+# Asset meta data should only be ignored when the corresponding asset is also ignored.
+!/[Aa]ssets/**/*.meta
+
+# IDE and generated project files
+.vs/
+ExportedObj/
+.consulo/
+*.csproj
+*.unityproj
+*.sln
+*.suo
+*.tmp
+*.user
+*.userprefs
+*.pidb
+*.booproj
+*.svd
+*.pdb
+*.mdb
+*.opendb
+*.VC.db
+
+# Unity generated meta files
+*.pidb.meta
+*.pdb.meta
+*.mdb.meta
+
+# Build outputs
+*.apk
+*.unitypackage
+
+# Environment files
+.env
+Assets/StreamingAssets/.env
+Assets/StreamingAssets/.env.meta
diff --git a/examples/demo-no-location/Assets.meta b/examples/demo-no-location/Assets.meta
new file mode 100644
index 00000000..109578fe
--- /dev/null
+++ b/examples/demo-no-location/Assets.meta
@@ -0,0 +1,8 @@
+fileFormatVersion: 2
+guid: b1c9ae431ac14f74a5ec239a9340107d
+folderAsset: yes
+DefaultImporter:
+ externalObjects: {}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/examples/demo-no-location/Assets/OneSignal.meta b/examples/demo-no-location/Assets/OneSignal.meta
new file mode 100644
index 00000000..d46fbe8b
--- /dev/null
+++ b/examples/demo-no-location/Assets/OneSignal.meta
@@ -0,0 +1,8 @@
+fileFormatVersion: 2
+guid: 2b8e5a14c93d4f7e9a0c3d6b1f84e527
+folderAsset: yes
+DefaultImporter:
+ externalObjects: {}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/examples/demo-no-location/Assets/OneSignal/Editor.meta b/examples/demo-no-location/Assets/OneSignal/Editor.meta
new file mode 100644
index 00000000..bd5cfabd
--- /dev/null
+++ b/examples/demo-no-location/Assets/OneSignal/Editor.meta
@@ -0,0 +1,8 @@
+fileFormatVersion: 2
+guid: da0271b7f2a5c4537ae9a45ae82b450e
+folderAsset: yes
+DefaultImporter:
+ externalObjects: {}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/examples/demo-no-location/Assets/OneSignal/Editor/OneSignalAndroidDependencies.xml b/examples/demo-no-location/Assets/OneSignal/Editor/OneSignalAndroidDependencies.xml
new file mode 100644
index 00000000..f41da55a
--- /dev/null
+++ b/examples/demo-no-location/Assets/OneSignal/Editor/OneSignalAndroidDependencies.xml
@@ -0,0 +1,10 @@
+
+
+
+ https://repo.maven.apache.org/maven2
+
+
+
+
+
+
diff --git a/examples/demo-no-location/Assets/OneSignal/Editor/OneSignalAndroidDependencies.xml.meta b/examples/demo-no-location/Assets/OneSignal/Editor/OneSignalAndroidDependencies.xml.meta
new file mode 100644
index 00000000..5e5ebd35
--- /dev/null
+++ b/examples/demo-no-location/Assets/OneSignal/Editor/OneSignalAndroidDependencies.xml.meta
@@ -0,0 +1,7 @@
+fileFormatVersion: 2
+guid: 94ac4dfb3f20e4c08afa2b53752207c3
+TextScriptImporter:
+ externalObjects: {}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/examples/demo-no-location/Assets/OneSignal/Editor/OneSignaliOSDependencies.xml b/examples/demo-no-location/Assets/OneSignal/Editor/OneSignaliOSDependencies.xml
new file mode 100644
index 00000000..15c9f1be
--- /dev/null
+++ b/examples/demo-no-location/Assets/OneSignal/Editor/OneSignaliOSDependencies.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
diff --git a/examples/demo-no-location/Assets/OneSignal/Editor/OneSignaliOSDependencies.xml.meta b/examples/demo-no-location/Assets/OneSignal/Editor/OneSignaliOSDependencies.xml.meta
new file mode 100644
index 00000000..c3844c58
--- /dev/null
+++ b/examples/demo-no-location/Assets/OneSignal/Editor/OneSignaliOSDependencies.xml.meta
@@ -0,0 +1,7 @@
+fileFormatVersion: 2
+guid: 63a05d4f4b1e24c9abb11ad9675ec7c0
+TextScriptImporter:
+ externalObjects: {}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/examples/demo-no-location/Assets/OneSignal/link.xml b/examples/demo-no-location/Assets/OneSignal/link.xml
new file mode 100644
index 00000000..63b9781b
--- /dev/null
+++ b/examples/demo-no-location/Assets/OneSignal/link.xml
@@ -0,0 +1,5 @@
+
+
+
+
+
diff --git a/examples/demo-no-location/Assets/OneSignal/link.xml.meta b/examples/demo-no-location/Assets/OneSignal/link.xml.meta
new file mode 100644
index 00000000..baeb0163
--- /dev/null
+++ b/examples/demo-no-location/Assets/OneSignal/link.xml.meta
@@ -0,0 +1,7 @@
+fileFormatVersion: 2
+guid: 7f3c1d9a4b2e4c8fa1d65e0c9b3a7f12
+TextScriptImporter:
+ externalObjects: {}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/examples/demo-no-location/Assets/Plugins.meta b/examples/demo-no-location/Assets/Plugins.meta
new file mode 100644
index 00000000..bdc3afd7
--- /dev/null
+++ b/examples/demo-no-location/Assets/Plugins.meta
@@ -0,0 +1,8 @@
+fileFormatVersion: 2
+guid: 7144c27db138d4e5d9672d3b8cb84124
+folderAsset: yes
+DefaultImporter:
+ externalObjects: {}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/examples/demo-no-location/Assets/Plugins/Android.meta b/examples/demo-no-location/Assets/Plugins/Android.meta
new file mode 100644
index 00000000..3a0ea5c5
--- /dev/null
+++ b/examples/demo-no-location/Assets/Plugins/Android.meta
@@ -0,0 +1,8 @@
+fileFormatVersion: 2
+guid: 1cdb4e048836243b9a70b07e3920718a
+folderAsset: yes
+DefaultImporter:
+ externalObjects: {}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/examples/demo-no-location/Assets/Plugins/Android/gradleTemplate.properties b/examples/demo-no-location/Assets/Plugins/Android/gradleTemplate.properties
new file mode 100644
index 00000000..4f9e9a40
--- /dev/null
+++ b/examples/demo-no-location/Assets/Plugins/Android/gradleTemplate.properties
@@ -0,0 +1,10 @@
+org.gradle.jvmargs=-Xmx**JVM_HEAP_SIZE**M
+org.gradle.parallel=true
+org.gradle.caching=true
+org.gradle.configuration-cache=true
+unityStreamingAssets=**STREAMING_ASSETS**
+# Android Resolver Properties Start
+android.useAndroidX=true
+android.enableJetifier=true
+# Android Resolver Properties End
+**ADDITIONAL_PROPERTIES**
diff --git a/examples/demo-no-location/Assets/Plugins/Android/gradleTemplate.properties.meta b/examples/demo-no-location/Assets/Plugins/Android/gradleTemplate.properties.meta
new file mode 100644
index 00000000..cacd73ac
--- /dev/null
+++ b/examples/demo-no-location/Assets/Plugins/Android/gradleTemplate.properties.meta
@@ -0,0 +1,7 @@
+fileFormatVersion: 2
+guid: c3e6b9a42d1f5a3c0b5e4f8d7a9c1e23
+DefaultImporter:
+ externalObjects: {}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/examples/demo-no-location/Assets/Plugins/Android/mainTemplate.gradle b/examples/demo-no-location/Assets/Plugins/Android/mainTemplate.gradle
new file mode 100644
index 00000000..f1667696
--- /dev/null
+++ b/examples/demo-no-location/Assets/Plugins/Android/mainTemplate.gradle
@@ -0,0 +1,66 @@
+// GENERATED BY UNITY. REMOVE THIS COMMENT TO PREVENT OVERWRITING WHEN EXPORTING AGAIN
+
+apply plugin: 'com.android.library'
+apply from: '../shared/keepUnitySymbols.gradle'
+apply from: '../shared/common.gradle'
+**APPLY_PLUGINS**
+
+dependencies {
+ implementation fileTree(dir: 'libs', include: ['*.jar'])
+// Android Resolver Dependencies Start
+ implementation 'com.onesignal:core:5.9.5' // Assets/OneSignal/Editor/OneSignalAndroidDependencies.xml
+ implementation 'com.onesignal:notifications:5.9.5' // Assets/OneSignal/Editor/OneSignalAndroidDependencies.xml
+ implementation 'com.onesignal:in-app-messages:5.9.5' // Assets/OneSignal/Editor/OneSignalAndroidDependencies.xml
+// Android Resolver Dependencies End
+**DEPS**}
+
+// Android Resolver Exclusions Start
+android {
+ packaging {
+ exclude ('/lib/armeabi/*' + '*')
+ exclude ('/lib/armeabi-v7a/*' + '*')
+ exclude ('/lib/mips/*' + '*')
+ exclude ('/lib/mips64/*' + '*')
+ exclude ('/lib/x86/*' + '*')
+ exclude ('/lib/x86_64/*' + '*')
+ }
+}
+// Android Resolver Exclusions End
+android {
+ namespace "com.unity3d.player"
+ ndkPath "**NDKPATH**"
+ ndkVersion "**NDKVERSION**"
+
+ compileSdk **APIVERSION**
+ buildToolsVersion = "**BUILDTOOLS**"
+
+ compileOptions {
+ sourceCompatibility JavaVersion.VERSION_17
+ targetCompatibility JavaVersion.VERSION_17
+ }
+
+ defaultConfig {
+ minSdk **MINSDK**
+ targetSdk **TARGETSDK**
+ ndk {
+ abiFilters **ABIFILTERS**
+ debugSymbolLevel **DEBUGSYMBOLLEVEL**
+ }
+ versionCode **VERSIONCODE**
+ versionName '**VERSIONNAME**'
+ consumerProguardFiles 'proguard-unity.txt'**USER_PROGUARD**
+**DEFAULT_CONFIG_SETUP**
+ }
+
+ lint {
+ abortOnError false
+ }
+
+ androidResources {
+ noCompress = **BUILTIN_NOCOMPRESS** + unityStreamingAssets.tokenize(', ')
+ ignoreAssetsPattern = "!.svn:!.git:!.ds_store:!*.scc:!CVS:!thumbs.db:!picasa.ini:!*~"
+ }**PACKAGING**
+}**REPOSITORIES**
+**IL_CPP_BUILD_SETUP**
+**SOURCE_BUILD_SETUP**
+**EXTERNAL_SOURCES**
diff --git a/examples/demo-no-location/Assets/Plugins/Android/mainTemplate.gradle.meta b/examples/demo-no-location/Assets/Plugins/Android/mainTemplate.gradle.meta
new file mode 100644
index 00000000..326dc6a0
--- /dev/null
+++ b/examples/demo-no-location/Assets/Plugins/Android/mainTemplate.gradle.meta
@@ -0,0 +1,7 @@
+fileFormatVersion: 2
+guid: a1c4f7e20b9d4e1a8f3c2d6b5e7a9c01
+DefaultImporter:
+ externalObjects: {}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/examples/demo-no-location/Assets/Plugins/Android/proguard-user.txt b/examples/demo-no-location/Assets/Plugins/Android/proguard-user.txt
new file mode 100644
index 00000000..d1bea67c
--- /dev/null
+++ b/examples/demo-no-location/Assets/Plugins/Android/proguard-user.txt
@@ -0,0 +1,9 @@
+-keep class com.onesignal.** { *; }
+
+# Work around for IllegalStateException with kotlinx-coroutines-android
+-keep class kotlinx.coroutines.android.AndroidDispatcherFactory {*;}
+
+# WorkManager initializes a Room database through AndroidX Startup before Unity starts.
+# Unity release builds run R8, so keep the generated database implementation reachable.
+-keep class androidx.work.impl.WorkDatabase* { *; }
+-keep class androidx.work.impl.model.** { *; }
diff --git a/examples/demo-no-location/Assets/Plugins/Android/proguard-user.txt.meta b/examples/demo-no-location/Assets/Plugins/Android/proguard-user.txt.meta
new file mode 100644
index 00000000..5ffc330a
--- /dev/null
+++ b/examples/demo-no-location/Assets/Plugins/Android/proguard-user.txt.meta
@@ -0,0 +1,7 @@
+fileFormatVersion: 2
+guid: d4f7c0b53e2a6b4d1c6f5a9e8b0d2f34
+TextScriptImporter:
+ externalObjects: {}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/examples/demo-no-location/Assets/Plugins/Android/settingsTemplate.gradle b/examples/demo-no-location/Assets/Plugins/Android/settingsTemplate.gradle
new file mode 100644
index 00000000..e2b67f57
--- /dev/null
+++ b/examples/demo-no-location/Assets/Plugins/Android/settingsTemplate.gradle
@@ -0,0 +1,30 @@
+pluginManagement {
+ repositories {
+ **ARTIFACTORYREPOSITORY**
+ gradlePluginPortal()
+ google()
+ mavenCentral()
+ }
+}
+
+include ':launcher', ':unityLibrary'
+**INCLUDES**
+
+dependencyResolutionManagement {
+ repositoriesMode.set(RepositoriesMode.PREFER_SETTINGS)
+ repositories {
+ **ARTIFACTORYREPOSITORY**
+ google()
+ mavenCentral()
+// Android Resolver Repos Start
+ def unityProjectPath = $/file:///**DIR_UNITYPROJECT**/$.replace("\\", "/")
+ maven {
+ url "https://repo.maven.apache.org/maven2" // Assets/OneSignal/Editor/OneSignalAndroidDependencies.xml
+ }
+ mavenLocal()
+// Android Resolver Repos End
+ flatDir {
+ dirs "${project(':unityLibrary').projectDir}/libs"
+ }
+ }
+}
diff --git a/examples/demo-no-location/Assets/Plugins/Android/settingsTemplate.gradle.meta b/examples/demo-no-location/Assets/Plugins/Android/settingsTemplate.gradle.meta
new file mode 100644
index 00000000..d8962b33
--- /dev/null
+++ b/examples/demo-no-location/Assets/Plugins/Android/settingsTemplate.gradle.meta
@@ -0,0 +1,7 @@
+fileFormatVersion: 2
+guid: b2d5a8f31c0e4f2b9a4d3e7c6f8b0d12
+DefaultImporter:
+ externalObjects: {}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/examples/demo-no-location/Assets/Scenes.meta b/examples/demo-no-location/Assets/Scenes.meta
new file mode 100644
index 00000000..fa507164
--- /dev/null
+++ b/examples/demo-no-location/Assets/Scenes.meta
@@ -0,0 +1,8 @@
+fileFormatVersion: 2
+guid: 09e41d679b69424089c08cc9c99557bf
+folderAsset: yes
+DefaultImporter:
+ externalObjects: {}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/examples/demo-no-location/Assets/Scenes/Main.unity b/examples/demo-no-location/Assets/Scenes/Main.unity
new file mode 100644
index 00000000..c01df042
--- /dev/null
+++ b/examples/demo-no-location/Assets/Scenes/Main.unity
@@ -0,0 +1,161 @@
+%YAML 1.1
+%TAG !u! tag:unity3d.com,2011:
+--- !u!29 &1
+OcclusionCullingSettings:
+ m_ObjectHideFlags: 0
+ serializedVersion: 2
+ m_OcclusionBakeSettings:
+ smallestOccluder: 5
+ smallestHole: 0.25
+ backfaceThreshold: 100
+ m_SceneGUID: 00000000000000000000000000000000
+ m_OcclusionCullingData: {fileID: 0}
+--- !u!104 &2
+RenderSettings:
+ m_ObjectHideFlags: 0
+ serializedVersion: 10
+ m_Fog: 0
+ m_FogColor: {r: 0.5, g: 0.5, b: 0.5, a: 1}
+ m_FogMode: 3
+ m_FogDensity: 0.01
+ m_LinearFogStart: 0
+ m_LinearFogEnd: 300
+ m_AmbientSkyColor: {r: 0.212, g: 0.227, b: 0.259, a: 1}
+ m_AmbientEquatorColor: {r: 0.114, g: 0.125, b: 0.133, a: 1}
+ m_AmbientGroundColor: {r: 0.047, g: 0.043, b: 0.035, a: 1}
+ m_AmbientIntensity: 1
+ m_AmbientMode: 0
+ m_SubtractiveShadowColor: {r: 0.42, g: 0.48, b: 0.63, a: 1}
+ m_SkyboxMaterial: {fileID: 0}
+ m_HaloStrength: 0.5
+ m_FlareStrength: 1
+ m_FlareFadeSpeed: 3
+ m_HaloTexture: {fileID: 0}
+ m_SpotCookie: {fileID: 0}
+ m_DefaultReflectionMode: 0
+ m_DefaultReflectionResolution: 128
+ m_ReflectionBounces: 1
+ m_ReflectionIntensity: 1
+ m_CustomReflection: {fileID: 0}
+ m_Sun: {fileID: 0}
+ m_UseRadianceAmbientProbe: 0
+--- !u!157 &3
+LightmapSettings:
+ m_ObjectHideFlags: 0
+ serializedVersion: 12
+ m_GIWorkflowMode: 1
+ m_GISettings:
+ serializedVersion: 2
+ m_BounceScale: 1
+ m_IndirectOutputScale: 1
+ m_AlbedoBoost: 1
+ m_EnvironmentLightingMode: 0
+ m_EnableBakedLightmaps: 1
+ m_EnableRealtimeLightmaps: 0
+ m_LightmapEditorSettings:
+ serializedVersion: 12
+ m_Resolution: 2
+ m_BakeResolution: 40
+ m_AtlasSize: 1024
+ m_AO: 0
+ m_AOMaxDistance: 1
+ m_CompAOExponent: 1
+ m_CompAOExponentDirect: 0
+ m_ExtractAmbientOcclusion: 0
+ m_Padding: 2
+ m_LightmapParameters: {fileID: 0}
+ m_LightmapsBakeMode: 1
+ m_TextureCompression: 1
+ m_FinalGather: 0
+ m_FinalGatherFiltering: 1
+ m_FinalGatherRayCount: 256
+ m_ReflectionCompression: 2
+ m_MixedBakeMode: 2
+ m_BakeBackend: 1
+ m_PVRSampling: 1
+ m_PVRDirectSampleCount: 32
+ m_PVRSampleCount: 512
+ m_PVREnvironmentSampleCount: 256
+ m_PVREnvironmentReferencePointCount: 2048
+ m_PVRFilteringMode: 1
+ m_PVRDenoiserTypeDirect: 1
+ m_PVRDenoiserTypeIndirect: 1
+ m_PVRDenoiserTypeAO: 1
+ m_PVRFilterTypeDirect: 0
+ m_PVRFilterTypeIndirect: 0
+ m_PVRFilterTypeAO: 0
+ m_PVREnvironmentMIS: 1
+ m_ExportTrainingData: 0
+ m_TrainingDataDestination: TrainingData
+ m_LightProbeSampleCountMultiplier: 4
+ m_LightingDataAsset: {fileID: 0}
+ m_LightingSettings: {fileID: 0}
+--- !u!196 &4
+NavMeshSettings:
+ serializedVersion: 2
+ m_ObjectHideFlags: 0
+ m_BuildSettings:
+ serializedVersion: 3
+ agentTypeID: 0
+ agentRadius: 0.5
+ agentHeight: 2
+ agentSlope: 45
+ agentClimb: 0.4
+ ledgeDropHeight: 0
+ maxJumpAcrossDistance: 0
+ minRegionArea: 2
+ manualCellSize: 0
+ cellSize: 0.16666667
+ manualTileSize: 0
+ tileSize: 256
+ buildHeightMesh: 0
+ maxJobWorkers: 0
+ preserveTilesOutsideBounds: 0
+ debug:
+ m_Flags: 0
+ m_NavMeshData: {fileID: 0}
+--- !u!1 &100000
+GameObject:
+ m_ObjectHideFlags: 0
+ m_CorrespondingSourceObject: {fileID: 0}
+ m_PrefabInstance: {fileID: 0}
+ m_PrefabAsset: {fileID: 0}
+ serializedVersion: 6
+ m_Component:
+ - component: {fileID: 100001}
+ - component: {fileID: 100002}
+ m_Layer: 0
+ m_Name: OneSignal No Location Demo
+ m_TagString: Untagged
+ m_Icon: {fileID: 0}
+ m_NavMeshLayer: 0
+ m_StaticEditorFlags: 0
+ m_IsActive: 1
+--- !u!4 &100001
+Transform:
+ m_ObjectHideFlags: 0
+ m_CorrespondingSourceObject: {fileID: 0}
+ m_PrefabInstance: {fileID: 0}
+ m_PrefabAsset: {fileID: 0}
+ m_GameObject: {fileID: 100000}
+ serializedVersion: 2
+ m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
+ m_LocalPosition: {x: 0, y: 0, z: 0}
+ m_LocalScale: {x: 1, y: 1, z: 1}
+ m_ConstrainProportionsScale: 0
+ m_Children: []
+ m_Father: {fileID: 0}
+ m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
+--- !u!114 &100002
+MonoBehaviour:
+ m_ObjectHideFlags: 0
+ m_CorrespondingSourceObject: {fileID: 0}
+ m_PrefabInstance: {fileID: 0}
+ m_PrefabAsset: {fileID: 0}
+ m_GameObject: {fileID: 100000}
+ m_Enabled: 1
+ m_EditorHideFlags: 0
+ m_Script: {fileID: 11500000, guid: 4e1e7c96909144afa42b3fb595db18f0, type: 3}
+ m_Name:
+ m_EditorClassIdentifier:
+ _oneSignalAppId: YOUR-ONESIGNAL-APP-ID
diff --git a/examples/demo-no-location/Assets/Scenes/Main.unity.meta b/examples/demo-no-location/Assets/Scenes/Main.unity.meta
new file mode 100644
index 00000000..2d24661a
--- /dev/null
+++ b/examples/demo-no-location/Assets/Scenes/Main.unity.meta
@@ -0,0 +1,7 @@
+fileFormatVersion: 2
+guid: 3d514e5ac1634c1b8bcf595734736969
+DefaultImporter:
+ externalObjects: {}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/examples/demo-no-location/Assets/Scripts.meta b/examples/demo-no-location/Assets/Scripts.meta
new file mode 100644
index 00000000..08b53c30
--- /dev/null
+++ b/examples/demo-no-location/Assets/Scripts.meta
@@ -0,0 +1,8 @@
+fileFormatVersion: 2
+guid: 74d60b46c43f47a4bf33a9f8dcf14cd4
+folderAsset: yes
+DefaultImporter:
+ externalObjects: {}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/examples/demo-no-location/Assets/Scripts/Editor.meta b/examples/demo-no-location/Assets/Scripts/Editor.meta
new file mode 100644
index 00000000..1924ad09
--- /dev/null
+++ b/examples/demo-no-location/Assets/Scripts/Editor.meta
@@ -0,0 +1,8 @@
+fileFormatVersion: 2
+guid: 459b3b9dbf4c4e72994239ce9fc89479
+folderAsset: yes
+DefaultImporter:
+ externalObjects: {}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/examples/demo-no-location/Assets/Scripts/Editor/BuildScript.cs b/examples/demo-no-location/Assets/Scripts/Editor/BuildScript.cs
new file mode 100644
index 00000000..68636f52
--- /dev/null
+++ b/examples/demo-no-location/Assets/Scripts/Editor/BuildScript.cs
@@ -0,0 +1,244 @@
+using System;
+using System.IO;
+using UnityEditor;
+using UnityEditor.Build;
+using UnityEditor.Build.Reporting;
+using UnityEditor.SceneManagement;
+using UnityEngine;
+
+public static class BuildScript
+{
+ private const string AndroidOutputDir = "Build/Android";
+ private const string ApkName = "onesignal-demo-no-location.apk";
+ private const string IOSOutputDir = "Build/iOS";
+ private const string AppIdEnvironmentVariable = "ONESIGNAL_APP_ID";
+ private const string MainScenePath = "Assets/Scenes/Main.unity";
+ private const string OneSignalAppIdPropertyName = "_oneSignalAppId";
+ private const string NoLocationDemoTypeName = "NoLocationDemo";
+
+ public static void BuildAndroidEmulator()
+ {
+ var outputPath = Path.Combine(AndroidOutputDir, ApkName);
+ Directory.CreateDirectory(AndroidOutputDir);
+
+ PlayerSettings.Android.targetArchitectures = AndroidArchitecture.ARM64;
+ PlayerSettings.SetScriptingBackend(
+ NamedBuildTarget.Android,
+ ScriptingImplementation.IL2CPP
+ );
+ PlayerSettings.SetIl2CppCodeGeneration(
+ NamedBuildTarget.Android,
+ Il2CppCodeGeneration.OptimizeSize
+ );
+ PlayerSettings.SetManagedStrippingLevel(
+ NamedBuildTarget.Android,
+ ManagedStrippingLevel.High
+ );
+ PlayerSettings.Android.minifyRelease = true;
+ PlayerSettings.Android.minifyWithR8 = true;
+ PlayerSettings.stripEngineCode = true;
+ PlayerSettings.SetIl2CppCompilerConfiguration(
+ NamedBuildTarget.Android,
+ Il2CppCompilerConfiguration.Release
+ );
+ EditorUserBuildSettings.androidBuildSystem = AndroidBuildSystem.Gradle;
+ EditorUserBuildSettings.exportAsGoogleAndroidProject = false;
+ EditorUserBuildSettings.buildAppBundle = false;
+
+ BuildReport report;
+ using (ApplyConfiguredAppId())
+ report = BuildPipeline.BuildPlayer(
+ new BuildPlayerOptions
+ {
+ scenes = GetScenes(),
+ locationPathName = outputPath,
+ target = BuildTarget.Android,
+ subtarget = 0,
+ options = BuildOptions.None,
+ }
+ );
+
+ HandleReport(report, outputPath);
+ }
+
+ public static void BuildiOSSimulator()
+ {
+ Directory.CreateDirectory(IOSOutputDir);
+
+ PlayerSettings.SetScriptingBackend(NamedBuildTarget.iOS, ScriptingImplementation.IL2CPP);
+ PlayerSettings.iOS.sdkVersion = iOSSdkVersion.SimulatorSDK;
+ PlayerSettings.iOS.simulatorSdkArchitecture = AppleMobileArchitectureSimulator.Universal;
+ PlayerSettings.SetIl2CppCodeGeneration(
+ NamedBuildTarget.iOS,
+ Il2CppCodeGeneration.OptimizeSize
+ );
+ PlayerSettings.SetManagedStrippingLevel(NamedBuildTarget.iOS, ManagedStrippingLevel.High);
+ PlayerSettings.stripEngineCode = true;
+ PlayerSettings.SetIl2CppCompilerConfiguration(
+ NamedBuildTarget.iOS,
+ Il2CppCompilerConfiguration.Release
+ );
+
+ BuildReport report;
+ using (ApplyConfiguredAppId())
+ report = BuildPipeline.BuildPlayer(
+ new BuildPlayerOptions
+ {
+ scenes = GetScenes(),
+ locationPathName = IOSOutputDir,
+ target = BuildTarget.iOS,
+ options = BuildOptions.None,
+ }
+ );
+
+ HandleReport(report, IOSOutputDir);
+ }
+
+ private static IDisposable ApplyConfiguredAppId()
+ {
+ var appId = GetConfiguredAppId();
+ if (string.IsNullOrWhiteSpace(appId))
+ return AppIdOverride.Noop;
+
+ var scenePath = GetMainScenePath();
+ if (!File.Exists(scenePath))
+ {
+ Debug.LogWarning($"[BuildScript] Could not find scene at {scenePath}");
+ return AppIdOverride.Noop;
+ }
+
+ var originalSceneContents = File.ReadAllText(scenePath);
+ var scene = EditorSceneManager.OpenScene(scenePath);
+
+ foreach (var rootGameObject in scene.GetRootGameObjects())
+ {
+ foreach (var component in rootGameObject.GetComponentsInChildren(true))
+ {
+ if (component == null || component.GetType().Name != NoLocationDemoTypeName)
+ continue;
+
+ var serializedObject = new SerializedObject(component);
+ var appIdProperty = serializedObject.FindProperty(OneSignalAppIdPropertyName);
+ if (appIdProperty == null)
+ continue;
+
+ appIdProperty.stringValue = appId;
+ serializedObject.ApplyModifiedPropertiesWithoutUndo();
+ EditorUtility.SetDirty(component);
+ EditorSceneManager.MarkSceneDirty(scene);
+ EditorSceneManager.SaveScene(scene);
+ Debug.Log(
+ $"[BuildScript] Applied {AppIdEnvironmentVariable} from environment or .env for this build."
+ );
+ return new AppIdOverride(scenePath, originalSceneContents);
+ }
+ }
+
+ Debug.LogWarning($"[BuildScript] Could not find {NoLocationDemoTypeName} in {scenePath}");
+ return new AppIdOverride(scenePath, originalSceneContents);
+ }
+
+ private static string GetConfiguredAppId()
+ {
+ var appId = Environment.GetEnvironmentVariable(AppIdEnvironmentVariable);
+ if (!string.IsNullOrWhiteSpace(appId))
+ return Unquote(appId.Trim());
+
+ var envPath = Path.Combine(Directory.GetParent(Application.dataPath).FullName, ".env");
+ if (!File.Exists(envPath))
+ return null;
+
+ foreach (var line in File.ReadAllLines(envPath))
+ {
+ var trimmed = line.Trim();
+ if (string.IsNullOrEmpty(trimmed) || trimmed.StartsWith("#"))
+ continue;
+
+ if (trimmed.StartsWith("export "))
+ trimmed = trimmed.Substring("export ".Length).TrimStart();
+
+ var separator = trimmed.IndexOf('=');
+ if (separator <= 0)
+ continue;
+
+ var key = trimmed.Substring(0, separator).Trim();
+ if (key != AppIdEnvironmentVariable)
+ continue;
+
+ return Unquote(trimmed.Substring(separator + 1).Trim());
+ }
+
+ return null;
+ }
+
+ private static string GetMainScenePath()
+ {
+ var scenes = GetScenes();
+ foreach (var scenePath in scenes)
+ {
+ if (scenePath == MainScenePath)
+ return scenePath;
+ }
+
+ return scenes.Length > 0 ? scenes[0] : MainScenePath;
+ }
+
+ private static string Unquote(string value)
+ {
+ if (value.Length < 2)
+ return value;
+
+ var first = value[0];
+ var last = value[value.Length - 1];
+ if ((first == '"' && last == '"') || (first == '\'' && last == '\''))
+ return value.Substring(1, value.Length - 2);
+
+ return value;
+ }
+
+ private static string[] GetScenes()
+ {
+ var scenes = EditorBuildSettings.scenes;
+ if (scenes.Length == 0)
+ return new[] { "Assets/Scenes/Main.unity" };
+
+ return Array.ConvertAll(scenes, scene => scene.path);
+ }
+
+ private static void HandleReport(BuildReport report, string outputPath)
+ {
+ if (report.summary.result == BuildResult.Succeeded)
+ {
+ Debug.Log($"[BuildScript] Build succeeded: {outputPath}");
+ return;
+ }
+
+ Debug.LogError(
+ $"[BuildScript] Build failed: {report.summary.result} - {report.summary.totalErrors} error(s)"
+ );
+ EditorApplication.Exit(1);
+ }
+
+ private sealed class AppIdOverride : IDisposable
+ {
+ internal static readonly AppIdOverride Noop = new AppIdOverride(null, null);
+
+ private readonly string _scenePath;
+ private readonly string _originalSceneContents;
+
+ internal AppIdOverride(string scenePath, string originalSceneContents)
+ {
+ _scenePath = scenePath;
+ _originalSceneContents = originalSceneContents;
+ }
+
+ public void Dispose()
+ {
+ if (string.IsNullOrEmpty(_scenePath) || _originalSceneContents == null)
+ return;
+
+ File.WriteAllText(_scenePath, _originalSceneContents);
+ AssetDatabase.ImportAsset(_scenePath);
+ }
+ }
+}
diff --git a/examples/demo-no-location/Assets/Scripts/Editor/BuildScript.cs.meta b/examples/demo-no-location/Assets/Scripts/Editor/BuildScript.cs.meta
new file mode 100644
index 00000000..367b6be4
--- /dev/null
+++ b/examples/demo-no-location/Assets/Scripts/Editor/BuildScript.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: 8269db6cc30844f3a02020892822213d
+MonoImporter:
+ externalObjects: {}
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {instanceID: 0}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/examples/demo-no-location/Assets/Scripts/Editor/OneSignal.NoLocationDemo.Editor.asmdef b/examples/demo-no-location/Assets/Scripts/Editor/OneSignal.NoLocationDemo.Editor.asmdef
new file mode 100644
index 00000000..3d7cc0ad
--- /dev/null
+++ b/examples/demo-no-location/Assets/Scripts/Editor/OneSignal.NoLocationDemo.Editor.asmdef
@@ -0,0 +1,17 @@
+{
+ "name": "OneSignal.NoLocationDemo.Editor",
+ "references": [
+ "OneSignal.Core.Editor"
+ ],
+ "includePlatforms": [
+ "Editor"
+ ],
+ "excludePlatforms": [],
+ "allowUnsafeCode": false,
+ "overrideReferences": false,
+ "precompiledReferences": [],
+ "autoReferenced": true,
+ "defineConstraints": [],
+ "versionDefines": [],
+ "noEngineReferences": false
+}
diff --git a/examples/demo-no-location/Assets/Scripts/Editor/OneSignal.NoLocationDemo.Editor.asmdef.meta b/examples/demo-no-location/Assets/Scripts/Editor/OneSignal.NoLocationDemo.Editor.asmdef.meta
new file mode 100644
index 00000000..61bd464c
--- /dev/null
+++ b/examples/demo-no-location/Assets/Scripts/Editor/OneSignal.NoLocationDemo.Editor.asmdef.meta
@@ -0,0 +1,7 @@
+fileFormatVersion: 2
+guid: 7940c97e347c4a378e08f8df79280662
+AssemblyDefinitionImporter:
+ externalObjects: {}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/examples/demo-no-location/Assets/Scripts/NoLocationDemo.cs b/examples/demo-no-location/Assets/Scripts/NoLocationDemo.cs
new file mode 100644
index 00000000..763b2775
--- /dev/null
+++ b/examples/demo-no-location/Assets/Scripts/NoLocationDemo.cs
@@ -0,0 +1,401 @@
+using System;
+using System.Text;
+using System.Threading.Tasks;
+using OneSignalSDK;
+using OneSignalSDK.Debug.Models;
+using UnityEngine;
+using UnityEngine.Networking;
+
+public sealed class NoLocationDemo : MonoBehaviour
+{
+ [SerializeField]
+ private string _oneSignalAppId = "YOUR-ONESIGNAL-APP-ID";
+
+ private const float ReferenceWidth = 393f;
+ private static readonly Color _backgroundColor = new Color32(248, 249, 250, 255);
+ private static readonly Color _primaryColor = new Color32(229, 75, 77, 255);
+ private static readonly Color _valueColor = new Color32(47, 52, 55, 255);
+ private static readonly Color _mutedTextColor = new Color32(97, 97, 97, 255);
+ private static readonly Color _labelColor = new Color32(107, 114, 128, 255);
+ private static readonly Color _dividerColor = new Color32(232, 234, 237, 255);
+ private static readonly Color _warningColor = new Color32(201, 37, 45, 255);
+
+ private GUIStyle _bodyStyle;
+ private GUIStyle _buttonStyle;
+ private GUIStyle _cardStyle;
+ private GUIStyle _headerSubtitleStyle;
+ private GUIStyle _headerTitleStyle;
+ private GUIStyle _labelStyle;
+ private GUIStyle _outlineButtonStyle;
+ private GUIStyle _sectionHeaderStyle;
+ private GUIStyle _valueStyle;
+ private GUIStyle _warningValueStyle;
+ private Texture2D _cardTexture;
+ private Texture2D _dividerTexture;
+ private Texture2D _primaryTexture;
+ private Texture2D _whiteTexture;
+ private Texture2D _backgroundTexture;
+ private Vector2 _scrollPosition;
+
+ private string _locationStatus = "Location test not run";
+ private string _pushStatus = string.Empty;
+ private bool _initialized;
+
+ private void Start()
+ {
+ OneSignal.Debug.LogLevel = LogLevel.Verbose;
+
+ if (!IsConfigured)
+ return;
+
+ OneSignal.Initialize(_oneSignalAppId);
+ _initialized = true;
+ }
+
+ private void OnGUI()
+ {
+ EnsureStyles();
+
+ var scale = Mathf.Max(1f, Screen.width / ReferenceWidth);
+ var logicalWidth = Screen.width / scale;
+ var logicalHeight = Screen.height / scale;
+ var safeArea = ScaleRect(Screen.safeArea, 1f / scale);
+ var topInset = Mathf.Max(0f, logicalHeight - safeArea.yMax);
+ var bottomInset = Mathf.Max(0f, safeArea.y);
+
+ var previousMatrix = GUI.matrix;
+ GUI.matrix = Matrix4x4.TRS(Vector3.zero, Quaternion.identity, new Vector3(scale, scale, 1f));
+
+ GUI.DrawTexture(new Rect(0, 0, logicalWidth, logicalHeight), _backgroundTexture);
+
+ var headerHeight = topInset + 72f;
+ GUI.DrawTexture(new Rect(0, 0, logicalWidth, headerHeight), _primaryTexture);
+ GUI.Label(new Rect(16f, topInset + 12f, logicalWidth - 32f, 28f), "OneSignal", _headerTitleStyle);
+ GUI.Label(
+ new Rect(16f, topInset + 42f, logicalWidth - 32f, 20f),
+ "No-Location Demo",
+ _headerSubtitleStyle
+ );
+
+ var scrollRect = new Rect(0, headerHeight, logicalWidth, logicalHeight - headerHeight);
+ var contentWidth = logicalWidth - 32f;
+ var contentHeight = 740f + bottomInset;
+
+ _scrollPosition = GUI.BeginScrollView(
+ scrollRect,
+ _scrollPosition,
+ new Rect(0, 0, logicalWidth, contentHeight),
+ false,
+ false
+ );
+
+ var y = 16f;
+ y = DrawAppSection(16f, y, contentWidth);
+ y = DrawPushSection(16f, y, contentWidth);
+ DrawLocationSection(16f, y, contentWidth);
+
+ GUI.EndScrollView();
+ GUI.matrix = previousMatrix;
+ }
+
+ private float DrawAppSection(float x, float y, float width)
+ {
+ DrawSectionHeader(x, y, "APP");
+ y += 24f;
+
+ var cardHeight = 52f;
+ GUI.Box(new Rect(x, y, width, cardHeight), GUIContent.none, _cardStyle);
+ DrawKeyValueRow(
+ x + 12f,
+ y + 14f,
+ width - 24f,
+ "App ID",
+ _oneSignalAppId,
+ IsConfigured ? _valueStyle : _warningValueStyle
+ );
+
+ return y + cardHeight + 24f;
+ }
+
+ private float DrawPushSection(float x, float y, float width)
+ {
+ DrawSectionHeader(x, y, "PUSH");
+ y += 24f;
+
+ var hasStatus = !string.IsNullOrEmpty(_pushStatus);
+ var cardHeight = hasStatus ? 280f : 252f;
+ GUI.Box(new Rect(x, y, width, cardHeight), GUIContent.none, _cardStyle);
+
+ var contentX = x + 12f;
+ var contentWidth = width - 24f;
+ var permission = _initialized
+ ? OneSignal.Notifications.Permission
+ ? "Granted"
+ : "Not granted"
+ : "Not initialized";
+ var pushId = _initialized ? FormatValue(OneSignal.User.PushSubscription.Id) : "-";
+
+ DrawKeyValueRow(
+ contentX,
+ y + 12f,
+ contentWidth,
+ "Permission",
+ permission,
+ _valueStyle
+ );
+ DrawDivider(contentX, y + 45f, contentWidth);
+ DrawKeyValueRow(contentX, y + 58f, contentWidth, "Push ID", pushId, _valueStyle);
+
+ if (GUI.Button(new Rect(contentX, y + 100f, contentWidth, 48f), "REQUEST PERMISSION", _buttonStyle))
+ RequestPushPermission();
+
+ if (GUI.Button(new Rect(contentX, y + 156f, contentWidth, 48f), "SEND TEST NOTIFICATION", _buttonStyle))
+ SendTestNotification();
+
+ if (hasStatus)
+ GUI.Label(new Rect(contentX, y + 212f, contentWidth, 56f), _pushStatus, _bodyStyle);
+
+ return y + cardHeight + 24f;
+ }
+
+ private void DrawLocationSection(float x, float y, float width)
+ {
+ DrawSectionHeader(x, y, "LOCATION MODULE");
+ y += 24f;
+
+ var cardHeight = 240f;
+ GUI.Box(new Rect(x, y, width, cardHeight), GUIContent.none, _cardStyle);
+
+ var contentX = x + 12f;
+ var contentWidth = width - 24f;
+ GUI.Label(
+ new Rect(contentX, y + 12f, contentWidth, 74f),
+ "This demo initializes OneSignal and requests notification permission only when you tap the button above. Native builds exclude the location module.",
+ _bodyStyle
+ );
+
+ GUI.Label(new Rect(contentX, y + 94f, contentWidth, 72f), _locationStatus, _bodyStyle);
+
+ if (
+ GUI.Button(
+ new Rect(contentX, y + 180f, contentWidth, 48f),
+ "TEST LOCATION REQUEST",
+ _outlineButtonStyle
+ )
+ )
+ TestLocationRequest();
+ }
+
+ private void DrawSectionHeader(float x, float y, string text) =>
+ GUI.Label(new Rect(x + 4f, y, 240f, 18f), text, _sectionHeaderStyle);
+
+ private void DrawKeyValueRow(
+ float x,
+ float y,
+ float width,
+ string label,
+ string value,
+ GUIStyle valueStyle
+ )
+ {
+ GUI.Label(new Rect(x, y, 92f, 22f), label, _labelStyle);
+ GUI.Label(new Rect(x + 100f, y, width - 100f, 44f), value, valueStyle);
+ }
+
+ private void DrawDivider(float x, float y, float width) =>
+ GUI.DrawTexture(new Rect(x, y, width, 1f), _dividerTexture);
+
+ private void EnsureStyles()
+ {
+ if (_bodyStyle != null)
+ return;
+
+ _cardTexture = MakeTexture(new Color32(255, 255, 255, 255));
+ _dividerTexture = MakeTexture(_dividerColor);
+ _primaryTexture = MakeTexture(_primaryColor);
+ _whiteTexture = MakeTexture(new Color32(255, 255, 255, 255));
+ _backgroundTexture = MakeTexture(_backgroundColor);
+
+ _headerTitleStyle = new GUIStyle(GUI.skin.label)
+ {
+ normal = { textColor = Color.white },
+ fontSize = 22,
+ fontStyle = FontStyle.Bold,
+ };
+ _headerSubtitleStyle = new GUIStyle(GUI.skin.label)
+ {
+ normal = { textColor = Color.white },
+ fontSize = 14,
+ };
+ _sectionHeaderStyle = new GUIStyle(GUI.skin.label)
+ {
+ normal = { textColor = _mutedTextColor },
+ fontSize = 12,
+ fontStyle = FontStyle.Bold,
+ };
+ _cardStyle = new GUIStyle(GUI.skin.box)
+ {
+ normal = { background = _cardTexture },
+ border = new RectOffset(12, 12, 12, 12),
+ padding = new RectOffset(0, 0, 0, 0),
+ };
+ _labelStyle = new GUIStyle(GUI.skin.label)
+ {
+ normal = { textColor = _labelColor },
+ fontSize = 14,
+ fontStyle = FontStyle.Bold,
+ };
+ _valueStyle = new GUIStyle(GUI.skin.label)
+ {
+ normal = { textColor = _valueColor },
+ fontSize = 13,
+ alignment = TextAnchor.UpperRight,
+ wordWrap = true,
+ };
+ _warningValueStyle = new GUIStyle(_valueStyle)
+ {
+ normal = { textColor = _warningColor },
+ };
+ _bodyStyle = new GUIStyle(GUI.skin.label)
+ {
+ normal = { textColor = _mutedTextColor },
+ fontSize = 14,
+ wordWrap = true,
+ };
+ _buttonStyle = new GUIStyle(GUI.skin.button)
+ {
+ normal = { background = _primaryTexture, textColor = Color.white },
+ active = { background = _primaryTexture, textColor = Color.white },
+ hover = { background = _primaryTexture, textColor = Color.white },
+ fontSize = 14,
+ fontStyle = FontStyle.Bold,
+ alignment = TextAnchor.MiddleCenter,
+ };
+ _outlineButtonStyle = new GUIStyle(GUI.skin.button)
+ {
+ normal = { background = _whiteTexture, textColor = _primaryColor },
+ active = { background = _whiteTexture, textColor = _primaryColor },
+ hover = { background = _whiteTexture, textColor = _primaryColor },
+ fontSize = 14,
+ fontStyle = FontStyle.Bold,
+ alignment = TextAnchor.MiddleCenter,
+ };
+ }
+
+ private async void RequestPushPermission()
+ {
+ if (!_initialized)
+ {
+ return;
+ }
+
+ try
+ {
+ await OneSignal.Notifications.RequestPermissionAsync(false);
+ }
+ catch (System.Exception exception)
+ {
+ Debug.LogError($"[NoLocationDemo] Push permission request failed: {exception.Message}");
+ }
+ }
+
+ private async void SendTestNotification()
+ {
+ if (!_initialized || !IsConfigured)
+ {
+ _pushStatus = "Set ONESIGNAL_APP_ID before sending a test push.";
+ return;
+ }
+
+ if (!OneSignal.Notifications.Permission)
+ {
+ _pushStatus = "Request notification permission before sending a test push.";
+ return;
+ }
+
+ var pushSubscriptionId = OneSignal.User.PushSubscription.Id;
+ if (string.IsNullOrWhiteSpace(pushSubscriptionId))
+ {
+ _pushStatus = "Allow notifications, then wait for a push ID.";
+ return;
+ }
+
+ _pushStatus = "Sending test notification...";
+
+ try
+ {
+ var sent = await PostTestNotification(pushSubscriptionId);
+ _pushStatus = sent
+ ? "Test notification requested."
+ : "Send failed. Verify the OneSignal App ID.";
+ }
+ catch (Exception exception)
+ {
+ _pushStatus = $"Send failed: {exception.Message}";
+ }
+ }
+
+ private async Task PostTestNotification(string pushSubscriptionId)
+ {
+ var payload =
+ "{"
+ + $"\"app_id\":\"{_oneSignalAppId}\","
+ + $"\"include_subscription_ids\":[\"{pushSubscriptionId}\"],"
+ + "\"headings\":{\"en\":\"OneSignal No-Location Demo\"},"
+ + "\"contents\":{\"en\":\"This test push was sent without linking the location module.\"}"
+ + "}";
+
+ using var request = new UnityWebRequest(
+ "https://onesignal.com/api/v1/notifications",
+ UnityWebRequest.kHttpVerbPOST
+ );
+ request.uploadHandler = new UploadHandlerRaw(Encoding.UTF8.GetBytes(payload));
+ request.downloadHandler = new DownloadHandlerBuffer();
+ request.SetRequestHeader("Content-Type", "application/json");
+ request.SetRequestHeader("Accept", "application/vnd.onesignal.v1+json");
+
+ var completion = new TaskCompletionSource();
+ var operation = request.SendWebRequest();
+ operation.completed += _ => completion.TrySetResult(true);
+ await completion.Task;
+
+ return request.result == UnityWebRequest.Result.Success;
+ }
+
+ private void TestLocationRequest()
+ {
+ if (!_initialized)
+ {
+ _locationStatus = "Initialize OneSignal before testing location.";
+ return;
+ }
+
+ try
+ {
+ OneSignal.Location.RequestPermission();
+ _locationStatus = "Location request completed without linking the location module.";
+ }
+ catch (System.Exception exception)
+ {
+ _locationStatus = $"Location request failed: {exception.Message}";
+ }
+ }
+
+ private bool IsConfigured =>
+ !string.IsNullOrWhiteSpace(_oneSignalAppId)
+ && !_oneSignalAppId.StartsWith("YOUR-");
+
+ private static string FormatValue(string value) =>
+ string.IsNullOrWhiteSpace(value) ? "-" : value;
+
+ private static Rect ScaleRect(Rect rect, float scale) =>
+ new Rect(rect.x * scale, rect.y * scale, rect.width * scale, rect.height * scale);
+
+ private static Texture2D MakeTexture(Color color)
+ {
+ var texture = new Texture2D(1, 1);
+ texture.SetPixel(0, 0, color);
+ texture.Apply();
+ return texture;
+ }
+}
diff --git a/examples/demo-no-location/Assets/Scripts/NoLocationDemo.cs.meta b/examples/demo-no-location/Assets/Scripts/NoLocationDemo.cs.meta
new file mode 100644
index 00000000..3457a5b9
--- /dev/null
+++ b/examples/demo-no-location/Assets/Scripts/NoLocationDemo.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: 4e1e7c96909144afa42b3fb595db18f0
+MonoImporter:
+ externalObjects: {}
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {instanceID: 0}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/examples/demo-no-location/Packages/manifest.json b/examples/demo-no-location/Packages/manifest.json
new file mode 100644
index 00000000..7012c1bb
--- /dev/null
+++ b/examples/demo-no-location/Packages/manifest.json
@@ -0,0 +1,11 @@
+{
+ "dependencies": {
+ "com.onesignal.unity.android": "file:../../../com.onesignal.unity.android",
+ "com.onesignal.unity.core": "file:../../../com.onesignal.unity.core",
+ "com.onesignal.unity.ios": "file:../../../com.onesignal.unity.ios",
+ "com.unity.modules.androidjni": "1.0.0",
+ "com.unity.modules.imgui": "1.0.0",
+ "com.unity.modules.jsonserialize": "1.0.0",
+ "com.unity.modules.unitywebrequest": "1.0.0"
+ }
+}
diff --git a/examples/demo-no-location/Packages/packages-lock.json b/examples/demo-no-location/Packages/packages-lock.json
new file mode 100644
index 00000000..2f650a2c
--- /dev/null
+++ b/examples/demo-no-location/Packages/packages-lock.json
@@ -0,0 +1,50 @@
+{
+ "dependencies": {
+ "com.onesignal.unity.android": {
+ "version": "file:../../../com.onesignal.unity.android",
+ "depth": 0,
+ "source": "local",
+ "dependencies": {
+ "com.onesignal.unity.core": "5.2.11"
+ }
+ },
+ "com.onesignal.unity.core": {
+ "version": "file:../../../com.onesignal.unity.core",
+ "depth": 0,
+ "source": "local",
+ "dependencies": {}
+ },
+ "com.onesignal.unity.ios": {
+ "version": "file:../../../com.onesignal.unity.ios",
+ "depth": 0,
+ "source": "local",
+ "dependencies": {
+ "com.onesignal.unity.core": "5.2.11"
+ }
+ },
+ "com.unity.modules.androidjni": {
+ "version": "1.0.0",
+ "depth": 0,
+ "source": "builtin",
+ "dependencies": {}
+ },
+ "com.unity.modules.imgui": {
+ "version": "1.0.0",
+ "depth": 0,
+ "source": "builtin",
+ "dependencies": {}
+ },
+ "com.unity.modules.jsonserialize": {
+ "version": "1.0.0",
+ "depth": 0,
+ "source": "builtin",
+ "dependencies": {}
+ },
+ "com.unity.modules.unitywebrequest": {
+ "version": "1.0.0",
+ "depth": 0,
+ "source": "builtin",
+ "dependencies": {}
+ }
+ }
+}
diff --git a/examples/demo-no-location/ProjectSettings/AndroidResolverDependencies.xml b/examples/demo-no-location/ProjectSettings/AndroidResolverDependencies.xml
new file mode 100644
index 00000000..e50579a3
--- /dev/null
+++ b/examples/demo-no-location/ProjectSettings/AndroidResolverDependencies.xml
@@ -0,0 +1,25 @@
+
+
+ com.onesignal:core:5.9.5
+ com.onesignal:notifications:5.9.5
+ com.onesignal:in-app-messages:5.9.5
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/examples/demo-no-location/ProjectSettings/EditorBuildSettings.asset b/examples/demo-no-location/ProjectSettings/EditorBuildSettings.asset
new file mode 100644
index 00000000..22a68559
--- /dev/null
+++ b/examples/demo-no-location/ProjectSettings/EditorBuildSettings.asset
@@ -0,0 +1,11 @@
+%YAML 1.1
+%TAG !u! tag:unity3d.com,2011:
+--- !u!1045 &1
+EditorBuildSettings:
+ m_ObjectHideFlags: 0
+ serializedVersion: 2
+ m_Scenes:
+ - enabled: 1
+ path: Assets/Scenes/Main.unity
+ guid: 3d514e5ac1634c1b8bcf595734736969
+ m_configObjects: {}
diff --git a/examples/demo-no-location/ProjectSettings/OneSignalSettings.json b/examples/demo-no-location/ProjectSettings/OneSignalSettings.json
new file mode 100644
index 00000000..336ed657
--- /dev/null
+++ b/examples/demo-no-location/ProjectSettings/OneSignalSettings.json
@@ -0,0 +1,3 @@
+{
+ "disableLocation": true
+}
diff --git a/examples/demo-no-location/ProjectSettings/ProjectSettings.asset b/examples/demo-no-location/ProjectSettings/ProjectSettings.asset
new file mode 100644
index 00000000..153beef1
--- /dev/null
+++ b/examples/demo-no-location/ProjectSettings/ProjectSettings.asset
@@ -0,0 +1,896 @@
+%YAML 1.1
+%TAG !u! tag:unity3d.com,2011:
+--- !u!129 &1
+PlayerSettings:
+ m_ObjectHideFlags: 0
+ serializedVersion: 28
+ productGUID: 8c68141ccf5e4fdf8af18b27d8f8cf22
+ AndroidProfiler: 0
+ AndroidFilterTouchesWhenObscured: 0
+ AndroidEnableSustainedPerformanceMode: 0
+ defaultScreenOrientation: 0
+ targetDevice: 2
+ useOnDemandResources: 0
+ accelerometerFrequency: 60
+ companyName: OneSignal
+ productName: OneSignal No-Location Demo
+ defaultCursor: {fileID: 0}
+ cursorHotspot: {x: 0, y: 0}
+ m_SplashScreenBackgroundColor: {r: 0.12941177, g: 0.12941177, b: 0.12941177, a: 1}
+ m_ShowUnitySplashScreen: 1
+ m_ShowUnitySplashLogo: 1
+ m_SplashScreenOverlayOpacity: 1
+ m_SplashScreenAnimation: 1
+ m_SplashScreenLogoStyle: 1
+ m_SplashScreenDrawMode: 0
+ m_SplashScreenBackgroundAnimationZoom: 1
+ m_SplashScreenLogoAnimationZoom: 1
+ m_SplashScreenBackgroundLandscapeAspect: 1
+ m_SplashScreenBackgroundPortraitAspect: 1
+ m_SplashScreenBackgroundLandscapeUvs:
+ serializedVersion: 2
+ x: 0
+ y: 0
+ width: 1
+ height: 1
+ m_SplashScreenBackgroundPortraitUvs:
+ serializedVersion: 2
+ x: 0
+ y: 0
+ width: 1
+ height: 1
+ m_SplashScreenLogos: []
+ m_VirtualRealitySplashScreen: {fileID: 0}
+ defaultScreenWidth: 1920
+ defaultScreenHeight: 1080
+ defaultScreenWidthWeb: 960
+ defaultScreenHeightWeb: 600
+ m_StereoRenderingPath: 0
+ m_ActiveColorSpace: 0
+ unsupportedMSAAFallback: 0
+ m_SpriteBatchMaxVertexCount: 65535
+ m_SpriteBatchVertexThreshold: 300
+ m_MTRendering: 1
+ mipStripping: 0
+ numberOfMipsStripped: 0
+ numberOfMipsStrippedPerMipmapLimitGroup: {}
+ m_StackTraceTypes: 010000000100000001000000010000000100000001000000
+ iosShowActivityIndicatorOnLoading: -1
+ androidShowActivityIndicatorOnLoading: -1
+ iosUseCustomAppBackgroundBehavior: 0
+ allowedAutorotateToPortrait: 1
+ allowedAutorotateToPortraitUpsideDown: 1
+ allowedAutorotateToLandscapeRight: 1
+ allowedAutorotateToLandscapeLeft: 1
+ useOSAutorotation: 1
+ use32BitDisplayBuffer: 1
+ preserveFramebufferAlpha: 0
+ disableDepthAndStencilBuffers: 0
+ androidStartInFullscreen: 0
+ androidRenderOutsideSafeArea: 0
+ androidUseSwappy: 1
+ androidDisplayOptions: 1
+ androidBlitType: 0
+ androidResizeableActivity: 1
+ androidDefaultWindowWidth: 1920
+ androidDefaultWindowHeight: 1080
+ androidMinimumWindowWidth: 400
+ androidMinimumWindowHeight: 300
+ androidFullscreenMode: 1
+ androidAutoRotationBehavior: 1
+ androidPredictiveBackSupport: 1
+ androidApplicationEntry: 1
+ defaultIsNativeResolution: 1
+ macRetinaSupport: 1
+ runInBackground: 0
+ muteOtherAudioSources: 0
+ Prepare IOS For Recording: 0
+ Force IOS Speakers When Recording: 0
+ audioSpatialExperience: 0
+ deferSystemGesturesMode: 0
+ hideHomeButton: 0
+ submitAnalytics: 1
+ usePlayerLog: 1
+ dedicatedServerOptimizations: 1
+ bakeCollisionMeshes: 0
+ forceSingleInstance: 0
+ useFlipModelSwapchain: 1
+ resizableWindow: 0
+ useMacAppStoreValidation: 0
+ macAppStoreCategory: public.app-category.games
+ gpuSkinning: 0
+ meshDeformation: 0
+ xboxPIXTextureCapture: 0
+ xboxEnableAvatar: 0
+ xboxEnableKinect: 0
+ xboxEnableKinectAutoTracking: 0
+ xboxEnableFitness: 0
+ visibleInBackground: 1
+ allowFullscreenSwitch: 1
+ fullscreenMode: 1
+ xboxSpeechDB: 0
+ xboxEnableHeadOrientation: 0
+ xboxEnableGuest: 0
+ xboxEnablePIXSampling: 0
+ metalFramebufferOnly: 0
+ metalUseMetalDisplayLink: 0
+ xboxOneResolution: 0
+ xboxOneSResolution: 0
+ xboxOneXResolution: 3
+ xboxOneMonoLoggingLevel: 0
+ xboxOneLoggingLevel: 1
+ xboxOneDisableEsram: 0
+ xboxOneEnableTypeOptimization: 0
+ xboxOnePresentImmediateThreshold: 0
+ switchQueueCommandMemory: 1048576
+ switchQueueControlMemory: 16384
+ switchQueueComputeMemory: 262144
+ switchNVNShaderPoolsGranularity: 33554432
+ switchNVNDefaultPoolsGranularity: 16777216
+ switchNVNOtherPoolsGranularity: 16777216
+ switchGpuScratchPoolGranularity: 2097152
+ switchAllowGpuScratchShrinking: 0
+ switchNVNMaxPublicTextureIDCount: 0
+ switchNVNMaxPublicSamplerIDCount: 0
+ switchMaxWorkerMultiple: 8
+ switchNVNGraphicsFirmwareMemory: 32
+ switchGraphicsJobsSyncAfterKick: 1
+ vulkanNumSwapchainBuffers: 3
+ vulkanEnableSetSRGBWrite: 0
+ vulkanEnablePreTransform: 0
+ vulkanEnableLateAcquireNextImage: 0
+ vulkanEnableCommandBufferRecycling: 1
+ loadStoreDebugModeEnabled: 0
+ visionOSBundleVersion: 1.0
+ tvOSBundleVersion: 1.0
+ bundleVersion: 5.2.9
+ preloadedAssets: []
+ metroInputSource: 0
+ wsaTransparentSwapchain: 0
+ xboxOneDisableKinectGpuReservation: 1
+ xboxOneEnable7thCore: 1
+ vrSettings:
+ enable360StereoCapture: 0
+ enableFrameTimingStats: 0
+ enableOpenGLProfilerGPURecorders: 1
+ allowHDRDisplaySupport: 0
+ useHDRDisplay: 0
+ hdrBitDepth: 0
+ m_ColorGamuts: 00000000
+ targetPixelDensity: 30
+ resolutionScalingMode: 0
+ resetResolutionOnWindowResize: 0
+ androidSupportedAspectRatio: 1
+ androidMaxAspectRatio: 2.4
+ androidMinAspectRatio: 1
+ applicationIdentifier:
+ Android: com.onesignal.example
+ iPhone: com.onesignal.example
+ buildNumber:
+ Standalone: 0
+ VisionOS: 0
+ iPhone: 1
+ tvOS: 0
+ overrideDefaultApplicationIdentifier: 1
+ AndroidBundleVersionCode: 1
+ AndroidMinSdkVersion: 25
+ AndroidTargetSdkVersion: 34
+ AndroidPreferredInstallLocation: 1
+ AndroidPreferredDataLocation: 1
+ aotOptions:
+ stripEngineCode: 1
+ iPhoneStrippingLevel: 0
+ iPhoneScriptCallOptimization: 0
+ ForceInternetPermission: 0
+ ForceSDCardPermission: 0
+ CreateWallpaper: 0
+ androidSplitApplicationBinary: 0
+ keepLoadedShadersAlive: 0
+ StripUnusedMeshComponents: 0
+ strictShaderVariantMatching: 0
+ VertexChannelCompressionMask: 4054
+ iPhoneSdkVersion: 989
+ iOSSimulatorArchitecture: 2
+ iOSTargetOSVersionString: 15.0
+ tvOSSdkVersion: 0
+ tvOSSimulatorArchitecture: 0
+ tvOSRequireExtendedGameController: 0
+ tvOSTargetOSVersionString: 15.0
+ VisionOSSdkVersion: 0
+ VisionOSTargetOSVersionString: 1.0
+ uIPrerenderedIcon: 0
+ uIRequiresPersistentWiFi: 0
+ uIRequiresFullScreen: 1
+ uIStatusBarHidden: 1
+ uIExitOnSuspend: 0
+ uIStatusBarStyle: 0
+ appleTVSplashScreen: {fileID: 0}
+ appleTVSplashScreen2x: {fileID: 0}
+ tvOSSmallIconLayers: []
+ tvOSSmallIconLayers2x: []
+ tvOSLargeIconLayers: []
+ tvOSLargeIconLayers2x: []
+ tvOSTopShelfImageLayers: []
+ tvOSTopShelfImageLayers2x: []
+ tvOSTopShelfImageWideLayers: []
+ tvOSTopShelfImageWideLayers2x: []
+ iOSLaunchScreenType: 0
+ iOSLaunchScreenPortrait: {fileID: 0}
+ iOSLaunchScreenLandscape: {fileID: 0}
+ iOSLaunchScreenBackgroundColor:
+ serializedVersion: 2
+ rgba: 0
+ iOSLaunchScreenFillPct: 100
+ iOSLaunchScreenSize: 100
+ iOSLaunchScreeniPadType: 0
+ iOSLaunchScreeniPadImage: {fileID: 0}
+ iOSLaunchScreeniPadBackgroundColor:
+ serializedVersion: 2
+ rgba: 0
+ iOSLaunchScreeniPadFillPct: 100
+ iOSLaunchScreeniPadSize: 100
+ iOSLaunchScreenCustomStoryboardPath:
+ iOSLaunchScreeniPadCustomStoryboardPath:
+ iOSDeviceRequirements: []
+ iOSURLSchemes: []
+ macOSURLSchemes: []
+ iOSBackgroundModes: 0
+ iOSMetalForceHardShadows: 0
+ metalEditorSupport: 1
+ metalAPIValidation: 1
+ metalCompileShaderBinary: 0
+ iOSRenderExtraFrameOnPause: 1
+ iosCopyPluginsCodeInsteadOfSymlink: 0
+ appleDeveloperTeamID:
+ iOSManualSigningProvisioningProfileID:
+ tvOSManualSigningProvisioningProfileID:
+ VisionOSManualSigningProvisioningProfileID:
+ iOSManualSigningProvisioningProfileType: 0
+ tvOSManualSigningProvisioningProfileType: 0
+ VisionOSManualSigningProvisioningProfileType: 0
+ appleEnableAutomaticSigning: 0
+ iOSRequireARKit: 0
+ iOSAutomaticallyDetectAndAddCapabilities: 1
+ appleEnableProMotion: 0
+ shaderPrecisionModel: 0
+ clonedFromGUID: 00000000000000000000000000000000
+ templatePackageId:
+ templateDefaultScene:
+ useCustomMainManifest: 0
+ useCustomLauncherManifest: 0
+ useCustomMainGradleTemplate: 1
+ useCustomLauncherGradleManifest: 0
+ useCustomBaseGradleTemplate: 0
+ useCustomGradlePropertiesTemplate: 1
+ useCustomGradleSettingsTemplate: 1
+ useCustomProguardFile: 1
+ AndroidTargetArchitectures: 2
+ AndroidAllowedArchitectures: -1
+ AndroidSplashScreenScale: 0
+ androidSplashScreen: {fileID: 0}
+ AndroidKeystoreName:
+ AndroidKeyaliasName:
+ AndroidEnableArmv9SecurityFeatures: 0
+ AndroidEnableArm64MTE: 0
+ AndroidBuildApkPerCpuArchitecture: 0
+ AndroidTVCompatibility: 0
+ AndroidIsGame: 1
+ androidAppCategory: 3
+ useAndroidAppCategory: 1
+ androidAppCategoryOther:
+ AndroidEnableTango: 0
+ androidEnableBanner: 1
+ androidUseLowAccuracyLocation: 0
+ androidUseCustomKeystore: 0
+ m_AndroidBanners:
+ - width: 320
+ height: 180
+ banner: {fileID: 0}
+ androidGamepadSupportLevel: 0
+ AndroidMinifyRelease: 1
+ AndroidMinifyDebug: 0
+ AndroidValidateAppBundleSize: 1
+ AndroidAppBundleSizeToValidate: 200
+ AndroidReportGooglePlayAppDependencies: 1
+ androidSymbolsSizeThreshold: 800
+ m_BuildTargetIcons: []
+ m_BuildTargetPlatformIcons:
+ - m_BuildTarget: iPhone
+ m_Icons:
+ - m_Textures: []
+ m_Width: 180
+ m_Height: 180
+ m_Kind: 0
+ m_SubKind: iPhone
+ - m_Textures: []
+ m_Width: 120
+ m_Height: 120
+ m_Kind: 0
+ m_SubKind: iPhone
+ - m_Textures: []
+ m_Width: 167
+ m_Height: 167
+ m_Kind: 0
+ m_SubKind: iPad
+ - m_Textures: []
+ m_Width: 152
+ m_Height: 152
+ m_Kind: 0
+ m_SubKind: iPad
+ - m_Textures: []
+ m_Width: 76
+ m_Height: 76
+ m_Kind: 0
+ m_SubKind: iPad
+ - m_Textures: []
+ m_Width: 120
+ m_Height: 120
+ m_Kind: 3
+ m_SubKind: iPhone
+ - m_Textures: []
+ m_Width: 80
+ m_Height: 80
+ m_Kind: 3
+ m_SubKind: iPhone
+ - m_Textures: []
+ m_Width: 80
+ m_Height: 80
+ m_Kind: 3
+ m_SubKind: iPad
+ - m_Textures: []
+ m_Width: 40
+ m_Height: 40
+ m_Kind: 3
+ m_SubKind: iPad
+ - m_Textures: []
+ m_Width: 87
+ m_Height: 87
+ m_Kind: 1
+ m_SubKind: iPhone
+ - m_Textures: []
+ m_Width: 58
+ m_Height: 58
+ m_Kind: 1
+ m_SubKind: iPhone
+ - m_Textures: []
+ m_Width: 29
+ m_Height: 29
+ m_Kind: 1
+ m_SubKind: iPhone
+ - m_Textures: []
+ m_Width: 58
+ m_Height: 58
+ m_Kind: 1
+ m_SubKind: iPad
+ - m_Textures: []
+ m_Width: 29
+ m_Height: 29
+ m_Kind: 1
+ m_SubKind: iPad
+ - m_Textures: []
+ m_Width: 60
+ m_Height: 60
+ m_Kind: 2
+ m_SubKind: iPhone
+ - m_Textures: []
+ m_Width: 40
+ m_Height: 40
+ m_Kind: 2
+ m_SubKind: iPhone
+ - m_Textures: []
+ m_Width: 40
+ m_Height: 40
+ m_Kind: 2
+ m_SubKind: iPad
+ - m_Textures: []
+ m_Width: 20
+ m_Height: 20
+ m_Kind: 2
+ m_SubKind: iPad
+ - m_Textures: []
+ m_Width: 1024
+ m_Height: 1024
+ m_Kind: 4
+ m_SubKind: App Store
+ - m_BuildTarget: Android
+ m_Icons:
+ - m_Textures: []
+ m_Width: 432
+ m_Height: 432
+ m_Kind: 2
+ m_SubKind:
+ - m_Textures: []
+ m_Width: 324
+ m_Height: 324
+ m_Kind: 2
+ m_SubKind:
+ - m_Textures: []
+ m_Width: 216
+ m_Height: 216
+ m_Kind: 2
+ m_SubKind:
+ - m_Textures: []
+ m_Width: 162
+ m_Height: 162
+ m_Kind: 2
+ m_SubKind:
+ - m_Textures: []
+ m_Width: 108
+ m_Height: 108
+ m_Kind: 2
+ m_SubKind:
+ - m_Textures: []
+ m_Width: 81
+ m_Height: 81
+ m_Kind: 2
+ m_SubKind:
+ - m_Textures: []
+ m_Width: 192
+ m_Height: 192
+ m_Kind: 1
+ m_SubKind:
+ - m_Textures: []
+ m_Width: 144
+ m_Height: 144
+ m_Kind: 1
+ m_SubKind:
+ - m_Textures: []
+ m_Width: 96
+ m_Height: 96
+ m_Kind: 1
+ m_SubKind:
+ - m_Textures: []
+ m_Width: 72
+ m_Height: 72
+ m_Kind: 1
+ m_SubKind:
+ - m_Textures: []
+ m_Width: 48
+ m_Height: 48
+ m_Kind: 1
+ m_SubKind:
+ - m_Textures: []
+ m_Width: 36
+ m_Height: 36
+ m_Kind: 1
+ m_SubKind:
+ - m_Textures: []
+ m_Width: 192
+ m_Height: 192
+ m_Kind: 0
+ m_SubKind:
+ - m_Textures: []
+ m_Width: 144
+ m_Height: 144
+ m_Kind: 0
+ m_SubKind:
+ - m_Textures: []
+ m_Width: 96
+ m_Height: 96
+ m_Kind: 0
+ m_SubKind:
+ - m_Textures: []
+ m_Width: 72
+ m_Height: 72
+ m_Kind: 0
+ m_SubKind:
+ - m_Textures: []
+ m_Width: 48
+ m_Height: 48
+ m_Kind: 0
+ m_SubKind:
+ - m_Textures: []
+ m_Width: 36
+ m_Height: 36
+ m_Kind: 0
+ m_SubKind:
+ m_BuildTargetBatching: []
+ m_BuildTargetShaderSettings: []
+ m_BuildTargetGraphicsJobs: []
+ m_BuildTargetGraphicsJobMode: []
+ m_BuildTargetGraphicsAPIs: []
+ m_BuildTargetVRSettings: []
+ m_DefaultShaderChunkSizeInMB: 16
+ m_DefaultShaderChunkCount: 0
+ openGLRequireES31: 0
+ openGLRequireES31AEP: 0
+ openGLRequireES32: 0
+ m_TemplateCustomTags: {}
+ mobileMTRendering:
+ Android: 1
+ VisionOS: 1
+ iPhone: 1
+ tvOS: 1
+ m_BuildTargetGroupLightmapEncodingQuality: []
+ m_BuildTargetGroupHDRCubemapEncodingQuality: []
+ m_BuildTargetGroupLightmapSettings: []
+ m_BuildTargetGroupLoadStoreDebugModeSettings: []
+ m_BuildTargetNormalMapEncoding: []
+ m_BuildTargetDefaultTextureCompressionFormat: []
+ playModeTestRunnerEnabled: 0
+ runPlayModeTestAsEditModeTest: 0
+ actionOnDotNetUnhandledException: 1
+ editorGfxJobOverride: 1
+ enableInternalProfiler: 0
+ logObjCUncaughtExceptions: 1
+ enableCrashReportAPI: 0
+ cameraUsageDescription:
+ locationUsageDescription:
+ microphoneUsageDescription:
+ bluetoothUsageDescription:
+ macOSTargetOSVersion: 12.0
+ switchNMETAOverride:
+ switchNetLibKey:
+ switchSocketMemoryPoolSize: 6144
+ switchSocketAllocatorPoolSize: 128
+ switchSocketConcurrencyLimit: 14
+ switchScreenResolutionBehavior: 2
+ switchUseCPUProfiler: 0
+ switchEnableFileSystemTrace: 0
+ switchLTOSetting: 0
+ switchApplicationID: 0x01004b9000490000
+ switchNSODependencies:
+ switchCompilerFlags:
+ switchTitleNames_0:
+ switchTitleNames_1:
+ switchTitleNames_2:
+ switchTitleNames_3:
+ switchTitleNames_4:
+ switchTitleNames_5:
+ switchTitleNames_6:
+ switchTitleNames_7:
+ switchTitleNames_8:
+ switchTitleNames_9:
+ switchTitleNames_10:
+ switchTitleNames_11:
+ switchTitleNames_12:
+ switchTitleNames_13:
+ switchTitleNames_14:
+ switchTitleNames_15:
+ switchPublisherNames_0:
+ switchPublisherNames_1:
+ switchPublisherNames_2:
+ switchPublisherNames_3:
+ switchPublisherNames_4:
+ switchPublisherNames_5:
+ switchPublisherNames_6:
+ switchPublisherNames_7:
+ switchPublisherNames_8:
+ switchPublisherNames_9:
+ switchPublisherNames_10:
+ switchPublisherNames_11:
+ switchPublisherNames_12:
+ switchPublisherNames_13:
+ switchPublisherNames_14:
+ switchPublisherNames_15:
+ switchIcons_0: {fileID: 0}
+ switchIcons_1: {fileID: 0}
+ switchIcons_2: {fileID: 0}
+ switchIcons_3: {fileID: 0}
+ switchIcons_4: {fileID: 0}
+ switchIcons_5: {fileID: 0}
+ switchIcons_6: {fileID: 0}
+ switchIcons_7: {fileID: 0}
+ switchIcons_8: {fileID: 0}
+ switchIcons_9: {fileID: 0}
+ switchIcons_10: {fileID: 0}
+ switchIcons_11: {fileID: 0}
+ switchIcons_12: {fileID: 0}
+ switchIcons_13: {fileID: 0}
+ switchIcons_14: {fileID: 0}
+ switchIcons_15: {fileID: 0}
+ switchSmallIcons_0: {fileID: 0}
+ switchSmallIcons_1: {fileID: 0}
+ switchSmallIcons_2: {fileID: 0}
+ switchSmallIcons_3: {fileID: 0}
+ switchSmallIcons_4: {fileID: 0}
+ switchSmallIcons_5: {fileID: 0}
+ switchSmallIcons_6: {fileID: 0}
+ switchSmallIcons_7: {fileID: 0}
+ switchSmallIcons_8: {fileID: 0}
+ switchSmallIcons_9: {fileID: 0}
+ switchSmallIcons_10: {fileID: 0}
+ switchSmallIcons_11: {fileID: 0}
+ switchSmallIcons_12: {fileID: 0}
+ switchSmallIcons_13: {fileID: 0}
+ switchSmallIcons_14: {fileID: 0}
+ switchSmallIcons_15: {fileID: 0}
+ switchManualHTML:
+ switchAccessibleURLs:
+ switchLegalInformation:
+ switchMainThreadStackSize: 1048576
+ switchPresenceGroupId:
+ switchLogoHandling: 0
+ switchReleaseVersion: 0
+ switchDisplayVersion: 1.0.0
+ switchStartupUserAccount: 0
+ switchSupportedLanguagesMask: 0
+ switchLogoType: 0
+ switchApplicationErrorCodeCategory:
+ switchUserAccountSaveDataSize: 0
+ switchUserAccountSaveDataJournalSize: 0
+ switchApplicationAttribute: 0
+ switchCardSpecSize: -1
+ switchCardSpecClock: -1
+ switchRatingsMask: 0
+ switchRatingsInt_0: 0
+ switchRatingsInt_1: 0
+ switchRatingsInt_2: 0
+ switchRatingsInt_3: 0
+ switchRatingsInt_4: 0
+ switchRatingsInt_5: 0
+ switchRatingsInt_6: 0
+ switchRatingsInt_7: 0
+ switchRatingsInt_8: 0
+ switchRatingsInt_9: 0
+ switchRatingsInt_10: 0
+ switchRatingsInt_11: 0
+ switchRatingsInt_12: 0
+ switchLocalCommunicationIds_0:
+ switchLocalCommunicationIds_1:
+ switchLocalCommunicationIds_2:
+ switchLocalCommunicationIds_3:
+ switchLocalCommunicationIds_4:
+ switchLocalCommunicationIds_5:
+ switchLocalCommunicationIds_6:
+ switchLocalCommunicationIds_7:
+ switchParentalControl: 0
+ switchAllowsScreenshot: 1
+ switchAllowsVideoCapturing: 1
+ switchAllowsRuntimeAddOnContentInstall: 0
+ switchDataLossConfirmation: 0
+ switchUserAccountLockEnabled: 0
+ switchSystemResourceMemory: 16777216
+ switchSupportedNpadStyles: 22
+ switchNativeFsCacheSize: 32
+ switchIsHoldTypeHorizontal: 1
+ switchSupportedNpadCount: 8
+ switchEnableTouchScreen: 1
+ switchSocketConfigEnabled: 0
+ switchTcpInitialSendBufferSize: 32
+ switchTcpInitialReceiveBufferSize: 64
+ switchTcpAutoSendBufferSizeMax: 256
+ switchTcpAutoReceiveBufferSizeMax: 256
+ switchUdpSendBufferSize: 9
+ switchUdpReceiveBufferSize: 42
+ switchSocketBufferEfficiency: 4
+ switchSocketInitializeEnabled: 1
+ switchNetworkInterfaceManagerInitializeEnabled: 1
+ switchDisableHTCSPlayerConnection: 0
+ switchUseNewStyleFilepaths: 1
+ switchUseLegacyFmodPriorities: 0
+ switchUseMicroSleepForYield: 1
+ switchEnableRamDiskSupport: 0
+ switchMicroSleepForYieldTime: 25
+ switchRamDiskSpaceSize: 12
+ switchUpgradedPlayerSettingsToNMETA: 0
+ ps4NPAgeRating: 12
+ ps4NPTitleSecret:
+ ps4NPTrophyPackPath:
+ ps4ParentalLevel: 11
+ ps4ContentID: ED1633-NPXX51362_00-0000000000000000
+ ps4Category: 0
+ ps4MasterVersion: 01.00
+ ps4AppVersion: 01.00
+ ps4AppType: 0
+ ps4ParamSfxPath:
+ ps4VideoOutPixelFormat: 0
+ ps4VideoOutInitialWidth: 1920
+ ps4VideoOutBaseModeInitialWidth: 1920
+ ps4VideoOutReprojectionRate: 60
+ ps4PronunciationXMLPath:
+ ps4PronunciationSIGPath:
+ ps4BackgroundImagePath:
+ ps4StartupImagePath:
+ ps4StartupImagesFolder:
+ ps4IconImagesFolder:
+ ps4SaveDataImagePath:
+ ps4SdkOverride:
+ ps4BGMPath:
+ ps4ShareFilePath:
+ ps4ShareOverlayImagePath:
+ ps4PrivacyGuardImagePath:
+ ps4ExtraSceSysFile:
+ ps4NPtitleDatPath:
+ ps4RemotePlayKeyAssignment: -1
+ ps4RemotePlayKeyMappingDir:
+ ps4PlayTogetherPlayerCount: 0
+ ps4EnterButtonAssignment: 2
+ ps4ApplicationParam1: 0
+ ps4ApplicationParam2: 0
+ ps4ApplicationParam3: 0
+ ps4ApplicationParam4: 0
+ ps4DownloadDataSize: 0
+ ps4GarlicHeapSize: 2048
+ ps4ProGarlicHeapSize: 2560
+ playerPrefsMaxSize: 32768
+ ps4Passcode: Ti337x0jGPK6DloiDZUkKLLmVBjcfPCk
+ ps4pnSessions: 1
+ ps4pnPresence: 1
+ ps4pnFriends: 1
+ ps4pnGameCustomData: 1
+ playerPrefsSupport: 0
+ enableApplicationExit: 0
+ resetTempFolder: 1
+ restrictedAudioUsageRights: 0
+ ps4UseResolutionFallback: 0
+ ps4ReprojectionSupport: 0
+ ps4UseAudio3dBackend: 0
+ ps4UseLowGarlicFragmentationMode: 1
+ ps4SocialScreenEnabled: 0
+ ps4ScriptOptimizationLevel: 2
+ ps4Audio3dVirtualSpeakerCount: 14
+ ps4attribCpuUsage: 0
+ ps4PatchPkgPath:
+ ps4PatchLatestPkgPath:
+ ps4PatchChangeinfoPath:
+ ps4PatchDayOne: 0
+ ps4attribUserManagement: 0
+ ps4attribMoveSupport: 0
+ ps4attrib3DSupport: 0
+ ps4attribShareSupport: 0
+ ps4attribExclusiveVR: 0
+ ps4disableAutoHideSplash: 0
+ ps4videoRecordingFeaturesUsed: 0
+ ps4contentSearchFeaturesUsed: 0
+ ps4CompatibilityPS5: 0
+ ps4AllowPS5Detection: 0
+ ps4GPU800MHz: 1
+ ps4attribEyeToEyeDistanceSettingVR: 0
+ ps4IncludedModules: []
+ ps4attribVROutputEnabled: 0
+ monoEnv:
+ splashScreenBackgroundSourceLandscape: {fileID: 0}
+ splashScreenBackgroundSourcePortrait: {fileID: 0}
+ blurSplashScreenBackground: 1
+ spritePackerPolicy:
+ webGLMemorySize: 32
+ webGLExceptionSupport: 1
+ webGLNameFilesAsHashes: 0
+ webGLShowDiagnostics: 0
+ webGLDataCaching: 1
+ webGLDebugSymbols: 0
+ webGLEmscriptenArgs:
+ webGLModulesDirectory:
+ webGLTemplate: APPLICATION:Default
+ webGLAnalyzeBuildSize: 0
+ webGLUseEmbeddedResources: 0
+ webGLCompressionFormat: 1
+ webGLWasmArithmeticExceptions: 0
+ webGLLinkerTarget: 1
+ webGLThreadsSupport: 0
+ webGLDecompressionFallback: 0
+ webGLInitialMemorySize: 32
+ webGLMaximumMemorySize: 2048
+ webGLMemoryGrowthMode: 2
+ webGLMemoryLinearGrowthStep: 16
+ webGLMemoryGeometricGrowthStep: 0.2
+ webGLMemoryGeometricGrowthCap: 96
+ webGLPowerPreference: 2
+ webGLWebAssemblyTable: 0
+ webGLWebAssemblyBigInt: 0
+ webGLCloseOnQuit: 0
+ webWasm2023: 0
+ webEnableSubmoduleStrippingCompatibility: 0
+ scriptingDefineSymbols: {}
+ additionalCompilerArguments: {}
+ platformArchitecture: {}
+ scriptingBackend:
+ Android: 1
+ iPhone: 1
+ il2cppCompilerConfiguration:
+ Android: 1
+ il2cppCodeGeneration:
+ Android: 1
+ iPhone: 1
+ il2cppStacktraceInformation: {}
+ managedStrippingLevel:
+ Android: 3
+ iPhone: 3
+ incrementalIl2cppBuild: {}
+ suppressCommonWarnings: 1
+ allowUnsafeCode: 0
+ useDeterministicCompilation: 1
+ additionalIl2CppArgs:
+ scriptingRuntimeVersion: 1
+ gcIncremental: 1
+ gcWBarrierValidation: 0
+ apiCompatibilityLevelPerPlatform: {}
+ editorAssembliesCompatibilityLevel: 1
+ m_RenderingPath: 1
+ m_MobileRenderingPath: 1
+ metroPackageName: demo-no-location
+ metroPackageVersion:
+ metroCertificatePath:
+ metroCertificatePassword:
+ metroCertificateSubject:
+ metroCertificateIssuer:
+ metroCertificateNotAfter: 0000000000000000
+ metroApplicationDescription: demo-no-location
+ wsaImages: {}
+ metroTileShortName:
+ metroTileShowName: 0
+ metroMediumTileShowName: 0
+ metroLargeTileShowName: 0
+ metroWideTileShowName: 0
+ metroSupportStreamingInstall: 0
+ metroLastRequiredScene: 0
+ metroDefaultTileSize: 1
+ metroTileForegroundText: 2
+ metroTileBackgroundColor: {r: 0.13333334, g: 0.17254902, b: 0.21568628, a: 0}
+ metroSplashScreenBackgroundColor: {r: 0.12941177, g: 0.17254902, b: 0.21568628, a: 1}
+ metroSplashScreenUseBackgroundColor: 0
+ syncCapabilities: 0
+ platformCapabilities: {}
+ metroTargetDeviceFamilies: {}
+ metroFTAName:
+ metroFTAFileTypes: []
+ metroProtocolName:
+ vcxProjDefaultLanguage:
+ XboxOneProductId:
+ XboxOneUpdateKey:
+ XboxOneSandboxId:
+ XboxOneContentId:
+ XboxOneTitleId:
+ XboxOneSCId:
+ XboxOneGameOsOverridePath:
+ XboxOnePackagingOverridePath:
+ XboxOneAppManifestOverridePath:
+ XboxOneVersion: 1.0.0.0
+ XboxOnePackageEncryption: 0
+ XboxOnePackageUpdateGranularity: 2
+ XboxOneDescription:
+ XboxOneLanguage:
+ - enus
+ XboxOneCapability: []
+ XboxOneGameRating: {}
+ XboxOneIsContentPackage: 0
+ XboxOneEnhancedXboxCompatibilityMode: 0
+ XboxOneEnableGPUVariability: 1
+ XboxOneSockets: {}
+ XboxOneSplashScreen: {fileID: 0}
+ XboxOneAllowedProductIds: []
+ XboxOnePersistentLocalStorageSize: 0
+ XboxOneXTitleMemory: 8
+ XboxOneOverrideIdentityName:
+ XboxOneOverrideIdentityPublisher:
+ vrEditorSettings: {}
+ cloudServicesEnabled: {}
+ luminIcon:
+ m_Name:
+ m_ModelFolderPath:
+ m_PortalFolderPath:
+ luminCert:
+ m_CertPath:
+ m_SignPackage: 1
+ luminIsChannelApp: 0
+ luminVersion:
+ m_VersionCode: 1
+ m_VersionName:
+ hmiPlayerDataPath:
+ hmiForceSRGBBlit: 0
+ embeddedLinuxEnableGamepadInput: 0
+ hmiCpuConfiguration:
+ hmiLogStartupTiming: 0
+ qnxGraphicConfPath:
+ apiCompatibilityLevel: 6
+ captureStartupLogs: {}
+ activeInputHandler: -1
+ windowsGamepadBackendHint: 0
+ enableDirectStorage: 0
+ cloudProjectId:
+ framebufferDepthMemorylessMode: 0
+ qualitySettingsNames: []
+ projectName:
+ organizationId:
+ cloudEnabled: 0
+ legacyClampBlendShapeWeights: 1
+ hmiLoadingImage: {fileID: 0}
+ platformRequiresReadableAssets: 0
+ virtualTexturingSupportEnabled: 0
+ insecureHttpOption: 0
+ androidVulkanDenyFilterList: []
+ androidVulkanAllowFilterList: []
+ androidVulkanDeviceFilterListAsset: {fileID: 0}
+ d3d12DeviceFilterListAsset: {fileID: 0}
+ allowedHttpConnections: 3
diff --git a/examples/demo-no-location/ProjectSettings/ProjectVersion.txt b/examples/demo-no-location/ProjectSettings/ProjectVersion.txt
new file mode 100644
index 00000000..29501ff0
--- /dev/null
+++ b/examples/demo-no-location/ProjectSettings/ProjectVersion.txt
@@ -0,0 +1,2 @@
+m_EditorVersion: 6000.4.11f1
+m_EditorVersionWithRevision: 6000.4.11f1 (b0a1d6caadd2)
diff --git a/examples/demo-no-location/README.md b/examples/demo-no-location/README.md
new file mode 100644
index 00000000..7f7c1ef9
--- /dev/null
+++ b/examples/demo-no-location/README.md
@@ -0,0 +1,130 @@
+# OneSignal No-Location Demo
+
+Minimal Unity project for apps that use OneSignal without the native location module.
+
+This demo opts out of location two ways, so it stays no-location whether you build from the Editor or the command line:
+
+- The `run-ios.sh` and `run-android.sh` scripts export `ONESIGNAL_DISABLE_LOCATION=true` before launching Unity. The environment variable takes precedence over the Editor toggle.
+- The Editor toggle is checked in for interactive use (`ProjectSettings/OneSignalSettings.json`):
+
+ ```json
+ {
+ "disableLocation": true
+ }
+ ```
+
+If you open the project in the Editor without the environment variable, confirm **OneSignal > Disable Location Module** is checked before resolving Android dependencies or building iOS.
+
+## Configure App ID
+
+For scripted builds, `run-android.sh` and `run-ios.sh` read `ONESIGNAL_APP_ID` from the shell environment or from `.env` in this folder. The environment variable wins if both are set.
+
+```sh
+cp .env.example .env
+```
+
+Then edit `.env`:
+
+```sh
+ONESIGNAL_APP_ID=YOUR-ONESIGNAL-APP-ID
+```
+
+The build injects that value into the generated app without saving it into the tracked scene file.
+
+For Play Mode in the Unity Editor:
+
+1. Open `Assets/Scenes/Main.unity`.
+2. Select the `OneSignal No Location Demo` GameObject.
+3. Set `One Signal App Id` on the `NoLocationDemo` component.
+
+If the value is left as `YOUR-ONESIGNAL-APP-ID`, the app starts but does not initialize OneSignal.
+
+## Run On Android
+
+Have an Android emulator running, then run:
+
+```sh
+./run-android.sh
+```
+
+Useful options:
+
+```sh
+./run-android.sh --no-install
+./run-android.sh --install-only
+```
+
+Set `UNITY_PATH` if you want to use a specific Unity executable. Set `ADB` or `ANDROID_HOME` if the script cannot find `adb`.
+
+## Run On iOS
+
+Have an iOS simulator booted, then run:
+
+```sh
+./run-ios.sh
+```
+
+Recent macOS ships `openrsync` as `/usr/bin/rsync`, which fails the CocoaPods "Copy XCFrameworks" build phase (`renameat: No such file or directory` on the OneSignal dSYM). Install a real rsync once and `run-ios.sh` will prefer it automatically:
+
+```sh
+brew install rsync
+```
+
+Useful options:
+
+```sh
+./run-ios.sh --no-install
+./run-ios.sh --install-only
+./run-ios.sh --open
+```
+
+Set `UNITY_PATH` if you want to use a specific Unity executable.
+
+The iOS script generates a minimal Podfile when External Dependency Manager does not create one, then runs `pod install` and builds the generated Xcode workspace.
+
+## Native Dependencies
+
+The SDK generates the EDM4U manifests per project at `Assets/OneSignal/Editor/OneSignal{Android,iOS}Dependencies.xml` based on the location flag, so the granular (no-location) dependency set below is what EDM4U resolves for this demo.
+
+### Android
+
+The resolver snapshot uses OneSignal native modules without the location artifact:
+
+```xml
+com.onesignal:core:5.9.5
+com.onesignal:notifications:5.9.5
+com.onesignal:in-app-messages:5.9.5
+```
+
+If you force-resolve again, keep the location module disabled.
+
+### iOS
+
+When location is disabled, iOS uses OneSignal pods without `OneSignalLocation`:
+
+```xml
+
+
+```
+
+The notification service extension still uses `OneSignalXCFramework/OneSignalExtension`.
+
+## App Code
+
+`NoLocationDemo.cs` initializes OneSignal, requests push permission, sends a test push to the current subscription via the OneSignal REST API, and includes a test button for `OneSignal.Location.RequestPermission()`. With the native location module excluded, location calls no-op and `OneSignal.Location.IsShared` returns `false`.
+
+The test push is sent with the app ID only (no REST API key), targeting the current `include_subscription_ids`, matching the other OneSignal no-location demos.
+
+## Code Stripping (`link.xml`)
+
+`Assets/OneSignal/link.xml` is required. Do not delete it.
+
+The scripted builds use `ManagedStrippingLevel.High`, and the OneSignal platform implementations (`OneSignaliOS`, `OneSignalAndroid`) are resolved by reflection at runtime. Without this file, IL2CPP strips those types, so `OneSignal.Default` throws on first use and the SDK never initializes (the app shows `Not initialized` and no permission prompt appears).
+
+In a normal SDK integration the OneSignal Setup window generates this file automatically; this demo is built headlessly via `BuildScript`, so the file is checked in instead.
+
+## Generated Files
+
+Unity build output is generated under `Build/`, `Library/`, `Logs/`, and `UserSettings/`. These folders are ignored.
+
+Unity may also generate extra files under `ProjectSettings/`; this demo tracks only the minimal settings files needed to keep the project reproducible.
diff --git a/examples/demo-no-location/run-android.sh b/examples/demo-no-location/run-android.sh
new file mode 100755
index 00000000..255d90fb
--- /dev/null
+++ b/examples/demo-no-location/run-android.sh
@@ -0,0 +1,105 @@
+#!/bin/sh
+# Build the OneSignal Unity no-location demo APK and install it on a running emulator.
+#
+# Usage:
+# ./run-android.sh [--no-install] [--install-only]
+set -eu
+
+# Opt out of the OneSignal location module for this build. The SDK reads this at
+# dependency-resolution time and links the granular artifacts without location.
+export ONESIGNAL_DISABLE_LOCATION=true
+
+SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
+
+find_unity() {
+ if [ -n "${UNITY_PATH:-}" ]; then
+ echo "$UNITY_PATH"
+ return
+ fi
+ for d in $(ls -1 /Applications/Unity/Hub/Editor 2>/dev/null | sort -rV); do
+ BIN="/Applications/Unity/Hub/Editor/$d/Unity.app/Contents/MacOS/Unity"
+ [ -x "$BIN" ] && echo "$BIN" && return
+ done
+}
+UNITY="$(find_unity)"
+
+find_adb() {
+ if [ -n "${ADB:-}" ] && [ -x "$ADB" ]; then echo "$ADB"; return; fi
+ for CANDIDATE in \
+ "${ANDROID_HOME:-}/platform-tools/adb" \
+ "${ANDROID_SDK_ROOT:-}/platform-tools/adb" \
+ "$HOME/Library/Android/sdk/platform-tools/adb"; do
+ [ -x "$CANDIDATE" ] && echo "$CANDIDATE" && return
+ done
+ if command -v adb >/dev/null 2>&1; then command -v adb; return; fi
+ if [ -n "$UNITY" ]; then
+ UNITY_DIR=$(dirname "$(dirname "$(dirname "$(dirname "$UNITY")")")")
+ CANDIDATE="$UNITY_DIR/PlaybackEngines/AndroidPlayer/SDK/platform-tools/adb"
+ [ -x "$CANDIDATE" ] && echo "$CANDIDATE" && return
+ fi
+}
+ADB="$(find_adb)"
+
+OUTPUT="$SCRIPT_DIR/Build/Android/onesignal-demo-no-location.apk"
+LOG="$SCRIPT_DIR/Build/build-android.log"
+INSTALL=true
+SKIP_BUILD=false
+
+for arg in "$@"; do
+ case "$arg" in
+ --no-install) INSTALL=false ;;
+ --install-only) SKIP_BUILD=true ;;
+ esac
+done
+
+pick_emulator() {
+ [ -z "$ADB" ] && echo "adb not found. Set ADB or ANDROID_HOME to your Android SDK." && exit 1
+ LIST=$("$ADB" devices | awk '/emulator-[0-9]+[[:space:]]+device/{print $1}')
+ COUNT=$(printf '%s\n' "$LIST" | grep -c . || true)
+
+ [ "$COUNT" -eq 0 ] && echo "No running emulators found." && exit 1
+ [ "$COUNT" -eq 1 ] && EMULATOR="$LIST" && return
+
+ echo "Multiple emulators running - pick one:"
+ i=1
+ printf '%s\n' "$LIST" | while IFS= read -r S; do
+ NAME=$("$ADB" -s "$S" emu avd name 2>/dev/null | sed -n '1p' | tr -d '\r')
+ printf " [%d] %s (%s)\n" "$i" "$S" "$NAME"
+ i=$((i + 1))
+ done
+ printf "Choice [1-%d]: " "$COUNT"
+ read -r CHOICE
+ EMULATOR=$(printf '%s\n' "$LIST" | sed -n "${CHOICE}p")
+ [ -z "$EMULATOR" ] && echo "Invalid choice." && exit 1
+}
+
+EMULATOR=""
+[ "$INSTALL" = true ] && pick_emulator && echo "Target: $EMULATOR" && echo ""
+
+if [ "$SKIP_BUILD" = true ]; then
+ [ ! -f "$OUTPUT" ] && echo "No existing build. Run without --install-only first." && exit 1
+ echo "Skipping build, using existing $(du -sh "$OUTPUT" | awk '{print $1}') APK"
+else
+ [ ! -x "$UNITY" ] && echo "Unity not found at $UNITY - set UNITY_PATH" && exit 1
+ mkdir -p "$SCRIPT_DIR/Build/Android"
+ echo "Building no-location APK (ARM64 / IL2CPP)..."
+ echo "Log: $LOG"
+ echo ""
+
+ START=$(date +%s)
+ "$UNITY" -batchmode -nographics -quit -buildTarget Android \
+ -projectPath "$SCRIPT_DIR" -executeMethod BuildScript.BuildAndroidEmulator \
+ -logFile "$LOG"
+ ELAPSED=$(( $(date +%s) - START ))
+
+ [ ! -f "$OUTPUT" ] && echo "Build failed after $((ELAPSED/60))m $((ELAPSED%60))s. Check $LOG" && exit 1
+ echo "Build complete in $((ELAPSED/60))m $((ELAPSED%60))s - $(du -sh "$OUTPUT" | awk '{print $1}') $OUTPUT"
+fi
+
+if [ "$INSTALL" = true ] && [ -n "$EMULATOR" ]; then
+ "$ADB" start-server >/dev/null 2>&1
+ "$ADB" -s "$EMULATOR" wait-for-device
+ echo "Installing on $EMULATOR..."
+ "$ADB" -s "$EMULATOR" install -r "$OUTPUT"
+ "$ADB" -s "$EMULATOR" shell am start -n com.onesignal.example/com.unity3d.player.UnityPlayerActivity
+fi
diff --git a/examples/demo-no-location/run-ios.sh b/examples/demo-no-location/run-ios.sh
new file mode 100755
index 00000000..c3f1bed7
--- /dev/null
+++ b/examples/demo-no-location/run-ios.sh
@@ -0,0 +1,214 @@
+#!/bin/sh
+# Build the OneSignal Unity no-location demo for iOS simulator.
+#
+# Usage:
+# ./run-ios.sh [--no-install] [--install-only] [--open]
+set -eu
+
+# Opt out of the OneSignal location module for this build. The SDK reads this at
+# dependency-resolution time and links the granular pods without OneSignalLocation.
+export ONESIGNAL_DISABLE_LOCATION=true
+
+SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
+
+find_unity() {
+ if [ -n "${UNITY_PATH:-}" ]; then
+ echo "$UNITY_PATH"
+ return
+ fi
+ for d in $(ls -1 /Applications/Unity/Hub/Editor 2>/dev/null | sort -rV); do
+ BIN="/Applications/Unity/Hub/Editor/$d/Unity.app/Contents/MacOS/Unity"
+ [ -x "$BIN" ] && echo "$BIN" && return
+ done
+}
+UNITY="$(find_unity)"
+
+XCODE_DIR="$SCRIPT_DIR/Build/iOS"
+LOG="$SCRIPT_DIR/Build/build-ios.log"
+SCHEME="Unity-iPhone"
+DERIVED="$SCRIPT_DIR/Build/iOS-DerivedData"
+APP_BUNDLE_ID="com.onesignal.example"
+INSTALL=true
+SKIP_BUILD=false
+OPEN_XCODE=false
+
+for arg in "$@"; do
+ case "$arg" in
+ --no-install) INSTALL=false ;;
+ --install-only) SKIP_BUILD=true ;;
+ --open) OPEN_XCODE=true; INSTALL=false; SKIP_BUILD=true ;;
+ esac
+done
+
+pick_simulator() {
+ LIST=$(xcrun simctl list devices booted -j \
+ | python3 -c "
+import json,sys
+d=json.load(sys.stdin)
+for r,devs in d['devices'].items():
+ for dev in devs:
+ if dev['state']=='Booted':
+ print(dev['udid'] + '|' + dev['name'])
+" 2>/dev/null || true)
+ COUNT=$(printf '%s\n' "$LIST" | grep -c . || true)
+
+ [ "$COUNT" -eq 0 ] && echo "No booted simulators found. Boot one with: xcrun simctl boot " && exit 1
+ [ "$COUNT" -eq 1 ] && SIM_UDID=$(echo "$LIST" | cut -d'|' -f1) && SIM_NAME=$(echo "$LIST" | cut -d'|' -f2) && return
+
+ echo "Multiple simulators booted - pick one:"
+ i=1
+ printf '%s\n' "$LIST" | while IFS='|' read -r UDID NAME; do
+ printf " [%d] %s (%s)\n" "$i" "$NAME" "$UDID"
+ i=$((i + 1))
+ done
+ printf "Choice [1-%d]: " "$COUNT"
+ read -r CHOICE
+ LINE=$(printf '%s\n' "$LIST" | sed -n "${CHOICE}p")
+ [ -z "$LINE" ] && echo "Invalid choice." && exit 1
+ SIM_UDID=$(echo "$LINE" | cut -d'|' -f1)
+ SIM_NAME=$(echo "$LINE" | cut -d'|' -f2)
+}
+
+# Fallback Podfile generator: EDM4U's iOS resolver normally emits the Podfile
+# during the Unity build from the generated per-project dependency manifest. This
+# only runs if that didn't happen, so the no-location build still works offline.
+ensure_podfile() {
+ [ -f "$XCODE_DIR/Podfile" ] && return
+
+ DEPS="$SCRIPT_DIR/Assets/OneSignal/Editor/OneSignaliOSDependencies.xml"
+ [ ! -f "$DEPS" ] && return
+
+ python3 - "$DEPS" "$XCODE_DIR/Podfile" <<'PY'
+import os
+import sys
+import xml.etree.ElementTree as ET
+
+deps_path, podfile_path = sys.argv[1:3]
+root = ET.parse(deps_path).getroot()
+pods = []
+
+for pod in root.findall("./iosPods/iosPod"):
+ name = pod.get("name")
+ version = pod.get("version")
+ if name and version:
+ pods.append((name, version))
+
+if not pods:
+ sys.exit(0)
+
+onesignal_version = next(
+ (version for name, version in pods if name.startswith("OneSignalXCFramework")),
+ None,
+)
+
+lines = [
+ "source 'https://cdn.cocoapods.org/'",
+ "install! 'cocoapods', :disable_input_output_paths => true",
+ "platform :ios, '13.0'",
+ "use_frameworks! :linkage => :static",
+ "",
+]
+
+for target in ("UnityFramework", "Unity-iPhone"):
+ lines.append(f"target '{target}' do")
+ for name, version in pods:
+ lines.append(f" pod '{name}', '{version}'")
+ lines.extend(["end", ""])
+
+if onesignal_version:
+ lines.extend([
+ "target 'OneSignalNotificationServiceExtension' do",
+ f" pod 'OneSignalXCFramework/OneSignalExtension', '{onesignal_version}'",
+ "end",
+ "",
+ ])
+
+os.makedirs(os.path.dirname(podfile_path), exist_ok=True)
+with open(podfile_path, "w", encoding="utf-8") as podfile:
+ podfile.write("\n".join(lines))
+PY
+}
+
+SIM_UDID=""
+SIM_NAME=""
+[ "$INSTALL" = true ] && pick_simulator && echo "Target: $SIM_NAME ($SIM_UDID)" && echo ""
+
+if [ "$OPEN_XCODE" = true ]; then
+ WS="$XCODE_DIR/Unity-iPhone.xcworkspace"
+ [ ! -d "$WS" ] && echo "No workspace found. Run without --open first." && exit 1
+ echo "Opening $WS..."
+ open "$WS"
+ exit 0
+fi
+
+if [ "$SKIP_BUILD" = true ]; then
+ [ ! -d "$XCODE_DIR/Unity-iPhone.xcodeproj" ] && echo "No existing build. Run without --install-only first." && exit 1
+ echo "Skipping Unity build, using existing Xcode project"
+else
+ [ ! -x "$UNITY" ] && echo "Unity not found at $UNITY - set UNITY_PATH" && exit 1
+ mkdir -p "$XCODE_DIR"
+ echo "Generating no-location Xcode project (IL2CPP / Simulator)..."
+ echo "Log: $LOG"
+ echo ""
+
+ START=$(date +%s)
+ "$UNITY" -batchmode -nographics -quit -buildTarget iOS \
+ -projectPath "$SCRIPT_DIR" -executeMethod BuildScript.BuildiOSSimulator \
+ -logFile "$LOG"
+ ELAPSED=$(( $(date +%s) - START ))
+
+ [ ! -d "$XCODE_DIR/Unity-iPhone.xcodeproj" ] && echo "Build failed after $((ELAPSED/60))m $((ELAPSED%60))s. Check $LOG" && exit 1
+ echo "Xcode project generated in $((ELAPSED/60))m $((ELAPSED%60))s"
+fi
+
+ensure_podfile
+
+if [ -f "$XCODE_DIR/Podfile" ]; then
+ echo "Running pod install..."
+ (cd "$XCODE_DIR" && pod install --repo-update)
+fi
+
+if [ "$INSTALL" = true ] && [ -n "$SIM_UDID" ]; then
+ echo ""
+ echo "Building with xcodebuild for simulator..."
+ WS="$XCODE_DIR/Unity-iPhone.xcworkspace"
+ [ ! -d "$WS" ] && WS=""
+
+ # macOS ships openrsync as /usr/bin/rsync, which fails the CocoaPods "Copy
+ # XCFrameworks" phase ("renameat: No such file or directory" on the dSYM
+ # DWARF). Prefer a real rsync (brew install rsync) on PATH if present.
+ if [ -x /opt/homebrew/bin/rsync ]; then
+ PATH="/opt/homebrew/bin:$PATH"
+ export PATH
+ elif [ -x /usr/local/bin/rsync ]; then
+ PATH="/usr/local/bin:$PATH"
+ export PATH
+ else
+ echo "Warning: only macOS openrsync found; the XCFramework copy phase may fail."
+ echo " Install a real rsync with: brew install rsync"
+ fi
+
+ BUILD_START=$(date +%s)
+ if [ -n "$WS" ]; then
+ xcodebuild -workspace "$WS" -scheme "$SCHEME" \
+ -destination "id=$SIM_UDID" \
+ -derivedDataPath "$DERIVED" \
+ -quiet \
+ build
+ else
+ xcodebuild -project "$XCODE_DIR/Unity-iPhone.xcodeproj" -scheme "$SCHEME" \
+ -destination "id=$SIM_UDID" \
+ -derivedDataPath "$DERIVED" \
+ -quiet \
+ build
+ fi
+ BUILD_ELAPSED=$(( $(date +%s) - BUILD_START ))
+ echo "xcodebuild finished in $((BUILD_ELAPSED/60))m $((BUILD_ELAPSED%60))s"
+
+ APP_PATH=$(find "$DERIVED" -name "*.app" -path "*/Build/Products/*" | sed -n '1p')
+ [ -z "$APP_PATH" ] && echo "Could not find .app bundle in derived data." && exit 1
+
+ echo "Installing on $SIM_NAME..."
+ xcrun simctl install "$SIM_UDID" "$APP_PATH"
+ xcrun simctl launch "$SIM_UDID" "$APP_BUNDLE_ID"
+fi
diff --git a/examples/demo/ProjectSettings/ProjectVersion.txt b/examples/demo/ProjectSettings/ProjectVersion.txt
index 67039ec6..29501ff0 100644
--- a/examples/demo/ProjectSettings/ProjectVersion.txt
+++ b/examples/demo/ProjectSettings/ProjectVersion.txt
@@ -1,2 +1,2 @@
-m_EditorVersion: 6000.4.6f1
-m_EditorVersionWithRevision: 6000.4.6f1 (0b051c2e5d54)
+m_EditorVersion: 6000.4.11f1
+m_EditorVersionWithRevision: 6000.4.11f1 (b0a1d6caadd2)