From fb619b7dec6f4f05d8d3b70b06aba25dfb337efc Mon Sep 17 00:00:00 2001 From: Fadi George Date: Thu, 11 Jun 2026 17:58:35 -0700 Subject: [PATCH 01/21] feat: [SDK-4774] add optional location module disable --- README.md | 12 +++ .../Editor/OneSignalAndroidDependencies.cs | 102 ++++++++++++++++++ .../OneSignalAndroidDependencies.cs.meta | 11 ++ .../Runtime/AndroidLocationManager.cs | 25 ++++- .../Editor/OneSignalSDKSettings.cs | 102 ++++++++++++++++++ .../Editor/OneSignalSDKSettings.cs.meta | 11 ++ .../Editor/BuildPostProcessor.cs | 24 ++++- .../Editor/OneSignal.iOS.Editor.asmdef | 4 +- .../Editor/OneSignaliOSDependencies.cs | 95 ++++++++++++++++ .../Editor/OneSignaliOSDependencies.cs.meta | 11 ++ .../iOS/OneSignalUnityBridgeLocation.mm | 8 ++ 11 files changed, 395 insertions(+), 10 deletions(-) create mode 100644 com.onesignal.unity.android/Editor/OneSignalAndroidDependencies.cs create mode 100644 com.onesignal.unity.android/Editor/OneSignalAndroidDependencies.cs.meta create mode 100644 com.onesignal.unity.core/Editor/OneSignalSDKSettings.cs create mode 100644 com.onesignal.unity.core/Editor/OneSignalSDKSettings.cs.meta create mode 100644 com.onesignal.unity.ios/Editor/OneSignaliOSDependencies.cs create mode 100644 com.onesignal.unity.ios/Editor/OneSignaliOSDependencies.cs.meta diff --git a/README.md b/README.md index 62ee47318..8c4c4b6fb 100644 --- a/README.md +++ b/README.md @@ -150,6 +150,18 @@ The only thing remaining is to setup your own notification icons. You can do thi with your own. There is a complete guide for this [in the plugin's README](com.onesignal.unity.android/Editor/OneSignalConfig.androidlib/README.md). See our [Customize Notification Icons](https://documentation.onesignal.com/docs/customize-notification-icons) page for additional details. +### Disable Location Module + +By default, the OneSignal Unity SDK includes OneSignal's native location module so `OneSignal.Location` works without extra setup. If your app does not use location features, select **OneSignal > Disable Location Module** in the Unity Editor before resolving Android dependencies or building iOS. + +You can also set the same project setting from an editor script: + +```C# +OneSignalSDK.OneSignalSDKSettings.DisableLocation = true; +``` + +When disabled, Android resolves OneSignal's native modules without the location artifact and iOS uses OneSignal pods without `OneSignalLocation`. `OneSignal.Location.RequestPermission()` and `OneSignal.Location.IsShared = ...` no-op on native builds without the location module, and `OneSignal.Location.IsShared` returns `false`. + ## Usage You can find a complete implementation in our included [example MonoBehaviour](OneSignalExample/Assets/OneSignal/Example/OneSignalExampleBehaviour.cs). Additionally we have included a [sample scene](OneSignalExample/Assets/OneSignal/Example/OneSignalExampleScene.unity) which you can run to test out the SDK. diff --git a/com.onesignal.unity.android/Editor/OneSignalAndroidDependencies.cs b/com.onesignal.unity.android/Editor/OneSignalAndroidDependencies.cs new file mode 100644 index 000000000..523397f72 --- /dev/null +++ b/com.onesignal.unity.android/Editor/OneSignalAndroidDependencies.cs @@ -0,0 +1,102 @@ +/* + * Modified MIT License + * + * Copyright 2023 OneSignal + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * 1. The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * 2. All copies of substantial portions of the Software may only be used in connection + * with services provided by OneSignal. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +using System; +using System.IO; +using UnityEditor; +using Debug = UnityEngine.Debug; + +namespace OneSignalSDK +{ + [InitializeOnLoad] + internal static class OneSignalAndroidDependencies + { + static OneSignalAndroidDependencies() + { + OneSignalSDKSettings.Changed += WriteDependencies; + WriteDependencies(); + } + + internal static void WriteDependencies() + { + var contents = OneSignalSDKSettings.DisableLocation + ? DisabledLocationDependencies + : DefaultDependencies; + + try + { + if ( + File.Exists(_dependenciesPath) + && File.ReadAllText(_dependenciesPath) == contents + ) + return; + + File.WriteAllText(_dependenciesPath, contents); + AssetDatabase.ImportAsset(_dependenciesPath); + } + catch (Exception exception) + { + Debug.LogWarning( + $"Could not update OneSignal Android dependencies at {_dependenciesPath}: {exception.Message}" + ); + } + } + + private const string Version = "5.9.3"; + + private static readonly string _dependenciesPath = Path.Combine( + "Packages", + "com.onesignal.unity.android", + "Editor", + "OneSignalAndroidDependencies.xml" + ); + + private static string DefaultDependencies => + $@" + + + https://repo.maven.apache.org/maven2 + + + + +"; + + private static string DisabledLocationDependencies => + $@" + + + https://repo.maven.apache.org/maven2 + + + + + + +"; + } +} diff --git a/com.onesignal.unity.android/Editor/OneSignalAndroidDependencies.cs.meta b/com.onesignal.unity.android/Editor/OneSignalAndroidDependencies.cs.meta new file mode 100644 index 000000000..3dfe5c242 --- /dev/null +++ b/com.onesignal.unity.android/Editor/OneSignalAndroidDependencies.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 7c79cba1d8d84b6bba362e113f39e1d2 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/com.onesignal.unity.android/Runtime/AndroidLocationManager.cs b/com.onesignal.unity.android/Runtime/AndroidLocationManager.cs index 22cd337ee..47efa1cfc 100644 --- a/com.onesignal.unity.android/Runtime/AndroidLocationManager.cs +++ b/com.onesignal.unity.android/Runtime/AndroidLocationManager.cs @@ -25,8 +25,9 @@ * THE SOFTWARE. */ -using System.Threading.Tasks; +using System; using OneSignalSDK.Android.Utilities; +using OneSignalSDK.Debug.Utilities; using OneSignalSDK.Location; using UnityEngine; @@ -38,17 +39,33 @@ internal sealed class AndroidLocationManager : ILocationManager public AndroidLocationManager(AndroidJavaClass sdkClass) { - _location = sdkClass.CallStatic("getLocation"); + try + { + _location = sdkClass.CallStatic("getLocation"); + } + catch (Exception) + { + SDKDebug.Warn( + "OneSignal location module is not available. OneSignal.Location calls will no-op." + ); + } } public bool IsShared { - get => _location.Call("isShared"); - set => _location.Call("setShared", value); + get => _location != null && _location.Call("isShared"); + set + { + if (_location != null) + _location.Call("setShared", value); + } } public void RequestPermission() { + if (_location == null) + return; + var continuation = new BoolContinuation(); _location.Call("requestPermission", continuation.Proxy); } diff --git a/com.onesignal.unity.core/Editor/OneSignalSDKSettings.cs b/com.onesignal.unity.core/Editor/OneSignalSDKSettings.cs new file mode 100644 index 000000000..73011b886 --- /dev/null +++ b/com.onesignal.unity.core/Editor/OneSignalSDKSettings.cs @@ -0,0 +1,102 @@ +/* + * Modified MIT License + * + * Copyright 2023 OneSignal + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * 1. The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * 2. All copies of substantial portions of the Software may only be used in connection + * with services provided by OneSignal. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +using System; +using System.IO; +using UnityEditor; +using UnityEngine; + +namespace OneSignalSDK +{ + public static class OneSignalSDKSettings + { + public static event Action Changed; + + public static bool DisableLocation + { + get => _settings.disableLocation; + set + { + if (_settings.disableLocation == value) + return; + + _settings.disableLocation = value; + Save(); + Changed?.Invoke(); + AssetDatabase.Refresh(); + } + } + + public static void Save() + { + Directory.CreateDirectory(Path.GetDirectoryName(_settingsPath)); + File.WriteAllText(_settingsPath, JsonUtility.ToJson(_settings, true)); + } + + [MenuItem("OneSignal/Disable Location Module")] + private static void ToggleDisableLocation() + { + DisableLocation = !DisableLocation; + } + + [MenuItem("OneSignal/Disable Location Module", true)] + private static bool ToggleDisableLocationValidate() + { + Menu.SetChecked("OneSignal/Disable Location Module", DisableLocation); + return true; + } + + private static readonly string _settingsPath = Path.Combine( + "ProjectSettings", + "OneSignalSettings.json" + ); + + private static Settings _settings = Load(); + + private static Settings Load() + { + if (!File.Exists(_settingsPath)) + return new Settings(); + + try + { + return JsonUtility.FromJson(File.ReadAllText(_settingsPath)) + ?? new Settings(); + } + catch + { + return new Settings(); + } + } + + [Serializable] + private sealed class Settings + { + public bool disableLocation; + } + } +} diff --git a/com.onesignal.unity.core/Editor/OneSignalSDKSettings.cs.meta b/com.onesignal.unity.core/Editor/OneSignalSDKSettings.cs.meta new file mode 100644 index 000000000..1e308d59b --- /dev/null +++ b/com.onesignal.unity.core/Editor/OneSignalSDKSettings.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 5f3f0ff2a9a0419ca5b5fae3f72396ad +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/com.onesignal.unity.ios/Editor/BuildPostProcessor.cs b/com.onesignal.unity.ios/Editor/BuildPostProcessor.cs index 6a294b321..335ca1b5e 100644 --- a/com.onesignal.unity.ios/Editor/BuildPostProcessor.cs +++ b/com.onesignal.unity.ios/Editor/BuildPostProcessor.cs @@ -126,8 +126,10 @@ public void OnPostprocessBuild(BuildReport report) AddNotificationServiceExtension(); DisableBitcode(); + ConfigureLocationModule(); - AddLocationUsageDescription(); + if (!OneSignalSDK.OneSignalSDKSettings.DisableLocation) + AddLocationUsageDescription(); // Save the project back out File.WriteAllText(_projectPath, _project.WriteToString()); @@ -327,7 +329,7 @@ private void ExtensionAddPodsToTarget() var dependenciesFile = File.ReadAllText(dependenciesFilePath); var dependenciesRegex = new Regex( - "(?<=)" + "" ); if (!dependenciesRegex.IsMatch(dependenciesFile)) @@ -340,12 +342,12 @@ private void ExtensionAddPodsToTarget() var podfile = File.ReadAllText(podfilePath); var podfileRegex = new Regex( - $@"target '{ServiceExtensionTargetName}' do\n pod 'OneSignalXCFramework', '(.+)'\nend\n" + $@"target '{ServiceExtensionTargetName}' do\n pod 'OneSignalXCFramework(?:/OneSignalExtension)?', '(.+)'\nend\n" ); - var requiredVersion = dependenciesRegex.Match(dependenciesFile).ToString(); + var requiredVersion = dependenciesRegex.Match(dependenciesFile).Groups[1].Value; var requiredTarget = - $"target '{ServiceExtensionTargetName}' do\n pod 'OneSignalXCFramework', '{requiredVersion}'\nend\n"; + $"target '{ServiceExtensionTargetName}' do\n pod 'OneSignalXCFramework/OneSignalExtension', '{requiredVersion}'\nend\n"; if (!podfileRegex.IsMatch(podfile)) podfile += requiredTarget; @@ -358,6 +360,18 @@ private void ExtensionAddPodsToTarget() File.WriteAllText(podfilePath, podfile); } + private void ConfigureLocationModule() + { + if (!OneSignalSDK.OneSignalSDKSettings.DisableLocation) + return; + + _project.AddBuildProperty( + _project.GetUnityFrameworkTargetGuid(), + "GCC_PREPROCESSOR_DEFINITIONS", + "ONESIGNAL_DISABLE_LOCATION=1" + ); + } + private void AddLocationUsageDescription() { var plistPath = Path.Combine(_outputPath, "Info.plist"); diff --git a/com.onesignal.unity.ios/Editor/OneSignal.iOS.Editor.asmdef b/com.onesignal.unity.ios/Editor/OneSignal.iOS.Editor.asmdef index 54663dac3..23c5084c8 100644 --- a/com.onesignal.unity.ios/Editor/OneSignal.iOS.Editor.asmdef +++ b/com.onesignal.unity.ios/Editor/OneSignal.iOS.Editor.asmdef @@ -1,6 +1,8 @@ { "name": "OneSignal.iOS.Editor", - "references": [], + "references": [ + "OneSignal.Core.Editor" + ], "optionalUnityReferences": [], "includePlatforms": [ "Editor" diff --git a/com.onesignal.unity.ios/Editor/OneSignaliOSDependencies.cs b/com.onesignal.unity.ios/Editor/OneSignaliOSDependencies.cs new file mode 100644 index 000000000..7ae8d2fbb --- /dev/null +++ b/com.onesignal.unity.ios/Editor/OneSignaliOSDependencies.cs @@ -0,0 +1,95 @@ +/* + * Modified MIT License + * + * Copyright 2023 OneSignal + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * 1. The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * 2. All copies of substantial portions of the Software may only be used in connection + * with services provided by OneSignal. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +using System; +using System.IO; +using UnityEditor; +using Debug = UnityEngine.Debug; + +namespace OneSignalSDK.iOS +{ + [InitializeOnLoad] + internal static class OneSignaliOSDependencies + { + static OneSignaliOSDependencies() + { + OneSignalSDK.OneSignalSDKSettings.Changed += WriteDependencies; + WriteDependencies(); + } + + internal static void WriteDependencies() + { + var contents = OneSignalSDK.OneSignalSDKSettings.DisableLocation + ? DisabledLocationDependencies + : DefaultDependencies; + + try + { + if ( + File.Exists(_dependenciesPath) + && File.ReadAllText(_dependenciesPath) == contents + ) + return; + + File.WriteAllText(_dependenciesPath, contents); + AssetDatabase.ImportAsset(_dependenciesPath); + } + catch (Exception exception) + { + Debug.LogWarning( + $"Could not update OneSignal iOS dependencies at {_dependenciesPath}: {exception.Message}" + ); + } + } + + private const string Version = "5.5.2"; + + private static readonly string _dependenciesPath = Path.Combine( + "Packages", + "com.onesignal.unity.ios", + "Editor", + "OneSignaliOSDependencies.xml" + ); + + private static string DefaultDependencies => + $@" + + + + +"; + + private static string DisabledLocationDependencies => + $@" + + + + + +"; + } +} diff --git a/com.onesignal.unity.ios/Editor/OneSignaliOSDependencies.cs.meta b/com.onesignal.unity.ios/Editor/OneSignaliOSDependencies.cs.meta new file mode 100644 index 000000000..49c9aa34e --- /dev/null +++ b/com.onesignal.unity.ios/Editor/OneSignaliOSDependencies.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: b70d336c6c914452a259cd750a23da35 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/com.onesignal.unity.ios/Runtime/Plugins/iOS/OneSignalUnityBridgeLocation.mm b/com.onesignal.unity.ios/Runtime/Plugins/iOS/OneSignalUnityBridgeLocation.mm index 2c6988afb..3bc6e27fa 100644 --- a/com.onesignal.unity.ios/Runtime/Plugins/iOS/OneSignalUnityBridgeLocation.mm +++ b/com.onesignal.unity.ios/Runtime/Plugins/iOS/OneSignalUnityBridgeLocation.mm @@ -33,14 +33,22 @@ extern "C" { bool _oneSignalLocationGetIsShared() { +#if ONESIGNAL_DISABLE_LOCATION + return false; +#else return [OneSignal.Location isShared]; +#endif } void _oneSignalLocationSetIsShared(bool shared) { +#if !ONESIGNAL_DISABLE_LOCATION [OneSignal.Location setShared:shared]; +#endif } void _oneSignalLocationRequestPermission() { +#if !ONESIGNAL_DISABLE_LOCATION [OneSignal.Location requestPermission]; +#endif } } \ No newline at end of file From 4291ea88473bfc51da9800f655629f311ed376e3 Mon Sep 17 00:00:00 2001 From: Fadi George Date: Thu, 11 Jun 2026 18:10:56 -0700 Subject: [PATCH 02/21] feat(examples): add no-location demo project --- examples/demo-no-location/Assets.meta | 8 + examples/demo-no-location/Assets/Scenes.meta | 8 + .../demo-no-location/Assets/Scenes/Main.unity | 161 ++++++++++++++++++ .../Assets/Scenes/Main.unity.meta | 7 + examples/demo-no-location/Assets/Scripts.meta | 8 + .../Assets/Scripts/NoLocationDemo.cs | 77 +++++++++ .../Assets/Scripts/NoLocationDemo.cs.meta | 11 ++ .../demo-no-location/Packages/manifest.json | 8 + .../AndroidResolverDependencies.xml | 25 +++ .../ProjectSettings/EditorBuildSettings.asset | 11 ++ .../ProjectSettings/OneSignalSettings.json | 3 + .../ProjectSettings/ProjectSettings.asset | 84 +++++++++ .../ProjectSettings/ProjectVersion.txt | 2 + examples/demo-no-location/README.md | 33 ++++ 14 files changed, 446 insertions(+) create mode 100644 examples/demo-no-location/Assets.meta create mode 100644 examples/demo-no-location/Assets/Scenes.meta create mode 100644 examples/demo-no-location/Assets/Scenes/Main.unity create mode 100644 examples/demo-no-location/Assets/Scenes/Main.unity.meta create mode 100644 examples/demo-no-location/Assets/Scripts.meta create mode 100644 examples/demo-no-location/Assets/Scripts/NoLocationDemo.cs create mode 100644 examples/demo-no-location/Assets/Scripts/NoLocationDemo.cs.meta create mode 100644 examples/demo-no-location/Packages/manifest.json create mode 100644 examples/demo-no-location/ProjectSettings/AndroidResolverDependencies.xml create mode 100644 examples/demo-no-location/ProjectSettings/EditorBuildSettings.asset create mode 100644 examples/demo-no-location/ProjectSettings/OneSignalSettings.json create mode 100644 examples/demo-no-location/ProjectSettings/ProjectSettings.asset create mode 100644 examples/demo-no-location/ProjectSettings/ProjectVersion.txt create mode 100644 examples/demo-no-location/README.md diff --git a/examples/demo-no-location/Assets.meta b/examples/demo-no-location/Assets.meta new file mode 100644 index 000000000..109578fe4 --- /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/Scenes.meta b/examples/demo-no-location/Assets/Scenes.meta new file mode 100644 index 000000000..fa5071649 --- /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 000000000..c01df042c --- /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 000000000..2d24661a9 --- /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 000000000..08b53c300 --- /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/NoLocationDemo.cs b/examples/demo-no-location/Assets/Scripts/NoLocationDemo.cs new file mode 100644 index 000000000..d2043162d --- /dev/null +++ b/examples/demo-no-location/Assets/Scripts/NoLocationDemo.cs @@ -0,0 +1,77 @@ +using OneSignalSDK; +using OneSignalSDK.Debug.Models; +using UnityEngine; + +public sealed class NoLocationDemo : MonoBehaviour +{ + [SerializeField] + private string _oneSignalAppId = "YOUR-ONESIGNAL-APP-ID"; + + private string _status = "Set your OneSignal App ID in the Inspector."; + private bool _initialized; + + private void Start() + { + OneSignal.Debug.LogLevel = LogLevel.Verbose; + + if (!IsConfigured) + return; + + OneSignal.Initialize(_oneSignalAppId); + _initialized = true; + _status = "OneSignal initialized without native location module."; + } + + private void OnGUI() + { + const int margin = 24; + const int buttonHeight = 56; + var width = Screen.width - margin * 2; + + GUILayout.BeginArea(new Rect(margin, margin, width, Screen.height - margin * 2)); + GUILayout.Label("OneSignal No-Location Demo"); + GUILayout.Space(12); + GUILayout.Label(_status); + GUILayout.Space(12); + + if (GUILayout.Button("Request Push Permission", GUILayout.Height(buttonHeight))) + RequestPushPermission(); + + if (GUILayout.Button("Test Location Request No-Op", GUILayout.Height(buttonHeight))) + TestLocationRequest(); + + GUILayout.Space(12); + GUILayout.Label( + $"Location IsShared: {(_initialized ? OneSignal.Location.IsShared.ToString() : "Not initialized")}" + ); + GUILayout.EndArea(); + } + + private async void RequestPushPermission() + { + if (!_initialized) + { + _status = "Initialize OneSignal before requesting push permission."; + return; + } + + var granted = await OneSignal.Notifications.RequestPermissionAsync(false); + _status = $"Push permission: {(granted ? "granted" : "not granted")}"; + } + + private void TestLocationRequest() + { + if (!_initialized) + { + _status = "Initialize OneSignal before testing location."; + return; + } + + OneSignal.Location.RequestPermission(); + _status = "Location request no-op completed."; + } + + private bool IsConfigured => + !string.IsNullOrWhiteSpace(_oneSignalAppId) + && !_oneSignalAppId.StartsWith("YOUR-"); +} 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 000000000..3457a5b93 --- /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 000000000..b11262396 --- /dev/null +++ b/examples/demo-no-location/Packages/manifest.json @@ -0,0 +1,8 @@ +{ + "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" + } +} diff --git a/examples/demo-no-location/ProjectSettings/AndroidResolverDependencies.xml b/examples/demo-no-location/ProjectSettings/AndroidResolverDependencies.xml new file mode 100644 index 000000000..3eff04de1 --- /dev/null +++ b/examples/demo-no-location/ProjectSettings/AndroidResolverDependencies.xml @@ -0,0 +1,25 @@ + + + com.onesignal:core:5.9.3 + com.onesignal:notifications:5.9.3 + com.onesignal:in-app-messages:5.9.3 + + + + + + + + + + + + + + + + + + + + diff --git a/examples/demo-no-location/ProjectSettings/EditorBuildSettings.asset b/examples/demo-no-location/ProjectSettings/EditorBuildSettings.asset new file mode 100644 index 000000000..22a685594 --- /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 000000000..336ed657d --- /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 000000000..93d34980c --- /dev/null +++ b/examples/demo-no-location/ProjectSettings/ProjectSettings.asset @@ -0,0 +1,84 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!129 &1 +PlayerSettings: + m_ObjectHideFlags: 0 + serializedVersion: 26 + productGUID: 8c68141ccf5e4fdf8af18b27d8f8cf22 + AndroidProfiler: 0 + AndroidFilterTouchesWhenObscured: 0 + AndroidEnableSustainedPerformanceMode: 0 + defaultScreenOrientation: 1 + 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 + bundleVersion: 5.2.9 + preloadedAssets: [] + metroInputSource: 0 + wsaTransparentSwapchain: 0 + m_HolographicPauseOnTrackingLoss: 1 + xboxOneDisableKinectGpuReservation: 1 + xboxOneEnable7thCore: 1 + vrSettings: + enable360StereoCapture: 0 + enableFrameTimingStats: 0 + useHDRDisplay: 0 + applicationIdentifier: + Android: com.onesignal.example + iPhone: com.onesignal.example + buildNumber: + Standalone: 0 + iPhone: 1 + tvOS: 0 + overrideDefaultApplicationIdentifier: 1 + AndroidBundleVersionCode: 1 + AndroidMinSdkVersion: 25 + AndroidTargetSdkVersion: 34 + AndroidPreferredInstallLocation: 1 + AndroidPreferredDataLocation: 1 + AndroidSupportedAspectRatio: 1 + AndroidTargetArchitectures: 1 + AndroidSplashScreenScale: 0 + AndroidKeystoreName: + AndroidKeyaliasName: + iPhoneSdkVersion: 988 + iOSTargetOSVersionString: 13.0 + tvOSSdkVersion: 0 + tvOSRequireExtendedGameController: 0 + uIPrerenderedIcon: 0 + uIRequiresPersistentWiFi: 0 + uIRequiresFullScreen: 1 + uIStatusBarHidden: 1 + uIExitOnSuspend: 0 + appleEnableAutomaticSigning: 0 + appleDeveloperTeamID: + iOSManualProvisioningProfileID: + iOSManualProvisioningProfileType: 0 + tvOSManualProvisioningProfileID: + tvOSManualProvisioningProfileType: 0 + appleEnableProMotion: 0 + vulkanEnableSetSRGBWrite: 0 + m_SupportedAspectRatios: + 4:3: 1 + 5:4: 1 + 16:10: 1 + 16:9: 1 + Others: 1 + bundleIdentifier: com.onesignal.example + submitAnalytics: 1 + usePlayerLog: 1 diff --git a/examples/demo-no-location/ProjectSettings/ProjectVersion.txt b/examples/demo-no-location/ProjectSettings/ProjectVersion.txt new file mode 100644 index 000000000..f11019173 --- /dev/null +++ b/examples/demo-no-location/ProjectSettings/ProjectVersion.txt @@ -0,0 +1,2 @@ +m_EditorVersion: 6000.4.6f1 +m_EditorVersionWithRevision: 6000.4.6f1 (e5726377c19d) diff --git a/examples/demo-no-location/README.md b/examples/demo-no-location/README.md new file mode 100644 index 000000000..20c1573ae --- /dev/null +++ b/examples/demo-no-location/README.md @@ -0,0 +1,33 @@ +# OneSignal No-Location Demo + +Minimal Unity project for apps that use OneSignal without the native location module. + +Open this folder in Unity. The project setting below is checked in: + +```json +{ + "disableLocation": true +} +``` + +Before resolving Android dependencies or building iOS, confirm **OneSignal > Disable Location Module** is checked. + +## Configure + +Open `Assets/Scenes/Main.unity`, select the `OneSignal No Location Demo` GameObject, and set your OneSignal App ID on the `NoLocationDemo` component. + +## Android + +The resolver snapshot uses OneSignal native modules without the location artifact: + +```xml +com.onesignal:core:5.9.3 +com.onesignal:notifications:5.9.3 +com.onesignal:in-app-messages:5.9.3 +``` + +If you force-resolve again, keep the location module disabled. + +## App Code + +`NoLocationDemo.cs` initializes OneSignal, requests push permission, 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`. From 6e9c68fc5c8bd508e1c7db941618725aabed46ba Mon Sep 17 00:00:00 2001 From: Fadi George Date: Thu, 11 Jun 2026 18:17:26 -0700 Subject: [PATCH 03/21] docs(examples): clarify no-location setup --- examples/demo-no-location/README.md | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/examples/demo-no-location/README.md b/examples/demo-no-location/README.md index 20c1573ae..fba5764a2 100644 --- a/examples/demo-no-location/README.md +++ b/examples/demo-no-location/README.md @@ -2,7 +2,13 @@ Minimal Unity project for apps that use OneSignal without the native location module. -Open this folder in Unity. The project setting below is checked in: +Open this folder in Unity. Location is disabled with the same project setting used by the root README: + +```csharp +OneSignalSDK.OneSignalSDKSettings.DisableLocation = true; +``` + +The saved project setting is checked in as: ```json { From cd3a148557e35989cf4e657b26dacff84027016f Mon Sep 17 00:00:00 2001 From: Fadi George Date: Thu, 11 Jun 2026 18:23:00 -0700 Subject: [PATCH 04/21] feat(examples): add build scripts for no-location demo --- README.md | 4 +- .../Assets/Scripts/Editor.meta | 8 ++ .../Assets/Scripts/Editor/BuildScript.cs | 108 ++++++++++++++ .../Assets/Scripts/Editor/BuildScript.cs.meta | 11 ++ examples/demo-no-location/README.md | 19 ++- examples/demo-no-location/run-android.sh | 101 +++++++++++++ examples/demo-no-location/run-ios.sh | 134 ++++++++++++++++++ 7 files changed, 377 insertions(+), 8 deletions(-) create mode 100644 examples/demo-no-location/Assets/Scripts/Editor.meta create mode 100644 examples/demo-no-location/Assets/Scripts/Editor/BuildScript.cs create mode 100644 examples/demo-no-location/Assets/Scripts/Editor/BuildScript.cs.meta create mode 100755 examples/demo-no-location/run-android.sh create mode 100755 examples/demo-no-location/run-ios.sh diff --git a/README.md b/README.md index 8c4c4b6fb..4086640f3 100644 --- a/README.md +++ b/README.md @@ -154,12 +154,14 @@ with your own. There is a complete guide for this [in the plugin's README](com.o By default, the OneSignal Unity SDK includes OneSignal's native location module so `OneSignal.Location` works without extra setup. If your app does not use location features, select **OneSignal > Disable Location Module** in the Unity Editor before resolving Android dependencies or building iOS. -You can also set the same project setting from an editor script: +For automated Unity project setup, you can set the same Editor project setting from an Editor script before dependency resolution or build: ```C# OneSignalSDK.OneSignalSDKSettings.DisableLocation = true; ``` +Do not call this from runtime app code; it changes the Unity project configuration used by native dependency resolution. + When disabled, Android resolves OneSignal's native modules without the location artifact and iOS uses OneSignal pods without `OneSignalLocation`. `OneSignal.Location.RequestPermission()` and `OneSignal.Location.IsShared = ...` no-op on native builds without the location module, and `OneSignal.Location.IsShared` returns `false`. ## Usage 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 000000000..1924ad098 --- /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 000000000..292962da4 --- /dev/null +++ b/examples/demo-no-location/Assets/Scripts/Editor/BuildScript.cs @@ -0,0 +1,108 @@ +using System; +using System.IO; +using UnityEditor; +using UnityEditor.Build; +using UnityEditor.Build.Reporting; +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"; + + 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; + + var 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 + ); + + var report = BuildPipeline.BuildPlayer( + new BuildPlayerOptions + { + scenes = GetScenes(), + locationPathName = IOSOutputDir, + target = BuildTarget.iOS, + options = BuildOptions.None, + } + ); + HandleReport(report, IOSOutputDir); + } + + 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); + } +} 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 000000000..367b6be47 --- /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/README.md b/examples/demo-no-location/README.md index fba5764a2..7941b3a82 100644 --- a/examples/demo-no-location/README.md +++ b/examples/demo-no-location/README.md @@ -2,13 +2,7 @@ Minimal Unity project for apps that use OneSignal without the native location module. -Open this folder in Unity. Location is disabled with the same project setting used by the root README: - -```csharp -OneSignalSDK.OneSignalSDKSettings.DisableLocation = true; -``` - -The saved project setting is checked in as: +Open this folder in Unity. The saved project setting is checked in as: ```json { @@ -18,6 +12,17 @@ The saved project setting is checked in as: Before resolving Android dependencies or building iOS, confirm **OneSignal > Disable Location Module** is checked. +## Run + +Have an emulator or simulator booted, then run: + +```sh +./run-android.sh +./run-ios.sh +``` + +Both scripts accept `--no-install` to build only. `run-ios.sh` also supports `--open` after an Xcode project has been generated. + ## Configure Open `Assets/Scenes/Main.unity`, select the `OneSignal No Location Demo` GameObject, and set your OneSignal App ID on the `NoLocationDemo` component. diff --git a/examples/demo-no-location/run-android.sh b/examples/demo-no-location/run-android.sh new file mode 100755 index 000000000..46924b0f0 --- /dev/null +++ b/examples/demo-no-location/run-android.sh @@ -0,0 +1,101 @@ +#!/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 + +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 000000000..f40213946 --- /dev/null +++ b/examples/demo-no-location/run-ios.sh @@ -0,0 +1,134 @@ +#!/bin/sh +# Build the OneSignal Unity no-location demo for iOS simulator. +# +# Usage: +# ./run-ios.sh [--no-install] [--install-only] [--open] +set -eu + +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) +} + +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 + +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="" + + 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 From f93d84fecb4779be99c715583be2d9e8dbb4331a Mon Sep 17 00:00:00 2001 From: Fadi George Date: Thu, 11 Jun 2026 18:27:42 -0700 Subject: [PATCH 05/21] fix(examples): enforce no-location in scripted builds --- .../Editor/OneSignalAndroidDependencies.cs | 4 +- .../Editor/BuildPostProcessor.cs | 8 +-- .../Editor/OneSignaliOSDependencies.cs | 4 +- examples/demo-no-location/.gitignore | 54 +++++++++++++++++ .../Assets/Scripts/Editor/BuildScript.cs | 10 ++++ .../OneSignal.NoLocationDemo.Editor.asmdef | 17 ++++++ ...neSignal.NoLocationDemo.Editor.asmdef.meta | 7 +++ .../demo-no-location/Packages/manifest.json | 4 +- .../Packages/packages-lock.json | 44 ++++++++++++++ examples/demo-no-location/run-ios.sh | 59 +++++++++++++++++++ 10 files changed, 202 insertions(+), 9 deletions(-) create mode 100644 examples/demo-no-location/.gitignore create mode 100644 examples/demo-no-location/Assets/Scripts/Editor/OneSignal.NoLocationDemo.Editor.asmdef create mode 100644 examples/demo-no-location/Assets/Scripts/Editor/OneSignal.NoLocationDemo.Editor.asmdef.meta create mode 100644 examples/demo-no-location/Packages/packages-lock.json diff --git a/com.onesignal.unity.android/Editor/OneSignalAndroidDependencies.cs b/com.onesignal.unity.android/Editor/OneSignalAndroidDependencies.cs index 523397f72..7f0c99397 100644 --- a/com.onesignal.unity.android/Editor/OneSignalAndroidDependencies.cs +++ b/com.onesignal.unity.android/Editor/OneSignalAndroidDependencies.cs @@ -28,7 +28,7 @@ using System; using System.IO; using UnityEditor; -using Debug = UnityEngine.Debug; +using UnityDebug = UnityEngine.Debug; namespace OneSignalSDK { @@ -60,7 +60,7 @@ internal static void WriteDependencies() } catch (Exception exception) { - Debug.LogWarning( + UnityDebug.LogWarning( $"Could not update OneSignal Android dependencies at {_dependenciesPath}: {exception.Message}" ); } diff --git a/com.onesignal.unity.ios/Editor/BuildPostProcessor.cs b/com.onesignal.unity.ios/Editor/BuildPostProcessor.cs index 335ca1b5e..94143874f 100644 --- a/com.onesignal.unity.ios/Editor/BuildPostProcessor.cs +++ b/com.onesignal.unity.ios/Editor/BuildPostProcessor.cs @@ -60,7 +60,7 @@ using UnityEditor.Build; using UnityEditor.Build.Reporting; using UnityEditor.iOS.Xcode.Extensions; -using Debug = UnityEngine.Debug; +using UnityDebug = UnityEngine.Debug; using UnityEditor.Callbacks; namespace OneSignalSDK.iOS @@ -313,7 +313,7 @@ private void ExtensionAddPodsToTarget() if (!File.Exists(podfilePath)) { - Debug.LogError( + UnityDebug.LogError( $"Could not find Podfile. {ServiceExtensionFilename} will have errors." ); return; @@ -323,7 +323,7 @@ private void ExtensionAddPodsToTarget() if (!File.Exists(dependenciesFilePath)) { - Debug.LogError($"Could not find {DependenciesFilename}"); + UnityDebug.LogError($"Could not find {DependenciesFilename}"); return; } @@ -334,7 +334,7 @@ private void ExtensionAddPodsToTarget() if (!dependenciesRegex.IsMatch(dependenciesFile)) { - Debug.LogError( + UnityDebug.LogError( $"Could not read current iOS framework dependency version from {DependenciesFilename}" ); return; diff --git a/com.onesignal.unity.ios/Editor/OneSignaliOSDependencies.cs b/com.onesignal.unity.ios/Editor/OneSignaliOSDependencies.cs index 7ae8d2fbb..869b9d2b4 100644 --- a/com.onesignal.unity.ios/Editor/OneSignaliOSDependencies.cs +++ b/com.onesignal.unity.ios/Editor/OneSignaliOSDependencies.cs @@ -28,7 +28,7 @@ using System; using System.IO; using UnityEditor; -using Debug = UnityEngine.Debug; +using UnityDebug = UnityEngine.Debug; namespace OneSignalSDK.iOS { @@ -60,7 +60,7 @@ internal static void WriteDependencies() } catch (Exception exception) { - Debug.LogWarning( + UnityDebug.LogWarning( $"Could not update OneSignal iOS dependencies at {_dependenciesPath}: {exception.Message}" ); } diff --git a/examples/demo-no-location/.gitignore b/examples/demo-no-location/.gitignore new file mode 100644 index 000000000..55b9b40c9 --- /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/Scripts/Editor/BuildScript.cs b/examples/demo-no-location/Assets/Scripts/Editor/BuildScript.cs index 292962da4..8a065826a 100644 --- a/examples/demo-no-location/Assets/Scripts/Editor/BuildScript.cs +++ b/examples/demo-no-location/Assets/Scripts/Editor/BuildScript.cs @@ -13,6 +13,8 @@ public static class BuildScript public static void BuildAndroidEmulator() { + EnforceNoLocationBuild(); + var outputPath = Path.Combine(AndroidOutputDir, ApkName); Directory.CreateDirectory(AndroidOutputDir); @@ -55,6 +57,8 @@ public static void BuildAndroidEmulator() public static void BuildiOSSimulator() { + EnforceNoLocationBuild(); + Directory.CreateDirectory(IOSOutputDir); PlayerSettings.SetScriptingBackend(NamedBuildTarget.iOS, ScriptingImplementation.IL2CPP); @@ -83,6 +87,12 @@ public static void BuildiOSSimulator() HandleReport(report, IOSOutputDir); } + private static void EnforceNoLocationBuild() + { + // Scripted builds should stay no-location even if the Editor menu setting was toggled. + OneSignalSDK.OneSignalSDKSettings.DisableLocation = true; + } + private static string[] GetScenes() { var scenes = EditorBuildSettings.scenes; 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 000000000..3d7cc0ad4 --- /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 000000000..61bd464c4 --- /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/Packages/manifest.json b/examples/demo-no-location/Packages/manifest.json index b11262396..ce52b4648 100644 --- a/examples/demo-no-location/Packages/manifest.json +++ b/examples/demo-no-location/Packages/manifest.json @@ -3,6 +3,8 @@ "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.androidjni": "1.0.0", + "com.unity.modules.imgui": "1.0.0", + "com.unity.modules.jsonserialize": "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 000000000..2b1cfbcb9 --- /dev/null +++ b/examples/demo-no-location/Packages/packages-lock.json @@ -0,0 +1,44 @@ +{ + "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": {} + } + } +} diff --git a/examples/demo-no-location/run-ios.sh b/examples/demo-no-location/run-ios.sh index f40213946..bd39a30b4 100755 --- a/examples/demo-no-location/run-ios.sh +++ b/examples/demo-no-location/run-ios.sh @@ -65,6 +65,63 @@ for r,devs in d['devices'].items(): SIM_NAME=$(echo "$LINE" | cut -d'|' -f2) } +ensure_podfile() { + [ -f "$XCODE_DIR/Podfile" ] && return + + DEPS="$SCRIPT_DIR/../../com.onesignal.unity.ios/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 "" @@ -97,6 +154,8 @@ else 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) From ccf13deda6f1873a6a24d3f4ee302ad8f72501fc Mon Sep 17 00:00:00 2001 From: Fadi George Date: Mon, 29 Jun 2026 16:08:57 -0700 Subject: [PATCH 06/21] chore: bump Android to 5.9.5, iOS to 5.5.3 --- .../Editor/OneSignalAndroidDependencies.cs | 2 +- .../Editor/OneSignalAndroidDependencies.xml | 4 +++- com.onesignal.unity.ios/Editor/OneSignaliOSDependencies.cs | 2 +- com.onesignal.unity.ios/Editor/OneSignaliOSDependencies.xml | 3 ++- .../ProjectSettings/AndroidResolverDependencies.xml | 6 +++--- examples/demo-no-location/README.md | 6 +++--- 6 files changed, 13 insertions(+), 10 deletions(-) diff --git a/com.onesignal.unity.android/Editor/OneSignalAndroidDependencies.cs b/com.onesignal.unity.android/Editor/OneSignalAndroidDependencies.cs index 7f0c99397..7c5291913 100644 --- a/com.onesignal.unity.android/Editor/OneSignalAndroidDependencies.cs +++ b/com.onesignal.unity.android/Editor/OneSignalAndroidDependencies.cs @@ -66,7 +66,7 @@ internal static void WriteDependencies() } } - private const string Version = "5.9.3"; + private const string Version = "5.9.5"; private static readonly string _dependenciesPath = Path.Combine( "Packages", diff --git a/com.onesignal.unity.android/Editor/OneSignalAndroidDependencies.xml b/com.onesignal.unity.android/Editor/OneSignalAndroidDependencies.xml index e7a3cacaf..f41da55ad 100644 --- a/com.onesignal.unity.android/Editor/OneSignalAndroidDependencies.xml +++ b/com.onesignal.unity.android/Editor/OneSignalAndroidDependencies.xml @@ -3,6 +3,8 @@ https://repo.maven.apache.org/maven2 - + + + diff --git a/com.onesignal.unity.ios/Editor/OneSignaliOSDependencies.cs b/com.onesignal.unity.ios/Editor/OneSignaliOSDependencies.cs index 869b9d2b4..be596119a 100644 --- a/com.onesignal.unity.ios/Editor/OneSignaliOSDependencies.cs +++ b/com.onesignal.unity.ios/Editor/OneSignaliOSDependencies.cs @@ -66,7 +66,7 @@ internal static void WriteDependencies() } } - private const string Version = "5.5.2"; + private const string Version = "5.5.3"; private static readonly string _dependenciesPath = Path.Combine( "Packages", diff --git a/com.onesignal.unity.ios/Editor/OneSignaliOSDependencies.xml b/com.onesignal.unity.ios/Editor/OneSignaliOSDependencies.xml index b97318714..15c9f1bea 100644 --- a/com.onesignal.unity.ios/Editor/OneSignaliOSDependencies.xml +++ b/com.onesignal.unity.ios/Editor/OneSignaliOSDependencies.xml @@ -1,5 +1,6 @@ - + + diff --git a/examples/demo-no-location/ProjectSettings/AndroidResolverDependencies.xml b/examples/demo-no-location/ProjectSettings/AndroidResolverDependencies.xml index 3eff04de1..e50579a32 100644 --- a/examples/demo-no-location/ProjectSettings/AndroidResolverDependencies.xml +++ b/examples/demo-no-location/ProjectSettings/AndroidResolverDependencies.xml @@ -1,8 +1,8 @@ - com.onesignal:core:5.9.3 - com.onesignal:notifications:5.9.3 - com.onesignal:in-app-messages:5.9.3 + 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/README.md b/examples/demo-no-location/README.md index 7941b3a82..e4938bc36 100644 --- a/examples/demo-no-location/README.md +++ b/examples/demo-no-location/README.md @@ -32,9 +32,9 @@ Open `Assets/Scenes/Main.unity`, select the `OneSignal No Location Demo` GameObj The resolver snapshot uses OneSignal native modules without the location artifact: ```xml -com.onesignal:core:5.9.3 -com.onesignal:notifications:5.9.3 -com.onesignal:in-app-messages:5.9.3 +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. From 688d184ee3d62b628d06f7c6f7a41c1fdef53913 Mon Sep 17 00:00:00 2001 From: Fadi George Date: Mon, 29 Jun 2026 16:10:36 -0700 Subject: [PATCH 07/21] feat(examples): redesign no-location demo UI --- .../Assets/Scripts/NoLocationDemo.cs | 265 +++++- .../ProjectSettings/ProjectSettings.asset | 856 +++++++++++++++++- .../ProjectSettings/ProjectVersion.txt | 4 +- .../demo/ProjectSettings/ProjectVersion.txt | 4 +- 4 files changed, 1086 insertions(+), 43 deletions(-) diff --git a/examples/demo-no-location/Assets/Scripts/NoLocationDemo.cs b/examples/demo-no-location/Assets/Scripts/NoLocationDemo.cs index d2043162d..8dead7925 100644 --- a/examples/demo-no-location/Assets/Scripts/NoLocationDemo.cs +++ b/examples/demo-no-location/Assets/Scripts/NoLocationDemo.cs @@ -7,6 +7,32 @@ 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 _status = "Set your OneSignal App ID in the Inspector."; private bool _initialized; @@ -24,27 +50,225 @@ private void Start() private void OnGUI() { - const int margin = 24; - const int buttonHeight = 56; - var width = Screen.width - margin * 2; + 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 = 520f + 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; - GUILayout.BeginArea(new Rect(margin, margin, width, Screen.height - margin * 2)); - GUILayout.Label("OneSignal No-Location Demo"); - GUILayout.Space(12); - GUILayout.Label(_status); - GUILayout.Space(12); + var cardHeight = 196f; + GUI.Box(new Rect(x, y, width, cardHeight), GUIContent.none, _cardStyle); - if (GUILayout.Button("Request Push Permission", GUILayout.Height(buttonHeight))) + var contentX = x + 12f; + var contentWidth = width - 24f; + DrawKeyValueRow( + contentX, + y + 12f, + contentWidth, + "Permission", + _initialized + ? OneSignal.Notifications.Permission + ? "Granted" + : "Not granted" + : "Not initialized", + _valueStyle + ); + DrawDivider(contentX, y + 45f, contentWidth); + DrawKeyValueRow(contentX, y + 58f, contentWidth, "Status", _status, _valueStyle); + + if (GUI.Button(new Rect(contentX, y + 104f, contentWidth, 48f), "REQUEST PERMISSION", _buttonStyle)) RequestPushPermission(); - if (GUILayout.Button("Test Location Request No-Op", GUILayout.Height(buttonHeight))) - TestLocationRequest(); + return y + cardHeight + 24f; + } + + private void DrawLocationSection(float x, float y, float width) + { + DrawSectionHeader(x, y, "LOCATION MODULE"); + y += 24f; + + var cardHeight = 188f; + GUI.Box(new Rect(x, y, width, cardHeight), GUIContent.none, _cardStyle); - GUILayout.Space(12); - GUILayout.Label( - $"Location IsShared: {(_initialized ? OneSignal.Location.IsShared.ToString() : "Not initialized")}" + 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 ); - GUILayout.EndArea(); + + var locationStatus = _initialized + ? $"Location IsShared: {OneSignal.Location.IsShared}" + : "Location test not run"; + GUI.Label(new Rect(contentX, y + 94f, contentWidth, 28f), locationStatus, _bodyStyle); + + if ( + GUI.Button( + new Rect(contentX, y + 128f, 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() @@ -74,4 +298,15 @@ private void TestLocationRequest() private bool IsConfigured => !string.IsNullOrWhiteSpace(_oneSignalAppId) && !_oneSignalAppId.StartsWith("YOUR-"); + + 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/ProjectSettings/ProjectSettings.asset b/examples/demo-no-location/ProjectSettings/ProjectSettings.asset index 93d34980c..6f7fe2382 100644 --- a/examples/demo-no-location/ProjectSettings/ProjectSettings.asset +++ b/examples/demo-no-location/ProjectSettings/ProjectSettings.asset @@ -3,7 +3,7 @@ --- !u!129 &1 PlayerSettings: m_ObjectHideFlags: 0 - serializedVersion: 26 + serializedVersion: 28 productGUID: 8c68141ccf5e4fdf8af18b27d8f8cf22 AndroidProfiler: 0 AndroidFilterTouchesWhenObscured: 0 @@ -27,22 +27,148 @@ PlayerSettings: 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: 1 + androidRenderOutsideSafeArea: 1 + 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 - m_HolographicPauseOnTrackingLoss: 1 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 @@ -51,34 +177,716 @@ PlayerSettings: AndroidTargetSdkVersion: 34 AndroidPreferredInstallLocation: 1 AndroidPreferredDataLocation: 1 - AndroidSupportedAspectRatio: 1 - AndroidTargetArchitectures: 1 - AndroidSplashScreenScale: 0 - AndroidKeystoreName: - AndroidKeyaliasName: - iPhoneSdkVersion: 988 - iOSTargetOSVersionString: 13.0 + 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 - appleDeveloperTeamID: - iOSManualProvisioningProfileID: - iOSManualProvisioningProfileType: 0 - tvOSManualProvisioningProfileID: - tvOSManualProvisioningProfileType: 0 + iOSRequireARKit: 0 + iOSAutomaticallyDetectAndAddCapabilities: 1 appleEnableProMotion: 0 - vulkanEnableSetSRGBWrite: 0 - m_SupportedAspectRatios: - 4:3: 1 - 5:4: 1 - 16:10: 1 - 16:9: 1 - Others: 1 - bundleIdentifier: com.onesignal.example - submitAnalytics: 1 - usePlayerLog: 1 + shaderPrecisionModel: 0 + clonedFromGUID: 00000000000000000000000000000000 + templatePackageId: + templateDefaultScene: + useCustomMainManifest: 0 + useCustomLauncherManifest: 0 + useCustomMainGradleTemplate: 0 + useCustomLauncherGradleManifest: 0 + useCustomBaseGradleTemplate: 0 + useCustomGradlePropertiesTemplate: 0 + useCustomGradleSettingsTemplate: 0 + useCustomProguardFile: 0 + AndroidTargetArchitectures: 1 + 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: 0 + 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: + iPhone: 1 + il2cppCompilerConfiguration: {} + il2cppCodeGeneration: + iPhone: 1 + il2cppStacktraceInformation: {} + managedStrippingLevel: + 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 index f11019173..29501ff03 100644 --- a/examples/demo-no-location/ProjectSettings/ProjectVersion.txt +++ b/examples/demo-no-location/ProjectSettings/ProjectVersion.txt @@ -1,2 +1,2 @@ -m_EditorVersion: 6000.4.6f1 -m_EditorVersionWithRevision: 6000.4.6f1 (e5726377c19d) +m_EditorVersion: 6000.4.11f1 +m_EditorVersionWithRevision: 6000.4.11f1 (b0a1d6caadd2) diff --git a/examples/demo/ProjectSettings/ProjectVersion.txt b/examples/demo/ProjectSettings/ProjectVersion.txt index 67039ec60..29501ff03 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) From a5154314e0d07a358f80e9af29a98d3125491a83 Mon Sep 17 00:00:00 2001 From: Fadi George Date: Mon, 29 Jun 2026 16:13:43 -0700 Subject: [PATCH 08/21] docs(examples): expand no-location demo README --- examples/demo-no-location/.env.example | 4 ++ examples/demo-no-location/README.md | 68 +++++++++++++++++++++++--- 2 files changed, 65 insertions(+), 7 deletions(-) create mode 100644 examples/demo-no-location/.env.example diff --git a/examples/demo-no-location/.env.example b/examples/demo-no-location/.env.example new file mode 100644 index 000000000..488173667 --- /dev/null +++ b/examples/demo-no-location/.env.example @@ -0,0 +1,4 @@ +# The Unity no-location demo does not load this file automatically. +# Use this as a reference value to copy into the NoLocationDemo component +# in Assets/Scenes/Main.unity. +ONESIGNAL_APP_ID=YOUR-ONESIGNAL-APP-ID diff --git a/examples/demo-no-location/README.md b/examples/demo-no-location/README.md index e4938bc36..e9886a184 100644 --- a/examples/demo-no-location/README.md +++ b/examples/demo-no-location/README.md @@ -2,7 +2,7 @@ Minimal Unity project for apps that use OneSignal without the native location module. -Open this folder in Unity. The saved project setting is checked in as: +The saved OneSignal project setting is checked in as: ```json { @@ -12,22 +12,59 @@ Open this folder in Unity. The saved project setting is checked in as: Before resolving Android dependencies or building iOS, confirm **OneSignal > Disable Location Module** is checked. -## Run +## Configure App ID -Have an emulator or simulator booted, then run: +This demo does **not** read `.env` files or `ONESIGNAL_APP_ID` environment variables. +`.env.example` is provided only as a reference for the value to configure in Unity. + +To configure the app ID: + +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 ``` -Both scripts accept `--no-install` to build only. `run-ios.sh` also supports `--open` after an Xcode project has been generated. +Useful options: + +```sh +./run-ios.sh --no-install +./run-ios.sh --install-only +./run-ios.sh --open +``` -## Configure +Set `UNITY_PATH` if you want to use a specific Unity executable. -Open `Assets/Scenes/Main.unity`, select the `OneSignal No Location Demo` GameObject, and set your OneSignal App ID on the `NoLocationDemo` component. +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. -## Android +## Native Dependencies + +### Android The resolver snapshot uses OneSignal native modules without the location artifact: @@ -39,6 +76,23 @@ The resolver snapshot uses OneSignal native modules without the location artifac 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, 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`. + +## 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. From b522eaea7ebf75540c4be288d0103273ac06376e Mon Sep 17 00:00:00 2001 From: Fadi George Date: Mon, 29 Jun 2026 16:59:44 -0700 Subject: [PATCH 09/21] feat(examples): inject app ID during scripted builds --- examples/demo-no-location/.env.example | 6 +- .../Assets/Scripts/Editor/BuildScript.cs | 174 ++++++++++++++++-- examples/demo-no-location/README.md | 17 +- 3 files changed, 172 insertions(+), 25 deletions(-) diff --git a/examples/demo-no-location/.env.example b/examples/demo-no-location/.env.example index 488173667..69d154c0a 100644 --- a/examples/demo-no-location/.env.example +++ b/examples/demo-no-location/.env.example @@ -1,4 +1,4 @@ -# The Unity no-location demo does not load this file automatically. -# Use this as a reference value to copy into the NoLocationDemo component -# in Assets/Scenes/Main.unity. +# 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/Assets/Scripts/Editor/BuildScript.cs b/examples/demo-no-location/Assets/Scripts/Editor/BuildScript.cs index 8a065826a..7e05aa417 100644 --- a/examples/demo-no-location/Assets/Scripts/Editor/BuildScript.cs +++ b/examples/demo-no-location/Assets/Scripts/Editor/BuildScript.cs @@ -3,6 +3,7 @@ using UnityEditor; using UnityEditor.Build; using UnityEditor.Build.Reporting; +using UnityEditor.SceneManagement; using UnityEngine; public static class BuildScript @@ -10,6 +11,10 @@ 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() { @@ -42,16 +47,19 @@ public static void BuildAndroidEmulator() EditorUserBuildSettings.exportAsGoogleAndroidProject = false; EditorUserBuildSettings.buildAppBundle = false; - var report = BuildPipeline.BuildPlayer( - new BuildPlayerOptions - { - scenes = GetScenes(), - locationPathName = outputPath, - target = BuildTarget.Android, - subtarget = 0, - options = BuildOptions.None, - } - ); + BuildReport report; + using (ApplyConfiguredAppId()) + report = BuildPipeline.BuildPlayer( + new BuildPlayerOptions + { + scenes = GetScenes(), + locationPathName = outputPath, + target = BuildTarget.Android, + subtarget = 0, + options = BuildOptions.None, + } + ); + HandleReport(report, outputPath); } @@ -75,15 +83,18 @@ public static void BuildiOSSimulator() Il2CppCompilerConfiguration.Release ); - var report = BuildPipeline.BuildPlayer( - new BuildPlayerOptions - { - scenes = GetScenes(), - locationPathName = IOSOutputDir, - target = BuildTarget.iOS, - options = BuildOptions.None, - } - ); + BuildReport report; + using (ApplyConfiguredAppId()) + report = BuildPipeline.BuildPlayer( + new BuildPlayerOptions + { + scenes = GetScenes(), + locationPathName = IOSOutputDir, + target = BuildTarget.iOS, + options = BuildOptions.None, + } + ); + HandleReport(report, IOSOutputDir); } @@ -93,6 +104,108 @@ private static void EnforceNoLocationBuild() OneSignalSDK.OneSignalSDKSettings.DisableLocation = true; } + 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; @@ -115,4 +228,27 @@ private static void HandleReport(BuildReport report, string outputPath) ); 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/README.md b/examples/demo-no-location/README.md index e9886a184..43146e482 100644 --- a/examples/demo-no-location/README.md +++ b/examples/demo-no-location/README.md @@ -14,10 +14,21 @@ Before resolving Android dependencies or building iOS, confirm **OneSignal > Dis ## Configure App ID -This demo does **not** read `.env` files or `ONESIGNAL_APP_ID` environment variables. -`.env.example` is provided only as a reference for the value to configure in Unity. +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. -To configure the app ID: +```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. From 54775fcb20a3c0d0fc376b7e1bb01078687fede2 Mon Sep 17 00:00:00 2001 From: Fadi George Date: Mon, 29 Jun 2026 17:36:23 -0700 Subject: [PATCH 10/21] fix(examples): preserve OneSignal assemblies in no-location demo The scripted iOS/Android builds use ManagedStrippingLevel.High, which stripped the reflection-only OneSignaliOS/OneSignalAndroid platform implementations. _getDefaultInstance() then threw "Sequence contains no elements", so OneSignal never initialized and the permission prompt never appeared. Add a link.xml (matching the main demo) to preserve the OneSignal assemblies, and align the demo UI with the .NET no-location demo (Permission + Push ID rows). Co-authored-by: Cursor --- .../demo-no-location/Assets/OneSignal.meta | 8 +++ .../Assets/OneSignal/link.xml | 5 ++ .../Assets/OneSignal/link.xml.meta | 7 +++ .../Assets/Scripts/NoLocationDemo.cs | 54 ++++++++++++------- 4 files changed, 54 insertions(+), 20 deletions(-) create mode 100644 examples/demo-no-location/Assets/OneSignal.meta create mode 100644 examples/demo-no-location/Assets/OneSignal/link.xml create mode 100644 examples/demo-no-location/Assets/OneSignal/link.xml.meta diff --git a/examples/demo-no-location/Assets/OneSignal.meta b/examples/demo-no-location/Assets/OneSignal.meta new file mode 100644 index 000000000..d46fbe8ba --- /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/link.xml b/examples/demo-no-location/Assets/OneSignal/link.xml new file mode 100644 index 000000000..63b9781b1 --- /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 000000000..baeb01634 --- /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/Scripts/NoLocationDemo.cs b/examples/demo-no-location/Assets/Scripts/NoLocationDemo.cs index 8dead7925..8f9633151 100644 --- a/examples/demo-no-location/Assets/Scripts/NoLocationDemo.cs +++ b/examples/demo-no-location/Assets/Scripts/NoLocationDemo.cs @@ -33,7 +33,7 @@ public sealed class NoLocationDemo : MonoBehaviour private Texture2D _backgroundTexture; private Vector2 _scrollPosition; - private string _status = "Set your OneSignal App ID in the Inspector."; + private string _locationStatus = "Location test not run"; private bool _initialized; private void Start() @@ -45,7 +45,6 @@ private void Start() OneSignal.Initialize(_oneSignalAppId); _initialized = true; - _status = "OneSignal initialized without native location module."; } private void OnGUI() @@ -75,7 +74,7 @@ private void OnGUI() var scrollRect = new Rect(0, headerHeight, logicalWidth, logicalHeight - headerHeight); var contentWidth = logicalWidth - 32f; - var contentHeight = 520f + bottomInset; + var contentHeight = 560f + bottomInset; _scrollPosition = GUI.BeginScrollView( scrollRect, @@ -118,25 +117,28 @@ private float DrawPushSection(float x, float y, float width) DrawSectionHeader(x, y, "PUSH"); y += 24f; - var cardHeight = 196f; + var cardHeight = 164f; 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", - _initialized - ? OneSignal.Notifications.Permission - ? "Granted" - : "Not granted" - : "Not initialized", + permission, _valueStyle ); DrawDivider(contentX, y + 45f, contentWidth); - DrawKeyValueRow(contentX, y + 58f, contentWidth, "Status", _status, _valueStyle); + DrawKeyValueRow(contentX, y + 58f, contentWidth, "Push ID", pushId, _valueStyle); if (GUI.Button(new Rect(contentX, y + 104f, contentWidth, 48f), "REQUEST PERMISSION", _buttonStyle)) RequestPushPermission(); @@ -160,10 +162,7 @@ private void DrawLocationSection(float x, float y, float width) _bodyStyle ); - var locationStatus = _initialized - ? $"Location IsShared: {OneSignal.Location.IsShared}" - : "Location test not run"; - GUI.Label(new Rect(contentX, y + 94f, contentWidth, 28f), locationStatus, _bodyStyle); + GUI.Label(new Rect(contentX, y + 94f, contentWidth, 28f), _locationStatus, _bodyStyle); if ( GUI.Button( @@ -275,30 +274,45 @@ private async void RequestPushPermission() { if (!_initialized) { - _status = "Initialize OneSignal before requesting push permission."; return; } - var granted = await OneSignal.Notifications.RequestPermissionAsync(false); - _status = $"Push permission: {(granted ? "granted" : "not granted")}"; + try + { + await OneSignal.Notifications.RequestPermissionAsync(false); + } + catch (System.Exception exception) + { + Debug.LogError($"[NoLocationDemo] Push permission request failed: {exception.Message}"); + } } private void TestLocationRequest() { if (!_initialized) { - _status = "Initialize OneSignal before testing location."; + _locationStatus = "Initialize OneSignal before testing location."; return; } - OneSignal.Location.RequestPermission(); - _status = "Location request no-op completed."; + 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); From bee7273d847e988d9702a1e75783c3a83a507aea Mon Sep 17 00:00:00 2001 From: Fadi George Date: Mon, 29 Jun 2026 17:38:56 -0700 Subject: [PATCH 11/21] docs(examples): note required link.xml in no-location demo Explain that Assets/OneSignal/link.xml must not be deleted: scripted builds use high managed stripping and the OneSignal platform classes are reflection-resolved, so removing it breaks SDK initialization. Co-authored-by: Cursor --- examples/demo-no-location/README.md | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/examples/demo-no-location/README.md b/examples/demo-no-location/README.md index 43146e482..ec921335f 100644 --- a/examples/demo-no-location/README.md +++ b/examples/demo-no-location/README.md @@ -102,6 +102,14 @@ The notification service extension still uses `OneSignalXCFramework/OneSignalExt `NoLocationDemo.cs` initializes OneSignal, requests push permission, 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`. +## 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. From 01aea3f7697170a0ff41a3e94fa1d18a7ebb9095 Mon Sep 17 00:00:00 2001 From: Fadi George Date: Mon, 29 Jun 2026 17:50:27 -0700 Subject: [PATCH 12/21] feat: [SDK-4774] add test notification button to no-location demo Adds a "Send Test Notification" button that posts to the OneSignal REST API targeting the current push subscription, matching the .NET and Capacitor no-location demos. Enables the UnityWebRequest module needed for the request. Co-authored-by: Cursor --- .../Assets/Scripts/NoLocationDemo.cs | 81 ++++++++++++++++++- .../demo-no-location/Packages/manifest.json | 3 +- examples/demo-no-location/README.md | 4 +- 3 files changed, 83 insertions(+), 5 deletions(-) diff --git a/examples/demo-no-location/Assets/Scripts/NoLocationDemo.cs b/examples/demo-no-location/Assets/Scripts/NoLocationDemo.cs index 8f9633151..b1d739950 100644 --- a/examples/demo-no-location/Assets/Scripts/NoLocationDemo.cs +++ b/examples/demo-no-location/Assets/Scripts/NoLocationDemo.cs @@ -1,6 +1,10 @@ +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 { @@ -34,6 +38,7 @@ public sealed class NoLocationDemo : MonoBehaviour private Vector2 _scrollPosition; private string _locationStatus = "Location test not run"; + private string _pushStatus = string.Empty; private bool _initialized; private void Start() @@ -74,7 +79,7 @@ private void OnGUI() var scrollRect = new Rect(0, headerHeight, logicalWidth, logicalHeight - headerHeight); var contentWidth = logicalWidth - 32f; - var contentHeight = 560f + bottomInset; + var contentHeight = 690f + bottomInset; _scrollPosition = GUI.BeginScrollView( scrollRect, @@ -117,7 +122,8 @@ private float DrawPushSection(float x, float y, float width) DrawSectionHeader(x, y, "PUSH"); y += 24f; - var cardHeight = 164f; + 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; @@ -140,9 +146,15 @@ private float DrawPushSection(float x, float y, float width) DrawDivider(contentX, y + 45f, contentWidth); DrawKeyValueRow(contentX, y + 58f, contentWidth, "Push ID", pushId, _valueStyle); - if (GUI.Button(new Rect(contentX, y + 104f, contentWidth, 48f), "REQUEST PERMISSION", _buttonStyle)) + 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; } @@ -287,6 +299,69 @@ private async void RequestPushPermission() } } + 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) diff --git a/examples/demo-no-location/Packages/manifest.json b/examples/demo-no-location/Packages/manifest.json index ce52b4648..7012c1bbc 100644 --- a/examples/demo-no-location/Packages/manifest.json +++ b/examples/demo-no-location/Packages/manifest.json @@ -5,6 +5,7 @@ "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.jsonserialize": "1.0.0", + "com.unity.modules.unitywebrequest": "1.0.0" } } diff --git a/examples/demo-no-location/README.md b/examples/demo-no-location/README.md index ec921335f..edad125f0 100644 --- a/examples/demo-no-location/README.md +++ b/examples/demo-no-location/README.md @@ -100,7 +100,9 @@ The notification service extension still uses `OneSignalXCFramework/OneSignalExt ## App Code -`NoLocationDemo.cs` initializes OneSignal, requests push permission, 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`. +`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`) From 06b4c0686def22c9c0870d40969bea0cd4bced1b Mon Sep 17 00:00:00 2001 From: Fadi George Date: Mon, 29 Jun 2026 17:50:50 -0700 Subject: [PATCH 13/21] chore(examples): add UnityWebRequest package lock entry --- examples/demo-no-location/Packages/packages-lock.json | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/examples/demo-no-location/Packages/packages-lock.json b/examples/demo-no-location/Packages/packages-lock.json index 2b1cfbcb9..2f650a2cd 100644 --- a/examples/demo-no-location/Packages/packages-lock.json +++ b/examples/demo-no-location/Packages/packages-lock.json @@ -39,6 +39,12 @@ "depth": 0, "source": "builtin", "dependencies": {} + }, + "com.unity.modules.unitywebrequest": { + "version": "1.0.0", + "depth": 0, + "source": "builtin", + "dependencies": {} } } } From 79d56f060b4a5a97b00925e11fcf861d438073c6 Mon Sep 17 00:00:00 2001 From: Fadi George Date: Mon, 29 Jun 2026 17:59:00 -0700 Subject: [PATCH 14/21] fix(examples): prefer brew rsync over openrsync --- examples/demo-no-location/README.md | 6 ++++++ examples/demo-no-location/run-ios.sh | 14 ++++++++++++++ 2 files changed, 20 insertions(+) diff --git a/examples/demo-no-location/README.md b/examples/demo-no-location/README.md index edad125f0..bd205322f 100644 --- a/examples/demo-no-location/README.md +++ b/examples/demo-no-location/README.md @@ -61,6 +61,12 @@ Have an iOS simulator booted, then run: ./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 diff --git a/examples/demo-no-location/run-ios.sh b/examples/demo-no-location/run-ios.sh index bd39a30b4..56bedd3ce 100755 --- a/examples/demo-no-location/run-ios.sh +++ b/examples/demo-no-location/run-ios.sh @@ -167,6 +167,20 @@ if [ "$INSTALL" = true ] && [ -n "$SIM_UDID" ]; then 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" \ From 6423e81f74066fef0f675bdd5cba9bb899d13b99 Mon Sep 17 00:00:00 2001 From: Fadi George Date: Mon, 29 Jun 2026 18:08:20 -0700 Subject: [PATCH 15/21] fix(examples): expand location card UI height --- .../demo-no-location/Assets/Scripts/NoLocationDemo.cs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/examples/demo-no-location/Assets/Scripts/NoLocationDemo.cs b/examples/demo-no-location/Assets/Scripts/NoLocationDemo.cs index b1d739950..763b2775f 100644 --- a/examples/demo-no-location/Assets/Scripts/NoLocationDemo.cs +++ b/examples/demo-no-location/Assets/Scripts/NoLocationDemo.cs @@ -79,7 +79,7 @@ private void OnGUI() var scrollRect = new Rect(0, headerHeight, logicalWidth, logicalHeight - headerHeight); var contentWidth = logicalWidth - 32f; - var contentHeight = 690f + bottomInset; + var contentHeight = 740f + bottomInset; _scrollPosition = GUI.BeginScrollView( scrollRect, @@ -163,7 +163,7 @@ private void DrawLocationSection(float x, float y, float width) DrawSectionHeader(x, y, "LOCATION MODULE"); y += 24f; - var cardHeight = 188f; + var cardHeight = 240f; GUI.Box(new Rect(x, y, width, cardHeight), GUIContent.none, _cardStyle); var contentX = x + 12f; @@ -174,11 +174,11 @@ private void DrawLocationSection(float x, float y, float width) _bodyStyle ); - GUI.Label(new Rect(contentX, y + 94f, contentWidth, 28f), _locationStatus, _bodyStyle); + GUI.Label(new Rect(contentX, y + 94f, contentWidth, 72f), _locationStatus, _bodyStyle); if ( GUI.Button( - new Rect(contentX, y + 128f, contentWidth, 48f), + new Rect(contentX, y + 180f, contentWidth, 48f), "TEST LOCATION REQUEST", _outlineButtonStyle ) From c56f7f3b773baad223c1970570deb1bf33e4b8f4 Mon Sep 17 00:00:00 2001 From: Fadi George Date: Mon, 29 Jun 2026 18:10:41 -0700 Subject: [PATCH 16/21] fix(ios): log error when location module missing --- .../Plugins/iOS/OneSignalUnityBridgeLocation.mm | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/com.onesignal.unity.ios/Runtime/Plugins/iOS/OneSignalUnityBridgeLocation.mm b/com.onesignal.unity.ios/Runtime/Plugins/iOS/OneSignalUnityBridgeLocation.mm index 3bc6e27fa..a5c6c2d58 100644 --- a/com.onesignal.unity.ios/Runtime/Plugins/iOS/OneSignalUnityBridgeLocation.mm +++ b/com.onesignal.unity.ios/Runtime/Plugins/iOS/OneSignalUnityBridgeLocation.mm @@ -31,9 +31,12 @@ #import #import +static NSString *const OneSignalLocationModuleNotFoundMessage = @"OneSignalLocation not found. In order to use OneSignal's location features the OneSignalLocation module must be added."; + extern "C" { bool _oneSignalLocationGetIsShared() { #if ONESIGNAL_DISABLE_LOCATION + [OneSignalLog onesignalLog:ONE_S_LL_ERROR message:OneSignalLocationModuleNotFoundMessage]; return false; #else return [OneSignal.Location isShared]; @@ -41,13 +44,17 @@ bool _oneSignalLocationGetIsShared() { } void _oneSignalLocationSetIsShared(bool shared) { -#if !ONESIGNAL_DISABLE_LOCATION +#if ONESIGNAL_DISABLE_LOCATION + [OneSignalLog onesignalLog:ONE_S_LL_ERROR message:OneSignalLocationModuleNotFoundMessage]; +#else [OneSignal.Location setShared:shared]; #endif } void _oneSignalLocationRequestPermission() { -#if !ONESIGNAL_DISABLE_LOCATION +#if ONESIGNAL_DISABLE_LOCATION + [OneSignalLog onesignalLog:ONE_S_LL_ERROR message:OneSignalLocationModuleNotFoundMessage]; +#else [OneSignal.Location requestPermission]; #endif } From f46893a039c081d999e1dacc01904918fe5c9778 Mon Sep 17 00:00:00 2001 From: Fadi George Date: Mon, 29 Jun 2026 18:51:22 -0700 Subject: [PATCH 17/21] chore(examples): configure Android build for no-location demo --- examples/demo-no-location/Assets/Plugins.meta | 8 +++ .../Assets/Plugins/Android.meta | 8 +++ .../Plugins/Android/gradleTemplate.properties | 10 +++ .../Android/gradleTemplate.properties.meta | 7 ++ .../Plugins/Android/mainTemplate.gradle | 66 +++++++++++++++++++ .../Plugins/Android/mainTemplate.gradle.meta | 7 ++ .../Assets/Plugins/Android/proguard-user.txt | 9 +++ .../Plugins/Android/proguard-user.txt.meta | 7 ++ .../Plugins/Android/settingsTemplate.gradle | 30 +++++++++ .../Android/settingsTemplate.gradle.meta | 7 ++ .../ProjectSettings/ProjectSettings.asset | 20 +++--- 11 files changed, 171 insertions(+), 8 deletions(-) create mode 100644 examples/demo-no-location/Assets/Plugins.meta create mode 100644 examples/demo-no-location/Assets/Plugins/Android.meta create mode 100644 examples/demo-no-location/Assets/Plugins/Android/gradleTemplate.properties create mode 100644 examples/demo-no-location/Assets/Plugins/Android/gradleTemplate.properties.meta create mode 100644 examples/demo-no-location/Assets/Plugins/Android/mainTemplate.gradle create mode 100644 examples/demo-no-location/Assets/Plugins/Android/mainTemplate.gradle.meta create mode 100644 examples/demo-no-location/Assets/Plugins/Android/proguard-user.txt create mode 100644 examples/demo-no-location/Assets/Plugins/Android/proguard-user.txt.meta create mode 100644 examples/demo-no-location/Assets/Plugins/Android/settingsTemplate.gradle create mode 100644 examples/demo-no-location/Assets/Plugins/Android/settingsTemplate.gradle.meta diff --git a/examples/demo-no-location/Assets/Plugins.meta b/examples/demo-no-location/Assets/Plugins.meta new file mode 100644 index 000000000..bdc3afd70 --- /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 000000000..3a0ea5c50 --- /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 000000000..4f9e9a40d --- /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 000000000..cacd73ac7 --- /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 000000000..d467f31ca --- /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' // Packages/com.onesignal.unity.android/Editor/OneSignalAndroidDependencies.xml + implementation 'com.onesignal:notifications:5.9.5' // Packages/com.onesignal.unity.android/Editor/OneSignalAndroidDependencies.xml + implementation 'com.onesignal:in-app-messages:5.9.5' // Packages/com.onesignal.unity.android/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 000000000..326dc6a0e --- /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 000000000..d1bea67cc --- /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 000000000..5ffc330a3 --- /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 000000000..71e58ddb7 --- /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" // Packages/com.onesignal.unity.android/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 000000000..d8962b334 --- /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/ProjectSettings/ProjectSettings.asset b/examples/demo-no-location/ProjectSettings/ProjectSettings.asset index 6f7fe2382..7b88a929a 100644 --- a/examples/demo-no-location/ProjectSettings/ProjectSettings.asset +++ b/examples/demo-no-location/ProjectSettings/ProjectSettings.asset @@ -8,7 +8,7 @@ PlayerSettings: AndroidProfiler: 0 AndroidFilterTouchesWhenObscured: 0 AndroidEnableSustainedPerformanceMode: 0 - defaultScreenOrientation: 1 + defaultScreenOrientation: 0 targetDevice: 2 useOnDemandResources: 0 accelerometerFrequency: 60 @@ -258,13 +258,13 @@ PlayerSettings: templateDefaultScene: useCustomMainManifest: 0 useCustomLauncherManifest: 0 - useCustomMainGradleTemplate: 0 + useCustomMainGradleTemplate: 1 useCustomLauncherGradleManifest: 0 useCustomBaseGradleTemplate: 0 - useCustomGradlePropertiesTemplate: 0 - useCustomGradleSettingsTemplate: 0 - useCustomProguardFile: 0 - AndroidTargetArchitectures: 1 + useCustomGradlePropertiesTemplate: 1 + useCustomGradleSettingsTemplate: 1 + useCustomProguardFile: 1 + AndroidTargetArchitectures: 2 AndroidAllowedArchitectures: -1 AndroidSplashScreenScale: 0 androidSplashScreen: {fileID: 0} @@ -287,7 +287,7 @@ PlayerSettings: height: 180 banner: {fileID: 0} androidGamepadSupportLevel: 0 - AndroidMinifyRelease: 0 + AndroidMinifyRelease: 1 AndroidMinifyDebug: 0 AndroidValidateAppBundleSize: 1 AndroidAppBundleSizeToValidate: 200 @@ -776,12 +776,16 @@ PlayerSettings: additionalCompilerArguments: {} platformArchitecture: {} scriptingBackend: + Android: 1 iPhone: 1 - il2cppCompilerConfiguration: {} + il2cppCompilerConfiguration: + Android: 1 il2cppCodeGeneration: + Android: 1 iPhone: 1 il2cppStacktraceInformation: {} managedStrippingLevel: + Android: 3 iPhone: 3 incrementalIl2cppBuild: {} suppressCommonWarnings: 1 From 93006c24b894bd6ef5e09f63be190ab1f6b0f98b Mon Sep 17 00:00:00 2001 From: Fadi George Date: Mon, 29 Jun 2026 18:56:54 -0700 Subject: [PATCH 18/21] chore(examples): disable Android fullscreen safe area --- .../demo-no-location/ProjectSettings/ProjectSettings.asset | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/examples/demo-no-location/ProjectSettings/ProjectSettings.asset b/examples/demo-no-location/ProjectSettings/ProjectSettings.asset index 7b88a929a..153beef1d 100644 --- a/examples/demo-no-location/ProjectSettings/ProjectSettings.asset +++ b/examples/demo-no-location/ProjectSettings/ProjectSettings.asset @@ -66,8 +66,8 @@ PlayerSettings: use32BitDisplayBuffer: 1 preserveFramebufferAlpha: 0 disableDepthAndStencilBuffers: 0 - androidStartInFullscreen: 1 - androidRenderOutsideSafeArea: 1 + androidStartInFullscreen: 0 + androidRenderOutsideSafeArea: 0 androidUseSwappy: 1 androidDisplayOptions: 1 androidBlitType: 0 From 479be5041d9b37572b3ba08aaf77befe21f66649 Mon Sep 17 00:00:00 2001 From: Fadi George Date: Mon, 29 Jun 2026 19:24:47 -0700 Subject: [PATCH 19/21] fix(android): log error when location module missing --- .../Runtime/AndroidLocationManager.cs | 45 ++++++++++++++----- 1 file changed, 34 insertions(+), 11 deletions(-) diff --git a/com.onesignal.unity.android/Runtime/AndroidLocationManager.cs b/com.onesignal.unity.android/Runtime/AndroidLocationManager.cs index 47efa1cfc..3827606f4 100644 --- a/com.onesignal.unity.android/Runtime/AndroidLocationManager.cs +++ b/com.onesignal.unity.android/Runtime/AndroidLocationManager.cs @@ -35,6 +35,9 @@ namespace OneSignalSDK.Android.Location { internal sealed class AndroidLocationManager : ILocationManager { + private const string LocationModuleNotAvailable = + "OneSignal location module is not available. Add the location dependency to use OneSignal.Location."; + private readonly AndroidJavaObject _location; public AndroidLocationManager(AndroidJavaClass sdkClass) @@ -45,29 +48,49 @@ public AndroidLocationManager(AndroidJavaClass sdkClass) } catch (Exception) { - SDKDebug.Warn( - "OneSignal location module is not available. OneSignal.Location calls will no-op." - ); + SDKDebug.Error(LocationModuleNotAvailable); } } public bool IsShared { - get => _location != null && _location.Call("isShared"); + get + { + try + { + return _location != null && _location.Call("isShared"); + } + catch (Exception) + { + SDKDebug.Error(LocationModuleNotAvailable); + return false; + } + } set { - if (_location != null) - _location.Call("setShared", value); + try + { + if (_location != null) + _location.Call("setShared", value); + } + catch (Exception) + { + SDKDebug.Error(LocationModuleNotAvailable); + } } } public void RequestPermission() { - if (_location == null) - return; - - var continuation = new BoolContinuation(); - _location.Call("requestPermission", continuation.Proxy); + try + { + var continuation = new BoolContinuation(); + _location.Call("requestPermission", continuation.Proxy); + } + catch (Exception) + { + SDKDebug.Error(LocationModuleNotAvailable); + } } } } From ae5bd1faf84f108393ee9a6a6d230c3b2265bdc0 Mon Sep 17 00:00:00 2001 From: Fadi George Date: Mon, 29 Jun 2026 20:32:32 -0700 Subject: [PATCH 20/21] refactor(deps): move EDM4U manifests to Assets/OneSignal/Editor --- .github/workflows/create-release-pr.yml | 10 +++-- .github/workflows/e2e.yml | 4 +- README.md | 17 ++++---- .../Editor/OneSignalAndroidDependencies.cs | 9 ++-- .../Editor/OneSignalSDKSettings.cs | 23 ++++++++++ .../Editor/BuildPostProcessor.cs | 42 ++++++------------- .../Editor/OneSignaliOSDependencies.cs | 9 ++-- .../Assets/OneSignal/Editor.meta | 8 ++++ .../Editor/OneSignalAndroidDependencies.xml | 0 .../OneSignalAndroidDependencies.xml.meta | 4 +- .../Editor/OneSignaliOSDependencies.xml | 0 .../Editor/OneSignaliOSDependencies.xml.meta | 2 +- .../Assets/Scripts/Editor/BuildScript.cs | 10 ----- examples/demo-no-location/README.md | 19 +++++---- examples/demo-no-location/run-android.sh | 4 ++ examples/demo-no-location/run-ios.sh | 9 +++- .../App/Editor/iOS/BuildPostProcessor.cs | 4 +- .../Editor/OneSignalAndroidDependencies.xml | 8 ++++ .../OneSignalAndroidDependencies.xml.meta | 7 ++++ .../Editor/OneSignaliOSDependencies.xml | 5 +++ .../Editor/OneSignaliOSDependencies.xml.meta | 7 ++++ 21 files changed, 126 insertions(+), 75 deletions(-) create mode 100644 examples/demo-no-location/Assets/OneSignal/Editor.meta rename {com.onesignal.unity.android => examples/demo-no-location/Assets/OneSignal}/Editor/OneSignalAndroidDependencies.xml (100%) rename {com.onesignal.unity.android => examples/demo-no-location/Assets/OneSignal}/Editor/OneSignalAndroidDependencies.xml.meta (59%) rename {com.onesignal.unity.ios => examples/demo-no-location/Assets/OneSignal}/Editor/OneSignaliOSDependencies.xml (100%) rename {com.onesignal.unity.ios => examples/demo-no-location/Assets/OneSignal}/Editor/OneSignaliOSDependencies.xml.meta (75%) create mode 100644 examples/demo/Assets/OneSignal/Editor/OneSignalAndroidDependencies.xml create mode 100644 examples/demo/Assets/OneSignal/Editor/OneSignalAndroidDependencies.xml.meta create mode 100644 examples/demo/Assets/OneSignal/Editor/OneSignaliOSDependencies.xml create mode 100644 examples/demo/Assets/OneSignal/Editor/OneSignaliOSDependencies.xml.meta diff --git a/.github/workflows/create-release-pr.yml b/.github/workflows/create-release-pr.yml index a7828556c..8e97384e0 100644 --- a/.github/workflows/create-release-pr.yml +++ b/.github/workflows/create-release-pr.yml @@ -89,8 +89,8 @@ jobs: # Get versions from target branch (not the release branch) CURRENT_VERSION=$(git show origin/${{ inputs.target_branch }}:examples/demo/Assets/OneSignal/VERSION | tr -d '\n\r' | xargs) - ANDROID_VERSION=$(git show origin/${{ inputs.target_branch }}:com.onesignal.unity.android/Editor/OneSignalAndroidDependencies.xml | grep -oE 'spec="com.onesignal:OneSignal:[0-9]+\.[0-9]+\.[0-9]+"' | sed -E 's/.*OneSignal:([0-9]+\.[0-9]+\.[0-9]+)".*/\1/' | head -1) - IOS_VERSION=$(git show origin/${{ inputs.target_branch }}:com.onesignal.unity.ios/Editor/OneSignaliOSDependencies.xml | grep -oE 'version="[0-9.]+"' | grep -oE '[0-9.]+' | head -1) + ANDROID_VERSION=$(git show origin/${{ inputs.target_branch }}:com.onesignal.unity.android/Editor/OneSignalAndroidDependencies.cs | grep -oE 'Version = "[0-9]+\.[0-9]+\.[0-9]+"' | grep -oE '[0-9]+\.[0-9]+\.[0-9]+' | head -1) + IOS_VERSION=$(git show origin/${{ inputs.target_branch }}:com.onesignal.unity.ios/Editor/OneSignaliOSDependencies.cs | grep -oE 'Version = "[0-9]+\.[0-9]+\.[0-9]+"' | grep -oE '[0-9]+\.[0-9]+\.[0-9]+' | head -1) echo "unity_from=${CURRENT_VERSION}" >> $GITHUB_OUTPUT echo "android_from=${ANDROID_VERSION}" >> $GITHUB_OUTPUT echo "ios_from=${IOS_VERSION}" >> $GITHUB_OUTPUT @@ -109,7 +109,8 @@ jobs: sleep 30 done if [ "$FOUND" != "true" ]; then echo "✗ Android SDK version ${VERSION} not found after 5 attempts"; exit 1; fi - sed -i -E "s/spec=\"com\.onesignal:OneSignal:[0-9][0-9.]*\"/spec=\"com.onesignal:OneSignal:$VERSION\"/" com.onesignal.unity.android/Editor/OneSignalAndroidDependencies.xml + sed -i -E "s/const string Version = \"[0-9][0-9.]*\"/const string Version = \"$VERSION\"/" com.onesignal.unity.android/Editor/OneSignalAndroidDependencies.cs + sed -i -E "s/com\.onesignal:OneSignal:[0-9][0-9.]*<\/package>/com.onesignal:OneSignal:$VERSION<\/package>/" examples/demo/ProjectSettings/AndroidResolverDependencies.xml @@ -132,7 +133,8 @@ jobs: sleep 30 done if [ "$FOUND" != "true" ]; then echo "✗ iOS SDK version ${VERSION} not found after 5 attempts"; exit 1; fi - sed -i -E "s/version=\"[0-9][0-9.]*\"/version=\"$VERSION\"/" com.onesignal.unity.ios/Editor/OneSignaliOSDependencies.xml + sed -i -E "s/const string Version = \"[0-9][0-9.]*\"/const string Version = \"$VERSION\"/" com.onesignal.unity.ios/Editor/OneSignaliOSDependencies.cs + sed -i -E "s/version=\"[0-9][0-9.]*\"/version=\"$VERSION\"/" examples/demo/Assets/OneSignal/Editor/OneSignaliOSDependencies.xml # Only commit if there are changes git add -A diff --git a/.github/workflows/e2e.yml b/.github/workflows/e2e.yml index 1a8751261..1828c7110 100644 --- a/.github/workflows/e2e.yml +++ b/.github/workflows/e2e.yml @@ -45,9 +45,9 @@ jobs: - name: Resolve OneSignal Android SDK version id: android-sdk-version run: | - VERSION=$(grep -oE 'com\.onesignal:OneSignal:[^"]+' com.onesignal.unity.android/Editor/OneSignalAndroidDependencies.xml | head -n1 | cut -d: -f3) + VERSION=$(grep -oE 'Version = "[0-9]+\.[0-9]+\.[0-9]+"' com.onesignal.unity.android/Editor/OneSignalAndroidDependencies.cs | head -n1 | grep -oE '[0-9]+\.[0-9]+\.[0-9]+') if [ -z "$VERSION" ]; then - echo "::error::Could not parse OneSignal Android SDK version from OneSignalAndroidDependencies.xml" + echo "::error::Could not parse OneSignal Android SDK version from OneSignalAndroidDependencies.cs" exit 1 fi echo "version=${VERSION}" >> "$GITHUB_OUTPUT" diff --git a/README.md b/README.md index 4086640f3..1e28fadd1 100644 --- a/README.md +++ b/README.md @@ -152,17 +152,20 @@ with your own. There is a complete guide for this [in the plugin's README](com.o ### Disable Location Module -By default, the OneSignal Unity SDK includes OneSignal's native location module so `OneSignal.Location` works without extra setup. If your app does not use location features, select **OneSignal > Disable Location Module** in the Unity Editor before resolving Android dependencies or building iOS. +By default, the OneSignal Unity SDK includes OneSignal's native location module so `OneSignal.Location` works without extra setup. If your app does not use location features, you can exclude the native location module from iOS and Android builds. There are two ways to opt out: -For automated Unity project setup, you can set the same Editor project setting from an Editor script before dependency resolution or build: +- **Editor toggle** (interactive): select **OneSignal > Disable Location Module** in the Unity Editor before resolving Android dependencies or building iOS. This is persisted per project in `ProjectSettings/OneSignalSettings.json`. +- **Environment variable** (CLI/CI): set `ONESIGNAL_DISABLE_LOCATION=true` (or `1`) in the environment before launching Unity, for example: -```C# -OneSignalSDK.OneSignalSDKSettings.DisableLocation = true; -``` + ```sh + ONESIGNAL_DISABLE_LOCATION=true /path/to/Unity -batchmode -quit -projectPath . -buildTarget iOS -executeMethod BuildScript.BuildiOSSimulator + ``` + +When set, the environment variable takes precedence over the Editor toggle, so headless builds can opt out without changing project settings. -Do not call this from runtime app code; it changes the Unity project configuration used by native dependency resolution. +With the location module disabled, Android resolves OneSignal's native modules without the location artifact and iOS uses OneSignal pods without `OneSignalLocation`. `OneSignal.Location.RequestPermission()` and `OneSignal.Location.IsShared = ...` no-op on native builds without the location module, and `OneSignal.Location.IsShared` returns `false`. -When disabled, Android resolves OneSignal's native modules without the location artifact and iOS uses OneSignal pods without `OneSignalLocation`. `OneSignal.Location.RequestPermission()` and `OneSignal.Location.IsShared = ...` no-op on native builds without the location module, and `OneSignal.Location.IsShared` returns `false`. +When toggling the flag, clear stale native outputs (the generated Xcode project, CocoaPods/Gradle caches, and prior `Build/` artifacts) so a previously linked location module isn't reused. ## Usage You can find a complete implementation in our included [example MonoBehaviour](OneSignalExample/Assets/OneSignal/Example/OneSignalExampleBehaviour.cs). Additionally we have included a diff --git a/com.onesignal.unity.android/Editor/OneSignalAndroidDependencies.cs b/com.onesignal.unity.android/Editor/OneSignalAndroidDependencies.cs index 7c5291913..28685924c 100644 --- a/com.onesignal.unity.android/Editor/OneSignalAndroidDependencies.cs +++ b/com.onesignal.unity.android/Editor/OneSignalAndroidDependencies.cs @@ -43,7 +43,7 @@ static OneSignalAndroidDependencies() internal static void WriteDependencies() { - var contents = OneSignalSDKSettings.DisableLocation + var contents = OneSignalSDKSettings.EffectiveDisableLocation ? DisabledLocationDependencies : DefaultDependencies; @@ -55,6 +55,7 @@ internal static void WriteDependencies() ) return; + Directory.CreateDirectory(Path.GetDirectoryName(_dependenciesPath)); File.WriteAllText(_dependenciesPath, contents); AssetDatabase.ImportAsset(_dependenciesPath); } @@ -66,11 +67,11 @@ internal static void WriteDependencies() } } - private const string Version = "5.9.5"; + internal const string Version = "5.9.5"; private static readonly string _dependenciesPath = Path.Combine( - "Packages", - "com.onesignal.unity.android", + "Assets", + "OneSignal", "Editor", "OneSignalAndroidDependencies.xml" ); diff --git a/com.onesignal.unity.core/Editor/OneSignalSDKSettings.cs b/com.onesignal.unity.core/Editor/OneSignalSDKSettings.cs index 73011b886..c51b91c14 100644 --- a/com.onesignal.unity.core/Editor/OneSignalSDKSettings.cs +++ b/com.onesignal.unity.core/Editor/OneSignalSDKSettings.cs @@ -34,6 +34,8 @@ namespace OneSignalSDK { public static class OneSignalSDKSettings { + public const string DisableLocationEnvVar = "ONESIGNAL_DISABLE_LOCATION"; + public static event Action Changed; public static bool DisableLocation @@ -51,6 +53,27 @@ public static bool DisableLocation } } + /// + /// Resolved value used by the build pipeline. The + /// environment variable, when present, overrides the persisted Editor setting so CLI + /// and CI builds can opt out without mutating project settings. + /// + public static bool EffectiveDisableLocation + { + get + { + var environmentValue = Environment.GetEnvironmentVariable(DisableLocationEnvVar); + if (!string.IsNullOrEmpty(environmentValue)) + { + var normalized = environmentValue.Trim(); + return normalized.Equals("true", StringComparison.OrdinalIgnoreCase) + || normalized == "1"; + } + + return _settings.disableLocation; + } + } + public static void Save() { Directory.CreateDirectory(Path.GetDirectoryName(_settingsPath)); diff --git a/com.onesignal.unity.ios/Editor/BuildPostProcessor.cs b/com.onesignal.unity.ios/Editor/BuildPostProcessor.cs index 94143874f..5cd5d0c17 100644 --- a/com.onesignal.unity.ios/Editor/BuildPostProcessor.cs +++ b/com.onesignal.unity.ios/Editor/BuildPostProcessor.cs @@ -73,14 +73,8 @@ public class BuildPostProcessor : IPostprocessBuildWithReport { private const string ServiceExtensionTargetName = "OneSignalNotificationServiceExtension"; private const string ServiceExtensionFilename = "NotificationService.swift"; - private const string DependenciesFilename = "OneSignaliOSDependencies.xml"; private const string PackageName = "com.onesignal.unity.ios"; - private static readonly string EditorFilesPath = Path.Combine( - "Packages", - PackageName, - "Editor" - ); private static readonly string PluginLibrariesPath = Path.Combine( PackageName, "Runtime", @@ -128,7 +122,7 @@ public void OnPostprocessBuild(BuildReport report) DisableBitcode(); ConfigureLocationModule(); - if (!OneSignalSDK.OneSignalSDKSettings.DisableLocation) + if (!OneSignalSDK.OneSignalSDKSettings.EffectiveDisableLocation) AddLocationUsageDescription(); // Save the project back out @@ -319,33 +313,12 @@ private void ExtensionAddPodsToTarget() return; } - var dependenciesFilePath = Path.Combine(EditorFilesPath, DependenciesFilename); - - if (!File.Exists(dependenciesFilePath)) - { - UnityDebug.LogError($"Could not find {DependenciesFilename}"); - return; - } - - var dependenciesFile = File.ReadAllText(dependenciesFilePath); - var dependenciesRegex = new Regex( - "" - ); - - if (!dependenciesRegex.IsMatch(dependenciesFile)) - { - UnityDebug.LogError( - $"Could not read current iOS framework dependency version from {DependenciesFilename}" - ); - return; - } - var podfile = File.ReadAllText(podfilePath); var podfileRegex = new Regex( $@"target '{ServiceExtensionTargetName}' do\n pod 'OneSignalXCFramework(?:/OneSignalExtension)?', '(.+)'\nend\n" ); - var requiredVersion = dependenciesRegex.Match(dependenciesFile).Groups[1].Value; + var requiredVersion = OneSignaliOSDependencies.Version; var requiredTarget = $"target '{ServiceExtensionTargetName}' do\n pod 'OneSignalXCFramework/OneSignalExtension', '{requiredVersion}'\nend\n"; @@ -357,12 +330,21 @@ private void ExtensionAddPodsToTarget() podfile = podfile.Replace(podfileTarget, requiredTarget); } + // The app, widget, and notification service extension targets each copy the + // OneSignal XCFrameworks. With static frameworks this declares the same output + // file from multiple script phases, which newer Xcode treats as a hard + // "Multiple commands produce" error. Dropping the declared input/output paths + // makes the copy phases run unconditionally and resolves the conflict. + if (!podfile.Contains("disable_input_output_paths")) + podfile = + "install! 'cocoapods', :disable_input_output_paths => true\n" + podfile; + File.WriteAllText(podfilePath, podfile); } private void ConfigureLocationModule() { - if (!OneSignalSDK.OneSignalSDKSettings.DisableLocation) + if (!OneSignalSDK.OneSignalSDKSettings.EffectiveDisableLocation) return; _project.AddBuildProperty( diff --git a/com.onesignal.unity.ios/Editor/OneSignaliOSDependencies.cs b/com.onesignal.unity.ios/Editor/OneSignaliOSDependencies.cs index be596119a..32e075815 100644 --- a/com.onesignal.unity.ios/Editor/OneSignaliOSDependencies.cs +++ b/com.onesignal.unity.ios/Editor/OneSignaliOSDependencies.cs @@ -43,7 +43,7 @@ static OneSignaliOSDependencies() internal static void WriteDependencies() { - var contents = OneSignalSDK.OneSignalSDKSettings.DisableLocation + var contents = OneSignalSDK.OneSignalSDKSettings.EffectiveDisableLocation ? DisabledLocationDependencies : DefaultDependencies; @@ -55,6 +55,7 @@ internal static void WriteDependencies() ) return; + Directory.CreateDirectory(Path.GetDirectoryName(_dependenciesPath)); File.WriteAllText(_dependenciesPath, contents); AssetDatabase.ImportAsset(_dependenciesPath); } @@ -66,11 +67,11 @@ internal static void WriteDependencies() } } - private const string Version = "5.5.3"; + internal const string Version = "5.5.3"; private static readonly string _dependenciesPath = Path.Combine( - "Packages", - "com.onesignal.unity.ios", + "Assets", + "OneSignal", "Editor", "OneSignaliOSDependencies.xml" ); 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 000000000..bd5cfabd8 --- /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/com.onesignal.unity.android/Editor/OneSignalAndroidDependencies.xml b/examples/demo-no-location/Assets/OneSignal/Editor/OneSignalAndroidDependencies.xml similarity index 100% rename from com.onesignal.unity.android/Editor/OneSignalAndroidDependencies.xml rename to examples/demo-no-location/Assets/OneSignal/Editor/OneSignalAndroidDependencies.xml diff --git a/com.onesignal.unity.android/Editor/OneSignalAndroidDependencies.xml.meta b/examples/demo-no-location/Assets/OneSignal/Editor/OneSignalAndroidDependencies.xml.meta similarity index 59% rename from com.onesignal.unity.android/Editor/OneSignalAndroidDependencies.xml.meta rename to examples/demo-no-location/Assets/OneSignal/Editor/OneSignalAndroidDependencies.xml.meta index 079545c0c..5e5ebd357 100644 --- a/com.onesignal.unity.android/Editor/OneSignalAndroidDependencies.xml.meta +++ b/examples/demo-no-location/Assets/OneSignal/Editor/OneSignalAndroidDependencies.xml.meta @@ -1,7 +1,5 @@ fileFormatVersion: 2 -guid: 127a9573f8846469b8feaf4dd86f9587 -timeCreated: 1521620682 -licenseType: Free +guid: 94ac4dfb3f20e4c08afa2b53752207c3 TextScriptImporter: externalObjects: {} userData: diff --git a/com.onesignal.unity.ios/Editor/OneSignaliOSDependencies.xml b/examples/demo-no-location/Assets/OneSignal/Editor/OneSignaliOSDependencies.xml similarity index 100% rename from com.onesignal.unity.ios/Editor/OneSignaliOSDependencies.xml rename to examples/demo-no-location/Assets/OneSignal/Editor/OneSignaliOSDependencies.xml diff --git a/com.onesignal.unity.ios/Editor/OneSignaliOSDependencies.xml.meta b/examples/demo-no-location/Assets/OneSignal/Editor/OneSignaliOSDependencies.xml.meta similarity index 75% rename from com.onesignal.unity.ios/Editor/OneSignaliOSDependencies.xml.meta rename to examples/demo-no-location/Assets/OneSignal/Editor/OneSignaliOSDependencies.xml.meta index 69b8a119e..c3844c585 100644 --- a/com.onesignal.unity.ios/Editor/OneSignaliOSDependencies.xml.meta +++ b/examples/demo-no-location/Assets/OneSignal/Editor/OneSignaliOSDependencies.xml.meta @@ -1,5 +1,5 @@ fileFormatVersion: 2 -guid: 033a0fbaaa064a48ad2e72d8e35d5f36 +guid: 63a05d4f4b1e24c9abb11ad9675ec7c0 TextScriptImporter: externalObjects: {} userData: diff --git a/examples/demo-no-location/Assets/Scripts/Editor/BuildScript.cs b/examples/demo-no-location/Assets/Scripts/Editor/BuildScript.cs index 7e05aa417..68636f523 100644 --- a/examples/demo-no-location/Assets/Scripts/Editor/BuildScript.cs +++ b/examples/demo-no-location/Assets/Scripts/Editor/BuildScript.cs @@ -18,8 +18,6 @@ public static class BuildScript public static void BuildAndroidEmulator() { - EnforceNoLocationBuild(); - var outputPath = Path.Combine(AndroidOutputDir, ApkName); Directory.CreateDirectory(AndroidOutputDir); @@ -65,8 +63,6 @@ public static void BuildAndroidEmulator() public static void BuildiOSSimulator() { - EnforceNoLocationBuild(); - Directory.CreateDirectory(IOSOutputDir); PlayerSettings.SetScriptingBackend(NamedBuildTarget.iOS, ScriptingImplementation.IL2CPP); @@ -98,12 +94,6 @@ public static void BuildiOSSimulator() HandleReport(report, IOSOutputDir); } - private static void EnforceNoLocationBuild() - { - // Scripted builds should stay no-location even if the Editor menu setting was toggled. - OneSignalSDK.OneSignalSDKSettings.DisableLocation = true; - } - private static IDisposable ApplyConfiguredAppId() { var appId = GetConfiguredAppId(); diff --git a/examples/demo-no-location/README.md b/examples/demo-no-location/README.md index bd205322f..7f7c1ef9b 100644 --- a/examples/demo-no-location/README.md +++ b/examples/demo-no-location/README.md @@ -2,15 +2,18 @@ Minimal Unity project for apps that use OneSignal without the native location module. -The saved OneSignal project setting is checked in as: +This demo opts out of location two ways, so it stays no-location whether you build from the Editor or the command line: -```json -{ - "disableLocation": true -} -``` +- 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 + } + ``` -Before resolving Android dependencies or building iOS, confirm **OneSignal > Disable Location Module** is checked. +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 @@ -81,6 +84,8 @@ The iOS script generates a minimal Podfile when External Dependency Manager does ## 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: diff --git a/examples/demo-no-location/run-android.sh b/examples/demo-no-location/run-android.sh index 46924b0f0..255d90fb3 100755 --- a/examples/demo-no-location/run-android.sh +++ b/examples/demo-no-location/run-android.sh @@ -5,6 +5,10 @@ # ./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() { diff --git a/examples/demo-no-location/run-ios.sh b/examples/demo-no-location/run-ios.sh index 56bedd3ce..c3f1bed78 100755 --- a/examples/demo-no-location/run-ios.sh +++ b/examples/demo-no-location/run-ios.sh @@ -5,6 +5,10 @@ # ./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() { @@ -65,10 +69,13 @@ for r,devs in d['devices'].items(): 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/../../com.onesignal.unity.ios/Editor/OneSignaliOSDependencies.xml" + DEPS="$SCRIPT_DIR/Assets/OneSignal/Editor/OneSignaliOSDependencies.xml" [ ! -f "$DEPS" ] && return python3 - "$DEPS" "$XCODE_DIR/Podfile" <<'PY' diff --git a/examples/demo/Assets/App/Editor/iOS/BuildPostProcessor.cs b/examples/demo/Assets/App/Editor/iOS/BuildPostProcessor.cs index 424bbb889..a3fb9cab1 100644 --- a/examples/demo/Assets/App/Editor/iOS/BuildPostProcessor.cs +++ b/examples/demo/Assets/App/Editor/iOS/BuildPostProcessor.cs @@ -228,8 +228,8 @@ static void AddWidgetExtensionToPodFile(string outputPath) static string ResolveOneSignalXCFrameworkVersion() { var dependenciesFilePath = Path.Combine( - "Packages", - "com.onesignal.unity.ios", + "Assets", + "OneSignal", "Editor", "OneSignaliOSDependencies.xml" ); diff --git a/examples/demo/Assets/OneSignal/Editor/OneSignalAndroidDependencies.xml b/examples/demo/Assets/OneSignal/Editor/OneSignalAndroidDependencies.xml new file mode 100644 index 000000000..e7a3cacaf --- /dev/null +++ b/examples/demo/Assets/OneSignal/Editor/OneSignalAndroidDependencies.xml @@ -0,0 +1,8 @@ + + + + https://repo.maven.apache.org/maven2 + + + + diff --git a/examples/demo/Assets/OneSignal/Editor/OneSignalAndroidDependencies.xml.meta b/examples/demo/Assets/OneSignal/Editor/OneSignalAndroidDependencies.xml.meta new file mode 100644 index 000000000..4d0c987ab --- /dev/null +++ b/examples/demo/Assets/OneSignal/Editor/OneSignalAndroidDependencies.xml.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: b7aeb390ee8404c2fb63778d3f0870c7 +TextScriptImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/examples/demo/Assets/OneSignal/Editor/OneSignaliOSDependencies.xml b/examples/demo/Assets/OneSignal/Editor/OneSignaliOSDependencies.xml new file mode 100644 index 000000000..b97318714 --- /dev/null +++ b/examples/demo/Assets/OneSignal/Editor/OneSignaliOSDependencies.xml @@ -0,0 +1,5 @@ + + + + + diff --git a/examples/demo/Assets/OneSignal/Editor/OneSignaliOSDependencies.xml.meta b/examples/demo/Assets/OneSignal/Editor/OneSignaliOSDependencies.xml.meta new file mode 100644 index 000000000..732ef7698 --- /dev/null +++ b/examples/demo/Assets/OneSignal/Editor/OneSignaliOSDependencies.xml.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: df6b6a1d706cb43d99405e586ebe2bee +TextScriptImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: From a1ba64ab5f0424a1176d54e08ec7021749a0f07f Mon Sep 17 00:00:00 2001 From: Fadi George Date: Mon, 29 Jun 2026 21:00:24 -0700 Subject: [PATCH 21/21] style(ios): condense podfile string assignment --- com.onesignal.unity.ios/Editor/BuildPostProcessor.cs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/com.onesignal.unity.ios/Editor/BuildPostProcessor.cs b/com.onesignal.unity.ios/Editor/BuildPostProcessor.cs index 5cd5d0c17..de9721e49 100644 --- a/com.onesignal.unity.ios/Editor/BuildPostProcessor.cs +++ b/com.onesignal.unity.ios/Editor/BuildPostProcessor.cs @@ -336,8 +336,7 @@ private void ExtensionAddPodsToTarget() // "Multiple commands produce" error. Dropping the declared input/output paths // makes the copy phases run unconditionally and resolves the conflict. if (!podfile.Contains("disable_input_output_paths")) - podfile = - "install! 'cocoapods', :disable_input_output_paths => true\n" + podfile; + podfile = "install! 'cocoapods', :disable_input_output_paths => true\n" + podfile; File.WriteAllText(podfilePath, podfile); }