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 62ee47318..1e28fadd1 100644 --- a/README.md +++ b/README.md @@ -150,6 +150,23 @@ 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, you can exclude the native location module from iOS and Android builds. There are two ways to opt out: + +- **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: + + ```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. + +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 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 [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..28685924c --- /dev/null +++ b/com.onesignal.unity.android/Editor/OneSignalAndroidDependencies.cs @@ -0,0 +1,103 @@ +/* + * 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 UnityDebug = UnityEngine.Debug; + +namespace OneSignalSDK +{ + [InitializeOnLoad] + internal static class OneSignalAndroidDependencies + { + static OneSignalAndroidDependencies() + { + OneSignalSDKSettings.Changed += WriteDependencies; + WriteDependencies(); + } + + internal static void WriteDependencies() + { + var contents = OneSignalSDKSettings.EffectiveDisableLocation + ? DisabledLocationDependencies + : DefaultDependencies; + + try + { + if ( + File.Exists(_dependenciesPath) + && File.ReadAllText(_dependenciesPath) == contents + ) + return; + + Directory.CreateDirectory(Path.GetDirectoryName(_dependenciesPath)); + File.WriteAllText(_dependenciesPath, contents); + AssetDatabase.ImportAsset(_dependenciesPath); + } + catch (Exception exception) + { + UnityDebug.LogWarning( + $"Could not update OneSignal Android dependencies at {_dependenciesPath}: {exception.Message}" + ); + } + } + + internal const string Version = "5.9.5"; + + private static readonly string _dependenciesPath = Path.Combine( + "Assets", + "OneSignal", + "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..3827606f4 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; @@ -34,23 +35,62 @@ 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) { - _location = sdkClass.CallStatic("getLocation"); + try + { + _location = sdkClass.CallStatic("getLocation"); + } + catch (Exception) + { + SDKDebug.Error(LocationModuleNotAvailable); + } } public bool IsShared { - get => _location.Call("isShared"); - set => _location.Call("setShared", value); + get + { + try + { + return _location != null && _location.Call("isShared"); + } + catch (Exception) + { + SDKDebug.Error(LocationModuleNotAvailable); + return false; + } + } + set + { + try + { + if (_location != null) + _location.Call("setShared", value); + } + catch (Exception) + { + SDKDebug.Error(LocationModuleNotAvailable); + } + } } public void RequestPermission() { - var continuation = new BoolContinuation(); - _location.Call("requestPermission", continuation.Proxy); + try + { + var continuation = new BoolContinuation(); + _location.Call("requestPermission", continuation.Proxy); + } + catch (Exception) + { + SDKDebug.Error(LocationModuleNotAvailable); + } } } } diff --git a/com.onesignal.unity.core/Editor/OneSignalSDKSettings.cs b/com.onesignal.unity.core/Editor/OneSignalSDKSettings.cs new file mode 100644 index 000000000..c51b91c14 --- /dev/null +++ b/com.onesignal.unity.core/Editor/OneSignalSDKSettings.cs @@ -0,0 +1,125 @@ +/* + * 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 const string DisableLocationEnvVar = "ONESIGNAL_DISABLE_LOCATION"; + + 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(); + } + } + + /// + /// 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)); + 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..de9721e49 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 @@ -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", @@ -126,8 +120,10 @@ public void OnPostprocessBuild(BuildReport report) AddNotificationServiceExtension(); DisableBitcode(); + ConfigureLocationModule(); - AddLocationUsageDescription(); + if (!OneSignalSDK.OneSignalSDKSettings.EffectiveDisableLocation) + AddLocationUsageDescription(); // Save the project back out File.WriteAllText(_projectPath, _project.WriteToString()); @@ -311,41 +307,20 @@ private void ExtensionAddPodsToTarget() if (!File.Exists(podfilePath)) { - Debug.LogError( + UnityDebug.LogError( $"Could not find Podfile. {ServiceExtensionFilename} will have errors." ); return; } - var dependenciesFilePath = Path.Combine(EditorFilesPath, DependenciesFilename); - - if (!File.Exists(dependenciesFilePath)) - { - Debug.LogError($"Could not find {DependenciesFilename}"); - return; - } - - var dependenciesFile = File.ReadAllText(dependenciesFilePath); - var dependenciesRegex = new Regex( - "(?<=)" - ); - - if (!dependenciesRegex.IsMatch(dependenciesFile)) - { - Debug.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', '(.+)'\nend\n" + $@"target '{ServiceExtensionTargetName}' do\n pod 'OneSignalXCFramework(?:/OneSignalExtension)?', '(.+)'\nend\n" ); - var requiredVersion = dependenciesRegex.Match(dependenciesFile).ToString(); + var requiredVersion = OneSignaliOSDependencies.Version; 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; @@ -355,9 +330,29 @@ 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.EffectiveDisableLocation) + 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..32e075815 --- /dev/null +++ b/com.onesignal.unity.ios/Editor/OneSignaliOSDependencies.cs @@ -0,0 +1,96 @@ +/* + * 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 UnityDebug = 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.EffectiveDisableLocation + ? DisabledLocationDependencies + : DefaultDependencies; + + try + { + if ( + File.Exists(_dependenciesPath) + && File.ReadAllText(_dependenciesPath) == contents + ) + return; + + Directory.CreateDirectory(Path.GetDirectoryName(_dependenciesPath)); + File.WriteAllText(_dependenciesPath, contents); + AssetDatabase.ImportAsset(_dependenciesPath); + } + catch (Exception exception) + { + UnityDebug.LogWarning( + $"Could not update OneSignal iOS dependencies at {_dependenciesPath}: {exception.Message}" + ); + } + } + + internal const string Version = "5.5.3"; + + private static readonly string _dependenciesPath = Path.Combine( + "Assets", + "OneSignal", + "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..a5c6c2d58 100644 --- a/com.onesignal.unity.ios/Runtime/Plugins/iOS/OneSignalUnityBridgeLocation.mm +++ b/com.onesignal.unity.ios/Runtime/Plugins/iOS/OneSignalUnityBridgeLocation.mm @@ -31,16 +31,31 @@ #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]; +#endif } void _oneSignalLocationSetIsShared(bool shared) { +#if ONESIGNAL_DISABLE_LOCATION + [OneSignalLog onesignalLog:ONE_S_LL_ERROR message:OneSignalLocationModuleNotFoundMessage]; +#else [OneSignal.Location setShared:shared]; +#endif } void _oneSignalLocationRequestPermission() { +#if ONESIGNAL_DISABLE_LOCATION + [OneSignalLog onesignalLog:ONE_S_LL_ERROR message:OneSignalLocationModuleNotFoundMessage]; +#else [OneSignal.Location requestPermission]; +#endif } } \ No newline at end of file diff --git a/examples/demo-no-location/.env.example b/examples/demo-no-location/.env.example new file mode 100644 index 000000000..69d154c0a --- /dev/null +++ b/examples/demo-no-location/.env.example @@ -0,0 +1,4 @@ +# Used by run-android.sh and run-ios.sh during scripted builds. +# For Play Mode in the Unity Editor, set the same value on the +# NoLocationDemo component in Assets/Scenes/Main.unity. +ONESIGNAL_APP_ID=YOUR-ONESIGNAL-APP-ID diff --git a/examples/demo-no-location/.gitignore b/examples/demo-no-location/.gitignore new file mode 100644 index 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.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/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/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/examples/demo-no-location/Assets/OneSignal/Editor/OneSignalAndroidDependencies.xml b/examples/demo-no-location/Assets/OneSignal/Editor/OneSignalAndroidDependencies.xml new file mode 100644 index 000000000..f41da55ad --- /dev/null +++ b/examples/demo-no-location/Assets/OneSignal/Editor/OneSignalAndroidDependencies.xml @@ -0,0 +1,10 @@ + + + + https://repo.maven.apache.org/maven2 + + + + + + diff --git a/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/examples/demo-no-location/Assets/OneSignal/Editor/OneSignaliOSDependencies.xml b/examples/demo-no-location/Assets/OneSignal/Editor/OneSignaliOSDependencies.xml new file mode 100644 index 000000000..15c9f1bea --- /dev/null +++ b/examples/demo-no-location/Assets/OneSignal/Editor/OneSignaliOSDependencies.xml @@ -0,0 +1,6 @@ + + + + + + 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/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/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/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/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..68636f523 --- /dev/null +++ b/examples/demo-no-location/Assets/Scripts/Editor/BuildScript.cs @@ -0,0 +1,244 @@ +using System; +using System.IO; +using UnityEditor; +using UnityEditor.Build; +using UnityEditor.Build.Reporting; +using UnityEditor.SceneManagement; +using UnityEngine; + +public static class BuildScript +{ + private const string AndroidOutputDir = "Build/Android"; + private const string ApkName = "onesignal-demo-no-location.apk"; + private const string IOSOutputDir = "Build/iOS"; + private const string AppIdEnvironmentVariable = "ONESIGNAL_APP_ID"; + private const string MainScenePath = "Assets/Scenes/Main.unity"; + private const string OneSignalAppIdPropertyName = "_oneSignalAppId"; + private const string NoLocationDemoTypeName = "NoLocationDemo"; + + public static void BuildAndroidEmulator() + { + var outputPath = Path.Combine(AndroidOutputDir, ApkName); + Directory.CreateDirectory(AndroidOutputDir); + + PlayerSettings.Android.targetArchitectures = AndroidArchitecture.ARM64; + PlayerSettings.SetScriptingBackend( + NamedBuildTarget.Android, + ScriptingImplementation.IL2CPP + ); + PlayerSettings.SetIl2CppCodeGeneration( + NamedBuildTarget.Android, + Il2CppCodeGeneration.OptimizeSize + ); + PlayerSettings.SetManagedStrippingLevel( + NamedBuildTarget.Android, + ManagedStrippingLevel.High + ); + PlayerSettings.Android.minifyRelease = true; + PlayerSettings.Android.minifyWithR8 = true; + PlayerSettings.stripEngineCode = true; + PlayerSettings.SetIl2CppCompilerConfiguration( + NamedBuildTarget.Android, + Il2CppCompilerConfiguration.Release + ); + EditorUserBuildSettings.androidBuildSystem = AndroidBuildSystem.Gradle; + EditorUserBuildSettings.exportAsGoogleAndroidProject = false; + EditorUserBuildSettings.buildAppBundle = false; + + BuildReport report; + using (ApplyConfiguredAppId()) + report = BuildPipeline.BuildPlayer( + new BuildPlayerOptions + { + scenes = GetScenes(), + locationPathName = outputPath, + target = BuildTarget.Android, + subtarget = 0, + options = BuildOptions.None, + } + ); + + HandleReport(report, outputPath); + } + + public static void BuildiOSSimulator() + { + Directory.CreateDirectory(IOSOutputDir); + + PlayerSettings.SetScriptingBackend(NamedBuildTarget.iOS, ScriptingImplementation.IL2CPP); + PlayerSettings.iOS.sdkVersion = iOSSdkVersion.SimulatorSDK; + PlayerSettings.iOS.simulatorSdkArchitecture = AppleMobileArchitectureSimulator.Universal; + PlayerSettings.SetIl2CppCodeGeneration( + NamedBuildTarget.iOS, + Il2CppCodeGeneration.OptimizeSize + ); + PlayerSettings.SetManagedStrippingLevel(NamedBuildTarget.iOS, ManagedStrippingLevel.High); + PlayerSettings.stripEngineCode = true; + PlayerSettings.SetIl2CppCompilerConfiguration( + NamedBuildTarget.iOS, + Il2CppCompilerConfiguration.Release + ); + + BuildReport report; + using (ApplyConfiguredAppId()) + report = BuildPipeline.BuildPlayer( + new BuildPlayerOptions + { + scenes = GetScenes(), + locationPathName = IOSOutputDir, + target = BuildTarget.iOS, + options = BuildOptions.None, + } + ); + + HandleReport(report, IOSOutputDir); + } + + private static IDisposable ApplyConfiguredAppId() + { + var appId = GetConfiguredAppId(); + if (string.IsNullOrWhiteSpace(appId)) + return AppIdOverride.Noop; + + var scenePath = GetMainScenePath(); + if (!File.Exists(scenePath)) + { + Debug.LogWarning($"[BuildScript] Could not find scene at {scenePath}"); + return AppIdOverride.Noop; + } + + var originalSceneContents = File.ReadAllText(scenePath); + var scene = EditorSceneManager.OpenScene(scenePath); + + foreach (var rootGameObject in scene.GetRootGameObjects()) + { + foreach (var component in rootGameObject.GetComponentsInChildren(true)) + { + if (component == null || component.GetType().Name != NoLocationDemoTypeName) + continue; + + var serializedObject = new SerializedObject(component); + var appIdProperty = serializedObject.FindProperty(OneSignalAppIdPropertyName); + if (appIdProperty == null) + continue; + + appIdProperty.stringValue = appId; + serializedObject.ApplyModifiedPropertiesWithoutUndo(); + EditorUtility.SetDirty(component); + EditorSceneManager.MarkSceneDirty(scene); + EditorSceneManager.SaveScene(scene); + Debug.Log( + $"[BuildScript] Applied {AppIdEnvironmentVariable} from environment or .env for this build." + ); + return new AppIdOverride(scenePath, originalSceneContents); + } + } + + Debug.LogWarning($"[BuildScript] Could not find {NoLocationDemoTypeName} in {scenePath}"); + return new AppIdOverride(scenePath, originalSceneContents); + } + + private static string GetConfiguredAppId() + { + var appId = Environment.GetEnvironmentVariable(AppIdEnvironmentVariable); + if (!string.IsNullOrWhiteSpace(appId)) + return Unquote(appId.Trim()); + + var envPath = Path.Combine(Directory.GetParent(Application.dataPath).FullName, ".env"); + if (!File.Exists(envPath)) + return null; + + foreach (var line in File.ReadAllLines(envPath)) + { + var trimmed = line.Trim(); + if (string.IsNullOrEmpty(trimmed) || trimmed.StartsWith("#")) + continue; + + if (trimmed.StartsWith("export ")) + trimmed = trimmed.Substring("export ".Length).TrimStart(); + + var separator = trimmed.IndexOf('='); + if (separator <= 0) + continue; + + var key = trimmed.Substring(0, separator).Trim(); + if (key != AppIdEnvironmentVariable) + continue; + + return Unquote(trimmed.Substring(separator + 1).Trim()); + } + + return null; + } + + private static string GetMainScenePath() + { + var scenes = GetScenes(); + foreach (var scenePath in scenes) + { + if (scenePath == MainScenePath) + return scenePath; + } + + return scenes.Length > 0 ? scenes[0] : MainScenePath; + } + + private static string Unquote(string value) + { + if (value.Length < 2) + return value; + + var first = value[0]; + var last = value[value.Length - 1]; + if ((first == '"' && last == '"') || (first == '\'' && last == '\'')) + return value.Substring(1, value.Length - 2); + + return value; + } + + private static string[] GetScenes() + { + var scenes = EditorBuildSettings.scenes; + if (scenes.Length == 0) + return new[] { "Assets/Scenes/Main.unity" }; + + return Array.ConvertAll(scenes, scene => scene.path); + } + + private static void HandleReport(BuildReport report, string outputPath) + { + if (report.summary.result == BuildResult.Succeeded) + { + Debug.Log($"[BuildScript] Build succeeded: {outputPath}"); + return; + } + + Debug.LogError( + $"[BuildScript] Build failed: {report.summary.result} - {report.summary.totalErrors} error(s)" + ); + EditorApplication.Exit(1); + } + + private sealed class AppIdOverride : IDisposable + { + internal static readonly AppIdOverride Noop = new AppIdOverride(null, null); + + private readonly string _scenePath; + private readonly string _originalSceneContents; + + internal AppIdOverride(string scenePath, string originalSceneContents) + { + _scenePath = scenePath; + _originalSceneContents = originalSceneContents; + } + + public void Dispose() + { + if (string.IsNullOrEmpty(_scenePath) || _originalSceneContents == null) + return; + + File.WriteAllText(_scenePath, _originalSceneContents); + AssetDatabase.ImportAsset(_scenePath); + } + } +} diff --git a/examples/demo-no-location/Assets/Scripts/Editor/BuildScript.cs.meta b/examples/demo-no-location/Assets/Scripts/Editor/BuildScript.cs.meta new file mode 100644 index 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/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/Assets/Scripts/NoLocationDemo.cs b/examples/demo-no-location/Assets/Scripts/NoLocationDemo.cs new file mode 100644 index 000000000..763b2775f --- /dev/null +++ b/examples/demo-no-location/Assets/Scripts/NoLocationDemo.cs @@ -0,0 +1,401 @@ +using System; +using System.Text; +using System.Threading.Tasks; +using OneSignalSDK; +using OneSignalSDK.Debug.Models; +using UnityEngine; +using UnityEngine.Networking; + +public sealed class NoLocationDemo : MonoBehaviour +{ + [SerializeField] + private string _oneSignalAppId = "YOUR-ONESIGNAL-APP-ID"; + + private const float ReferenceWidth = 393f; + private static readonly Color _backgroundColor = new Color32(248, 249, 250, 255); + private static readonly Color _primaryColor = new Color32(229, 75, 77, 255); + private static readonly Color _valueColor = new Color32(47, 52, 55, 255); + private static readonly Color _mutedTextColor = new Color32(97, 97, 97, 255); + private static readonly Color _labelColor = new Color32(107, 114, 128, 255); + private static readonly Color _dividerColor = new Color32(232, 234, 237, 255); + private static readonly Color _warningColor = new Color32(201, 37, 45, 255); + + private GUIStyle _bodyStyle; + private GUIStyle _buttonStyle; + private GUIStyle _cardStyle; + private GUIStyle _headerSubtitleStyle; + private GUIStyle _headerTitleStyle; + private GUIStyle _labelStyle; + private GUIStyle _outlineButtonStyle; + private GUIStyle _sectionHeaderStyle; + private GUIStyle _valueStyle; + private GUIStyle _warningValueStyle; + private Texture2D _cardTexture; + private Texture2D _dividerTexture; + private Texture2D _primaryTexture; + private Texture2D _whiteTexture; + private Texture2D _backgroundTexture; + private Vector2 _scrollPosition; + + private string _locationStatus = "Location test not run"; + private string _pushStatus = string.Empty; + private bool _initialized; + + private void Start() + { + OneSignal.Debug.LogLevel = LogLevel.Verbose; + + if (!IsConfigured) + return; + + OneSignal.Initialize(_oneSignalAppId); + _initialized = true; + } + + private void OnGUI() + { + EnsureStyles(); + + var scale = Mathf.Max(1f, Screen.width / ReferenceWidth); + var logicalWidth = Screen.width / scale; + var logicalHeight = Screen.height / scale; + var safeArea = ScaleRect(Screen.safeArea, 1f / scale); + var topInset = Mathf.Max(0f, logicalHeight - safeArea.yMax); + var bottomInset = Mathf.Max(0f, safeArea.y); + + var previousMatrix = GUI.matrix; + GUI.matrix = Matrix4x4.TRS(Vector3.zero, Quaternion.identity, new Vector3(scale, scale, 1f)); + + GUI.DrawTexture(new Rect(0, 0, logicalWidth, logicalHeight), _backgroundTexture); + + var headerHeight = topInset + 72f; + GUI.DrawTexture(new Rect(0, 0, logicalWidth, headerHeight), _primaryTexture); + GUI.Label(new Rect(16f, topInset + 12f, logicalWidth - 32f, 28f), "OneSignal", _headerTitleStyle); + GUI.Label( + new Rect(16f, topInset + 42f, logicalWidth - 32f, 20f), + "No-Location Demo", + _headerSubtitleStyle + ); + + var scrollRect = new Rect(0, headerHeight, logicalWidth, logicalHeight - headerHeight); + var contentWidth = logicalWidth - 32f; + var contentHeight = 740f + bottomInset; + + _scrollPosition = GUI.BeginScrollView( + scrollRect, + _scrollPosition, + new Rect(0, 0, logicalWidth, contentHeight), + false, + false + ); + + var y = 16f; + y = DrawAppSection(16f, y, contentWidth); + y = DrawPushSection(16f, y, contentWidth); + DrawLocationSection(16f, y, contentWidth); + + GUI.EndScrollView(); + GUI.matrix = previousMatrix; + } + + private float DrawAppSection(float x, float y, float width) + { + DrawSectionHeader(x, y, "APP"); + y += 24f; + + var cardHeight = 52f; + GUI.Box(new Rect(x, y, width, cardHeight), GUIContent.none, _cardStyle); + DrawKeyValueRow( + x + 12f, + y + 14f, + width - 24f, + "App ID", + _oneSignalAppId, + IsConfigured ? _valueStyle : _warningValueStyle + ); + + return y + cardHeight + 24f; + } + + private float DrawPushSection(float x, float y, float width) + { + DrawSectionHeader(x, y, "PUSH"); + y += 24f; + + var hasStatus = !string.IsNullOrEmpty(_pushStatus); + var cardHeight = hasStatus ? 280f : 252f; + GUI.Box(new Rect(x, y, width, cardHeight), GUIContent.none, _cardStyle); + + var contentX = x + 12f; + var contentWidth = width - 24f; + var permission = _initialized + ? OneSignal.Notifications.Permission + ? "Granted" + : "Not granted" + : "Not initialized"; + var pushId = _initialized ? FormatValue(OneSignal.User.PushSubscription.Id) : "-"; + + DrawKeyValueRow( + contentX, + y + 12f, + contentWidth, + "Permission", + permission, + _valueStyle + ); + DrawDivider(contentX, y + 45f, contentWidth); + DrawKeyValueRow(contentX, y + 58f, contentWidth, "Push ID", pushId, _valueStyle); + + if (GUI.Button(new Rect(contentX, y + 100f, contentWidth, 48f), "REQUEST PERMISSION", _buttonStyle)) + RequestPushPermission(); + + if (GUI.Button(new Rect(contentX, y + 156f, contentWidth, 48f), "SEND TEST NOTIFICATION", _buttonStyle)) + SendTestNotification(); + + if (hasStatus) + GUI.Label(new Rect(contentX, y + 212f, contentWidth, 56f), _pushStatus, _bodyStyle); + + return y + cardHeight + 24f; + } + + private void DrawLocationSection(float x, float y, float width) + { + DrawSectionHeader(x, y, "LOCATION MODULE"); + y += 24f; + + var cardHeight = 240f; + GUI.Box(new Rect(x, y, width, cardHeight), GUIContent.none, _cardStyle); + + var contentX = x + 12f; + var contentWidth = width - 24f; + GUI.Label( + new Rect(contentX, y + 12f, contentWidth, 74f), + "This demo initializes OneSignal and requests notification permission only when you tap the button above. Native builds exclude the location module.", + _bodyStyle + ); + + GUI.Label(new Rect(contentX, y + 94f, contentWidth, 72f), _locationStatus, _bodyStyle); + + if ( + GUI.Button( + new Rect(contentX, y + 180f, contentWidth, 48f), + "TEST LOCATION REQUEST", + _outlineButtonStyle + ) + ) + TestLocationRequest(); + } + + private void DrawSectionHeader(float x, float y, string text) => + GUI.Label(new Rect(x + 4f, y, 240f, 18f), text, _sectionHeaderStyle); + + private void DrawKeyValueRow( + float x, + float y, + float width, + string label, + string value, + GUIStyle valueStyle + ) + { + GUI.Label(new Rect(x, y, 92f, 22f), label, _labelStyle); + GUI.Label(new Rect(x + 100f, y, width - 100f, 44f), value, valueStyle); + } + + private void DrawDivider(float x, float y, float width) => + GUI.DrawTexture(new Rect(x, y, width, 1f), _dividerTexture); + + private void EnsureStyles() + { + if (_bodyStyle != null) + return; + + _cardTexture = MakeTexture(new Color32(255, 255, 255, 255)); + _dividerTexture = MakeTexture(_dividerColor); + _primaryTexture = MakeTexture(_primaryColor); + _whiteTexture = MakeTexture(new Color32(255, 255, 255, 255)); + _backgroundTexture = MakeTexture(_backgroundColor); + + _headerTitleStyle = new GUIStyle(GUI.skin.label) + { + normal = { textColor = Color.white }, + fontSize = 22, + fontStyle = FontStyle.Bold, + }; + _headerSubtitleStyle = new GUIStyle(GUI.skin.label) + { + normal = { textColor = Color.white }, + fontSize = 14, + }; + _sectionHeaderStyle = new GUIStyle(GUI.skin.label) + { + normal = { textColor = _mutedTextColor }, + fontSize = 12, + fontStyle = FontStyle.Bold, + }; + _cardStyle = new GUIStyle(GUI.skin.box) + { + normal = { background = _cardTexture }, + border = new RectOffset(12, 12, 12, 12), + padding = new RectOffset(0, 0, 0, 0), + }; + _labelStyle = new GUIStyle(GUI.skin.label) + { + normal = { textColor = _labelColor }, + fontSize = 14, + fontStyle = FontStyle.Bold, + }; + _valueStyle = new GUIStyle(GUI.skin.label) + { + normal = { textColor = _valueColor }, + fontSize = 13, + alignment = TextAnchor.UpperRight, + wordWrap = true, + }; + _warningValueStyle = new GUIStyle(_valueStyle) + { + normal = { textColor = _warningColor }, + }; + _bodyStyle = new GUIStyle(GUI.skin.label) + { + normal = { textColor = _mutedTextColor }, + fontSize = 14, + wordWrap = true, + }; + _buttonStyle = new GUIStyle(GUI.skin.button) + { + normal = { background = _primaryTexture, textColor = Color.white }, + active = { background = _primaryTexture, textColor = Color.white }, + hover = { background = _primaryTexture, textColor = Color.white }, + fontSize = 14, + fontStyle = FontStyle.Bold, + alignment = TextAnchor.MiddleCenter, + }; + _outlineButtonStyle = new GUIStyle(GUI.skin.button) + { + normal = { background = _whiteTexture, textColor = _primaryColor }, + active = { background = _whiteTexture, textColor = _primaryColor }, + hover = { background = _whiteTexture, textColor = _primaryColor }, + fontSize = 14, + fontStyle = FontStyle.Bold, + alignment = TextAnchor.MiddleCenter, + }; + } + + private async void RequestPushPermission() + { + if (!_initialized) + { + return; + } + + try + { + await OneSignal.Notifications.RequestPermissionAsync(false); + } + catch (System.Exception exception) + { + Debug.LogError($"[NoLocationDemo] Push permission request failed: {exception.Message}"); + } + } + + private async void SendTestNotification() + { + if (!_initialized || !IsConfigured) + { + _pushStatus = "Set ONESIGNAL_APP_ID before sending a test push."; + return; + } + + if (!OneSignal.Notifications.Permission) + { + _pushStatus = "Request notification permission before sending a test push."; + return; + } + + var pushSubscriptionId = OneSignal.User.PushSubscription.Id; + if (string.IsNullOrWhiteSpace(pushSubscriptionId)) + { + _pushStatus = "Allow notifications, then wait for a push ID."; + return; + } + + _pushStatus = "Sending test notification..."; + + try + { + var sent = await PostTestNotification(pushSubscriptionId); + _pushStatus = sent + ? "Test notification requested." + : "Send failed. Verify the OneSignal App ID."; + } + catch (Exception exception) + { + _pushStatus = $"Send failed: {exception.Message}"; + } + } + + private async Task PostTestNotification(string pushSubscriptionId) + { + var payload = + "{" + + $"\"app_id\":\"{_oneSignalAppId}\"," + + $"\"include_subscription_ids\":[\"{pushSubscriptionId}\"]," + + "\"headings\":{\"en\":\"OneSignal No-Location Demo\"}," + + "\"contents\":{\"en\":\"This test push was sent without linking the location module.\"}" + + "}"; + + using var request = new UnityWebRequest( + "https://onesignal.com/api/v1/notifications", + UnityWebRequest.kHttpVerbPOST + ); + request.uploadHandler = new UploadHandlerRaw(Encoding.UTF8.GetBytes(payload)); + request.downloadHandler = new DownloadHandlerBuffer(); + request.SetRequestHeader("Content-Type", "application/json"); + request.SetRequestHeader("Accept", "application/vnd.onesignal.v1+json"); + + var completion = new TaskCompletionSource(); + var operation = request.SendWebRequest(); + operation.completed += _ => completion.TrySetResult(true); + await completion.Task; + + return request.result == UnityWebRequest.Result.Success; + } + + private void TestLocationRequest() + { + if (!_initialized) + { + _locationStatus = "Initialize OneSignal before testing location."; + return; + } + + try + { + OneSignal.Location.RequestPermission(); + _locationStatus = "Location request completed without linking the location module."; + } + catch (System.Exception exception) + { + _locationStatus = $"Location request failed: {exception.Message}"; + } + } + + private bool IsConfigured => + !string.IsNullOrWhiteSpace(_oneSignalAppId) + && !_oneSignalAppId.StartsWith("YOUR-"); + + private static string FormatValue(string value) => + string.IsNullOrWhiteSpace(value) ? "-" : value; + + private static Rect ScaleRect(Rect rect, float scale) => + new Rect(rect.x * scale, rect.y * scale, rect.width * scale, rect.height * scale); + + private static Texture2D MakeTexture(Color color) + { + var texture = new Texture2D(1, 1); + texture.SetPixel(0, 0, color); + texture.Apply(); + return texture; + } +} diff --git a/examples/demo-no-location/Assets/Scripts/NoLocationDemo.cs.meta b/examples/demo-no-location/Assets/Scripts/NoLocationDemo.cs.meta new file mode 100644 index 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..7012c1bbc --- /dev/null +++ b/examples/demo-no-location/Packages/manifest.json @@ -0,0 +1,11 @@ +{ + "dependencies": { + "com.onesignal.unity.android": "file:../../../com.onesignal.unity.android", + "com.onesignal.unity.core": "file:../../../com.onesignal.unity.core", + "com.onesignal.unity.ios": "file:../../../com.onesignal.unity.ios", + "com.unity.modules.androidjni": "1.0.0", + "com.unity.modules.imgui": "1.0.0", + "com.unity.modules.jsonserialize": "1.0.0", + "com.unity.modules.unitywebrequest": "1.0.0" + } +} diff --git a/examples/demo-no-location/Packages/packages-lock.json b/examples/demo-no-location/Packages/packages-lock.json new file mode 100644 index 000000000..2f650a2cd --- /dev/null +++ b/examples/demo-no-location/Packages/packages-lock.json @@ -0,0 +1,50 @@ +{ + "dependencies": { + "com.onesignal.unity.android": { + "version": "file:../../../com.onesignal.unity.android", + "depth": 0, + "source": "local", + "dependencies": { + "com.onesignal.unity.core": "5.2.11" + } + }, + "com.onesignal.unity.core": { + "version": "file:../../../com.onesignal.unity.core", + "depth": 0, + "source": "local", + "dependencies": {} + }, + "com.onesignal.unity.ios": { + "version": "file:../../../com.onesignal.unity.ios", + "depth": 0, + "source": "local", + "dependencies": { + "com.onesignal.unity.core": "5.2.11" + } + }, + "com.unity.modules.androidjni": { + "version": "1.0.0", + "depth": 0, + "source": "builtin", + "dependencies": {} + }, + "com.unity.modules.imgui": { + "version": "1.0.0", + "depth": 0, + "source": "builtin", + "dependencies": {} + }, + "com.unity.modules.jsonserialize": { + "version": "1.0.0", + "depth": 0, + "source": "builtin", + "dependencies": {} + }, + "com.unity.modules.unitywebrequest": { + "version": "1.0.0", + "depth": 0, + "source": "builtin", + "dependencies": {} + } + } +} diff --git a/examples/demo-no-location/ProjectSettings/AndroidResolverDependencies.xml b/examples/demo-no-location/ProjectSettings/AndroidResolverDependencies.xml new file mode 100644 index 000000000..e50579a32 --- /dev/null +++ b/examples/demo-no-location/ProjectSettings/AndroidResolverDependencies.xml @@ -0,0 +1,25 @@ + + + com.onesignal:core:5.9.5 + com.onesignal:notifications:5.9.5 + com.onesignal:in-app-messages:5.9.5 + + + + + + + + + + + + + + + + + + + + diff --git a/examples/demo-no-location/ProjectSettings/EditorBuildSettings.asset b/examples/demo-no-location/ProjectSettings/EditorBuildSettings.asset new file mode 100644 index 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..153beef1d --- /dev/null +++ b/examples/demo-no-location/ProjectSettings/ProjectSettings.asset @@ -0,0 +1,896 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!129 &1 +PlayerSettings: + m_ObjectHideFlags: 0 + serializedVersion: 28 + productGUID: 8c68141ccf5e4fdf8af18b27d8f8cf22 + AndroidProfiler: 0 + AndroidFilterTouchesWhenObscured: 0 + AndroidEnableSustainedPerformanceMode: 0 + defaultScreenOrientation: 0 + targetDevice: 2 + useOnDemandResources: 0 + accelerometerFrequency: 60 + companyName: OneSignal + productName: OneSignal No-Location Demo + defaultCursor: {fileID: 0} + cursorHotspot: {x: 0, y: 0} + m_SplashScreenBackgroundColor: {r: 0.12941177, g: 0.12941177, b: 0.12941177, a: 1} + m_ShowUnitySplashScreen: 1 + m_ShowUnitySplashLogo: 1 + m_SplashScreenOverlayOpacity: 1 + m_SplashScreenAnimation: 1 + m_SplashScreenLogoStyle: 1 + m_SplashScreenDrawMode: 0 + m_SplashScreenBackgroundAnimationZoom: 1 + m_SplashScreenLogoAnimationZoom: 1 + m_SplashScreenBackgroundLandscapeAspect: 1 + m_SplashScreenBackgroundPortraitAspect: 1 + m_SplashScreenBackgroundLandscapeUvs: + serializedVersion: 2 + x: 0 + y: 0 + width: 1 + height: 1 + m_SplashScreenBackgroundPortraitUvs: + serializedVersion: 2 + x: 0 + y: 0 + width: 1 + height: 1 + m_SplashScreenLogos: [] + m_VirtualRealitySplashScreen: {fileID: 0} + defaultScreenWidth: 1920 + defaultScreenHeight: 1080 + defaultScreenWidthWeb: 960 + defaultScreenHeightWeb: 600 + m_StereoRenderingPath: 0 + m_ActiveColorSpace: 0 + unsupportedMSAAFallback: 0 + m_SpriteBatchMaxVertexCount: 65535 + m_SpriteBatchVertexThreshold: 300 + m_MTRendering: 1 + mipStripping: 0 + numberOfMipsStripped: 0 + numberOfMipsStrippedPerMipmapLimitGroup: {} + m_StackTraceTypes: 010000000100000001000000010000000100000001000000 + iosShowActivityIndicatorOnLoading: -1 + androidShowActivityIndicatorOnLoading: -1 + iosUseCustomAppBackgroundBehavior: 0 + allowedAutorotateToPortrait: 1 + allowedAutorotateToPortraitUpsideDown: 1 + allowedAutorotateToLandscapeRight: 1 + allowedAutorotateToLandscapeLeft: 1 + useOSAutorotation: 1 + use32BitDisplayBuffer: 1 + preserveFramebufferAlpha: 0 + disableDepthAndStencilBuffers: 0 + androidStartInFullscreen: 0 + androidRenderOutsideSafeArea: 0 + androidUseSwappy: 1 + androidDisplayOptions: 1 + androidBlitType: 0 + androidResizeableActivity: 1 + androidDefaultWindowWidth: 1920 + androidDefaultWindowHeight: 1080 + androidMinimumWindowWidth: 400 + androidMinimumWindowHeight: 300 + androidFullscreenMode: 1 + androidAutoRotationBehavior: 1 + androidPredictiveBackSupport: 1 + androidApplicationEntry: 1 + defaultIsNativeResolution: 1 + macRetinaSupport: 1 + runInBackground: 0 + muteOtherAudioSources: 0 + Prepare IOS For Recording: 0 + Force IOS Speakers When Recording: 0 + audioSpatialExperience: 0 + deferSystemGesturesMode: 0 + hideHomeButton: 0 + submitAnalytics: 1 + usePlayerLog: 1 + dedicatedServerOptimizations: 1 + bakeCollisionMeshes: 0 + forceSingleInstance: 0 + useFlipModelSwapchain: 1 + resizableWindow: 0 + useMacAppStoreValidation: 0 + macAppStoreCategory: public.app-category.games + gpuSkinning: 0 + meshDeformation: 0 + xboxPIXTextureCapture: 0 + xboxEnableAvatar: 0 + xboxEnableKinect: 0 + xboxEnableKinectAutoTracking: 0 + xboxEnableFitness: 0 + visibleInBackground: 1 + allowFullscreenSwitch: 1 + fullscreenMode: 1 + xboxSpeechDB: 0 + xboxEnableHeadOrientation: 0 + xboxEnableGuest: 0 + xboxEnablePIXSampling: 0 + metalFramebufferOnly: 0 + metalUseMetalDisplayLink: 0 + xboxOneResolution: 0 + xboxOneSResolution: 0 + xboxOneXResolution: 3 + xboxOneMonoLoggingLevel: 0 + xboxOneLoggingLevel: 1 + xboxOneDisableEsram: 0 + xboxOneEnableTypeOptimization: 0 + xboxOnePresentImmediateThreshold: 0 + switchQueueCommandMemory: 1048576 + switchQueueControlMemory: 16384 + switchQueueComputeMemory: 262144 + switchNVNShaderPoolsGranularity: 33554432 + switchNVNDefaultPoolsGranularity: 16777216 + switchNVNOtherPoolsGranularity: 16777216 + switchGpuScratchPoolGranularity: 2097152 + switchAllowGpuScratchShrinking: 0 + switchNVNMaxPublicTextureIDCount: 0 + switchNVNMaxPublicSamplerIDCount: 0 + switchMaxWorkerMultiple: 8 + switchNVNGraphicsFirmwareMemory: 32 + switchGraphicsJobsSyncAfterKick: 1 + vulkanNumSwapchainBuffers: 3 + vulkanEnableSetSRGBWrite: 0 + vulkanEnablePreTransform: 0 + vulkanEnableLateAcquireNextImage: 0 + vulkanEnableCommandBufferRecycling: 1 + loadStoreDebugModeEnabled: 0 + visionOSBundleVersion: 1.0 + tvOSBundleVersion: 1.0 + bundleVersion: 5.2.9 + preloadedAssets: [] + metroInputSource: 0 + wsaTransparentSwapchain: 0 + xboxOneDisableKinectGpuReservation: 1 + xboxOneEnable7thCore: 1 + vrSettings: + enable360StereoCapture: 0 + enableFrameTimingStats: 0 + enableOpenGLProfilerGPURecorders: 1 + allowHDRDisplaySupport: 0 + useHDRDisplay: 0 + hdrBitDepth: 0 + m_ColorGamuts: 00000000 + targetPixelDensity: 30 + resolutionScalingMode: 0 + resetResolutionOnWindowResize: 0 + androidSupportedAspectRatio: 1 + androidMaxAspectRatio: 2.4 + androidMinAspectRatio: 1 + applicationIdentifier: + Android: com.onesignal.example + iPhone: com.onesignal.example + buildNumber: + Standalone: 0 + VisionOS: 0 + iPhone: 1 + tvOS: 0 + overrideDefaultApplicationIdentifier: 1 + AndroidBundleVersionCode: 1 + AndroidMinSdkVersion: 25 + AndroidTargetSdkVersion: 34 + AndroidPreferredInstallLocation: 1 + AndroidPreferredDataLocation: 1 + aotOptions: + stripEngineCode: 1 + iPhoneStrippingLevel: 0 + iPhoneScriptCallOptimization: 0 + ForceInternetPermission: 0 + ForceSDCardPermission: 0 + CreateWallpaper: 0 + androidSplitApplicationBinary: 0 + keepLoadedShadersAlive: 0 + StripUnusedMeshComponents: 0 + strictShaderVariantMatching: 0 + VertexChannelCompressionMask: 4054 + iPhoneSdkVersion: 989 + iOSSimulatorArchitecture: 2 + iOSTargetOSVersionString: 15.0 + tvOSSdkVersion: 0 + tvOSSimulatorArchitecture: 0 + tvOSRequireExtendedGameController: 0 + tvOSTargetOSVersionString: 15.0 + VisionOSSdkVersion: 0 + VisionOSTargetOSVersionString: 1.0 + uIPrerenderedIcon: 0 + uIRequiresPersistentWiFi: 0 + uIRequiresFullScreen: 1 + uIStatusBarHidden: 1 + uIExitOnSuspend: 0 + uIStatusBarStyle: 0 + appleTVSplashScreen: {fileID: 0} + appleTVSplashScreen2x: {fileID: 0} + tvOSSmallIconLayers: [] + tvOSSmallIconLayers2x: [] + tvOSLargeIconLayers: [] + tvOSLargeIconLayers2x: [] + tvOSTopShelfImageLayers: [] + tvOSTopShelfImageLayers2x: [] + tvOSTopShelfImageWideLayers: [] + tvOSTopShelfImageWideLayers2x: [] + iOSLaunchScreenType: 0 + iOSLaunchScreenPortrait: {fileID: 0} + iOSLaunchScreenLandscape: {fileID: 0} + iOSLaunchScreenBackgroundColor: + serializedVersion: 2 + rgba: 0 + iOSLaunchScreenFillPct: 100 + iOSLaunchScreenSize: 100 + iOSLaunchScreeniPadType: 0 + iOSLaunchScreeniPadImage: {fileID: 0} + iOSLaunchScreeniPadBackgroundColor: + serializedVersion: 2 + rgba: 0 + iOSLaunchScreeniPadFillPct: 100 + iOSLaunchScreeniPadSize: 100 + iOSLaunchScreenCustomStoryboardPath: + iOSLaunchScreeniPadCustomStoryboardPath: + iOSDeviceRequirements: [] + iOSURLSchemes: [] + macOSURLSchemes: [] + iOSBackgroundModes: 0 + iOSMetalForceHardShadows: 0 + metalEditorSupport: 1 + metalAPIValidation: 1 + metalCompileShaderBinary: 0 + iOSRenderExtraFrameOnPause: 1 + iosCopyPluginsCodeInsteadOfSymlink: 0 + appleDeveloperTeamID: + iOSManualSigningProvisioningProfileID: + tvOSManualSigningProvisioningProfileID: + VisionOSManualSigningProvisioningProfileID: + iOSManualSigningProvisioningProfileType: 0 + tvOSManualSigningProvisioningProfileType: 0 + VisionOSManualSigningProvisioningProfileType: 0 + appleEnableAutomaticSigning: 0 + iOSRequireARKit: 0 + iOSAutomaticallyDetectAndAddCapabilities: 1 + appleEnableProMotion: 0 + shaderPrecisionModel: 0 + clonedFromGUID: 00000000000000000000000000000000 + templatePackageId: + templateDefaultScene: + useCustomMainManifest: 0 + useCustomLauncherManifest: 0 + useCustomMainGradleTemplate: 1 + useCustomLauncherGradleManifest: 0 + useCustomBaseGradleTemplate: 0 + useCustomGradlePropertiesTemplate: 1 + useCustomGradleSettingsTemplate: 1 + useCustomProguardFile: 1 + AndroidTargetArchitectures: 2 + AndroidAllowedArchitectures: -1 + AndroidSplashScreenScale: 0 + androidSplashScreen: {fileID: 0} + AndroidKeystoreName: + AndroidKeyaliasName: + AndroidEnableArmv9SecurityFeatures: 0 + AndroidEnableArm64MTE: 0 + AndroidBuildApkPerCpuArchitecture: 0 + AndroidTVCompatibility: 0 + AndroidIsGame: 1 + androidAppCategory: 3 + useAndroidAppCategory: 1 + androidAppCategoryOther: + AndroidEnableTango: 0 + androidEnableBanner: 1 + androidUseLowAccuracyLocation: 0 + androidUseCustomKeystore: 0 + m_AndroidBanners: + - width: 320 + height: 180 + banner: {fileID: 0} + androidGamepadSupportLevel: 0 + AndroidMinifyRelease: 1 + AndroidMinifyDebug: 0 + AndroidValidateAppBundleSize: 1 + AndroidAppBundleSizeToValidate: 200 + AndroidReportGooglePlayAppDependencies: 1 + androidSymbolsSizeThreshold: 800 + m_BuildTargetIcons: [] + m_BuildTargetPlatformIcons: + - m_BuildTarget: iPhone + m_Icons: + - m_Textures: [] + m_Width: 180 + m_Height: 180 + m_Kind: 0 + m_SubKind: iPhone + - m_Textures: [] + m_Width: 120 + m_Height: 120 + m_Kind: 0 + m_SubKind: iPhone + - m_Textures: [] + m_Width: 167 + m_Height: 167 + m_Kind: 0 + m_SubKind: iPad + - m_Textures: [] + m_Width: 152 + m_Height: 152 + m_Kind: 0 + m_SubKind: iPad + - m_Textures: [] + m_Width: 76 + m_Height: 76 + m_Kind: 0 + m_SubKind: iPad + - m_Textures: [] + m_Width: 120 + m_Height: 120 + m_Kind: 3 + m_SubKind: iPhone + - m_Textures: [] + m_Width: 80 + m_Height: 80 + m_Kind: 3 + m_SubKind: iPhone + - m_Textures: [] + m_Width: 80 + m_Height: 80 + m_Kind: 3 + m_SubKind: iPad + - m_Textures: [] + m_Width: 40 + m_Height: 40 + m_Kind: 3 + m_SubKind: iPad + - m_Textures: [] + m_Width: 87 + m_Height: 87 + m_Kind: 1 + m_SubKind: iPhone + - m_Textures: [] + m_Width: 58 + m_Height: 58 + m_Kind: 1 + m_SubKind: iPhone + - m_Textures: [] + m_Width: 29 + m_Height: 29 + m_Kind: 1 + m_SubKind: iPhone + - m_Textures: [] + m_Width: 58 + m_Height: 58 + m_Kind: 1 + m_SubKind: iPad + - m_Textures: [] + m_Width: 29 + m_Height: 29 + m_Kind: 1 + m_SubKind: iPad + - m_Textures: [] + m_Width: 60 + m_Height: 60 + m_Kind: 2 + m_SubKind: iPhone + - m_Textures: [] + m_Width: 40 + m_Height: 40 + m_Kind: 2 + m_SubKind: iPhone + - m_Textures: [] + m_Width: 40 + m_Height: 40 + m_Kind: 2 + m_SubKind: iPad + - m_Textures: [] + m_Width: 20 + m_Height: 20 + m_Kind: 2 + m_SubKind: iPad + - m_Textures: [] + m_Width: 1024 + m_Height: 1024 + m_Kind: 4 + m_SubKind: App Store + - m_BuildTarget: Android + m_Icons: + - m_Textures: [] + m_Width: 432 + m_Height: 432 + m_Kind: 2 + m_SubKind: + - m_Textures: [] + m_Width: 324 + m_Height: 324 + m_Kind: 2 + m_SubKind: + - m_Textures: [] + m_Width: 216 + m_Height: 216 + m_Kind: 2 + m_SubKind: + - m_Textures: [] + m_Width: 162 + m_Height: 162 + m_Kind: 2 + m_SubKind: + - m_Textures: [] + m_Width: 108 + m_Height: 108 + m_Kind: 2 + m_SubKind: + - m_Textures: [] + m_Width: 81 + m_Height: 81 + m_Kind: 2 + m_SubKind: + - m_Textures: [] + m_Width: 192 + m_Height: 192 + m_Kind: 1 + m_SubKind: + - m_Textures: [] + m_Width: 144 + m_Height: 144 + m_Kind: 1 + m_SubKind: + - m_Textures: [] + m_Width: 96 + m_Height: 96 + m_Kind: 1 + m_SubKind: + - m_Textures: [] + m_Width: 72 + m_Height: 72 + m_Kind: 1 + m_SubKind: + - m_Textures: [] + m_Width: 48 + m_Height: 48 + m_Kind: 1 + m_SubKind: + - m_Textures: [] + m_Width: 36 + m_Height: 36 + m_Kind: 1 + m_SubKind: + - m_Textures: [] + m_Width: 192 + m_Height: 192 + m_Kind: 0 + m_SubKind: + - m_Textures: [] + m_Width: 144 + m_Height: 144 + m_Kind: 0 + m_SubKind: + - m_Textures: [] + m_Width: 96 + m_Height: 96 + m_Kind: 0 + m_SubKind: + - m_Textures: [] + m_Width: 72 + m_Height: 72 + m_Kind: 0 + m_SubKind: + - m_Textures: [] + m_Width: 48 + m_Height: 48 + m_Kind: 0 + m_SubKind: + - m_Textures: [] + m_Width: 36 + m_Height: 36 + m_Kind: 0 + m_SubKind: + m_BuildTargetBatching: [] + m_BuildTargetShaderSettings: [] + m_BuildTargetGraphicsJobs: [] + m_BuildTargetGraphicsJobMode: [] + m_BuildTargetGraphicsAPIs: [] + m_BuildTargetVRSettings: [] + m_DefaultShaderChunkSizeInMB: 16 + m_DefaultShaderChunkCount: 0 + openGLRequireES31: 0 + openGLRequireES31AEP: 0 + openGLRequireES32: 0 + m_TemplateCustomTags: {} + mobileMTRendering: + Android: 1 + VisionOS: 1 + iPhone: 1 + tvOS: 1 + m_BuildTargetGroupLightmapEncodingQuality: [] + m_BuildTargetGroupHDRCubemapEncodingQuality: [] + m_BuildTargetGroupLightmapSettings: [] + m_BuildTargetGroupLoadStoreDebugModeSettings: [] + m_BuildTargetNormalMapEncoding: [] + m_BuildTargetDefaultTextureCompressionFormat: [] + playModeTestRunnerEnabled: 0 + runPlayModeTestAsEditModeTest: 0 + actionOnDotNetUnhandledException: 1 + editorGfxJobOverride: 1 + enableInternalProfiler: 0 + logObjCUncaughtExceptions: 1 + enableCrashReportAPI: 0 + cameraUsageDescription: + locationUsageDescription: + microphoneUsageDescription: + bluetoothUsageDescription: + macOSTargetOSVersion: 12.0 + switchNMETAOverride: + switchNetLibKey: + switchSocketMemoryPoolSize: 6144 + switchSocketAllocatorPoolSize: 128 + switchSocketConcurrencyLimit: 14 + switchScreenResolutionBehavior: 2 + switchUseCPUProfiler: 0 + switchEnableFileSystemTrace: 0 + switchLTOSetting: 0 + switchApplicationID: 0x01004b9000490000 + switchNSODependencies: + switchCompilerFlags: + switchTitleNames_0: + switchTitleNames_1: + switchTitleNames_2: + switchTitleNames_3: + switchTitleNames_4: + switchTitleNames_5: + switchTitleNames_6: + switchTitleNames_7: + switchTitleNames_8: + switchTitleNames_9: + switchTitleNames_10: + switchTitleNames_11: + switchTitleNames_12: + switchTitleNames_13: + switchTitleNames_14: + switchTitleNames_15: + switchPublisherNames_0: + switchPublisherNames_1: + switchPublisherNames_2: + switchPublisherNames_3: + switchPublisherNames_4: + switchPublisherNames_5: + switchPublisherNames_6: + switchPublisherNames_7: + switchPublisherNames_8: + switchPublisherNames_9: + switchPublisherNames_10: + switchPublisherNames_11: + switchPublisherNames_12: + switchPublisherNames_13: + switchPublisherNames_14: + switchPublisherNames_15: + switchIcons_0: {fileID: 0} + switchIcons_1: {fileID: 0} + switchIcons_2: {fileID: 0} + switchIcons_3: {fileID: 0} + switchIcons_4: {fileID: 0} + switchIcons_5: {fileID: 0} + switchIcons_6: {fileID: 0} + switchIcons_7: {fileID: 0} + switchIcons_8: {fileID: 0} + switchIcons_9: {fileID: 0} + switchIcons_10: {fileID: 0} + switchIcons_11: {fileID: 0} + switchIcons_12: {fileID: 0} + switchIcons_13: {fileID: 0} + switchIcons_14: {fileID: 0} + switchIcons_15: {fileID: 0} + switchSmallIcons_0: {fileID: 0} + switchSmallIcons_1: {fileID: 0} + switchSmallIcons_2: {fileID: 0} + switchSmallIcons_3: {fileID: 0} + switchSmallIcons_4: {fileID: 0} + switchSmallIcons_5: {fileID: 0} + switchSmallIcons_6: {fileID: 0} + switchSmallIcons_7: {fileID: 0} + switchSmallIcons_8: {fileID: 0} + switchSmallIcons_9: {fileID: 0} + switchSmallIcons_10: {fileID: 0} + switchSmallIcons_11: {fileID: 0} + switchSmallIcons_12: {fileID: 0} + switchSmallIcons_13: {fileID: 0} + switchSmallIcons_14: {fileID: 0} + switchSmallIcons_15: {fileID: 0} + switchManualHTML: + switchAccessibleURLs: + switchLegalInformation: + switchMainThreadStackSize: 1048576 + switchPresenceGroupId: + switchLogoHandling: 0 + switchReleaseVersion: 0 + switchDisplayVersion: 1.0.0 + switchStartupUserAccount: 0 + switchSupportedLanguagesMask: 0 + switchLogoType: 0 + switchApplicationErrorCodeCategory: + switchUserAccountSaveDataSize: 0 + switchUserAccountSaveDataJournalSize: 0 + switchApplicationAttribute: 0 + switchCardSpecSize: -1 + switchCardSpecClock: -1 + switchRatingsMask: 0 + switchRatingsInt_0: 0 + switchRatingsInt_1: 0 + switchRatingsInt_2: 0 + switchRatingsInt_3: 0 + switchRatingsInt_4: 0 + switchRatingsInt_5: 0 + switchRatingsInt_6: 0 + switchRatingsInt_7: 0 + switchRatingsInt_8: 0 + switchRatingsInt_9: 0 + switchRatingsInt_10: 0 + switchRatingsInt_11: 0 + switchRatingsInt_12: 0 + switchLocalCommunicationIds_0: + switchLocalCommunicationIds_1: + switchLocalCommunicationIds_2: + switchLocalCommunicationIds_3: + switchLocalCommunicationIds_4: + switchLocalCommunicationIds_5: + switchLocalCommunicationIds_6: + switchLocalCommunicationIds_7: + switchParentalControl: 0 + switchAllowsScreenshot: 1 + switchAllowsVideoCapturing: 1 + switchAllowsRuntimeAddOnContentInstall: 0 + switchDataLossConfirmation: 0 + switchUserAccountLockEnabled: 0 + switchSystemResourceMemory: 16777216 + switchSupportedNpadStyles: 22 + switchNativeFsCacheSize: 32 + switchIsHoldTypeHorizontal: 1 + switchSupportedNpadCount: 8 + switchEnableTouchScreen: 1 + switchSocketConfigEnabled: 0 + switchTcpInitialSendBufferSize: 32 + switchTcpInitialReceiveBufferSize: 64 + switchTcpAutoSendBufferSizeMax: 256 + switchTcpAutoReceiveBufferSizeMax: 256 + switchUdpSendBufferSize: 9 + switchUdpReceiveBufferSize: 42 + switchSocketBufferEfficiency: 4 + switchSocketInitializeEnabled: 1 + switchNetworkInterfaceManagerInitializeEnabled: 1 + switchDisableHTCSPlayerConnection: 0 + switchUseNewStyleFilepaths: 1 + switchUseLegacyFmodPriorities: 0 + switchUseMicroSleepForYield: 1 + switchEnableRamDiskSupport: 0 + switchMicroSleepForYieldTime: 25 + switchRamDiskSpaceSize: 12 + switchUpgradedPlayerSettingsToNMETA: 0 + ps4NPAgeRating: 12 + ps4NPTitleSecret: + ps4NPTrophyPackPath: + ps4ParentalLevel: 11 + ps4ContentID: ED1633-NPXX51362_00-0000000000000000 + ps4Category: 0 + ps4MasterVersion: 01.00 + ps4AppVersion: 01.00 + ps4AppType: 0 + ps4ParamSfxPath: + ps4VideoOutPixelFormat: 0 + ps4VideoOutInitialWidth: 1920 + ps4VideoOutBaseModeInitialWidth: 1920 + ps4VideoOutReprojectionRate: 60 + ps4PronunciationXMLPath: + ps4PronunciationSIGPath: + ps4BackgroundImagePath: + ps4StartupImagePath: + ps4StartupImagesFolder: + ps4IconImagesFolder: + ps4SaveDataImagePath: + ps4SdkOverride: + ps4BGMPath: + ps4ShareFilePath: + ps4ShareOverlayImagePath: + ps4PrivacyGuardImagePath: + ps4ExtraSceSysFile: + ps4NPtitleDatPath: + ps4RemotePlayKeyAssignment: -1 + ps4RemotePlayKeyMappingDir: + ps4PlayTogetherPlayerCount: 0 + ps4EnterButtonAssignment: 2 + ps4ApplicationParam1: 0 + ps4ApplicationParam2: 0 + ps4ApplicationParam3: 0 + ps4ApplicationParam4: 0 + ps4DownloadDataSize: 0 + ps4GarlicHeapSize: 2048 + ps4ProGarlicHeapSize: 2560 + playerPrefsMaxSize: 32768 + ps4Passcode: Ti337x0jGPK6DloiDZUkKLLmVBjcfPCk + ps4pnSessions: 1 + ps4pnPresence: 1 + ps4pnFriends: 1 + ps4pnGameCustomData: 1 + playerPrefsSupport: 0 + enableApplicationExit: 0 + resetTempFolder: 1 + restrictedAudioUsageRights: 0 + ps4UseResolutionFallback: 0 + ps4ReprojectionSupport: 0 + ps4UseAudio3dBackend: 0 + ps4UseLowGarlicFragmentationMode: 1 + ps4SocialScreenEnabled: 0 + ps4ScriptOptimizationLevel: 2 + ps4Audio3dVirtualSpeakerCount: 14 + ps4attribCpuUsage: 0 + ps4PatchPkgPath: + ps4PatchLatestPkgPath: + ps4PatchChangeinfoPath: + ps4PatchDayOne: 0 + ps4attribUserManagement: 0 + ps4attribMoveSupport: 0 + ps4attrib3DSupport: 0 + ps4attribShareSupport: 0 + ps4attribExclusiveVR: 0 + ps4disableAutoHideSplash: 0 + ps4videoRecordingFeaturesUsed: 0 + ps4contentSearchFeaturesUsed: 0 + ps4CompatibilityPS5: 0 + ps4AllowPS5Detection: 0 + ps4GPU800MHz: 1 + ps4attribEyeToEyeDistanceSettingVR: 0 + ps4IncludedModules: [] + ps4attribVROutputEnabled: 0 + monoEnv: + splashScreenBackgroundSourceLandscape: {fileID: 0} + splashScreenBackgroundSourcePortrait: {fileID: 0} + blurSplashScreenBackground: 1 + spritePackerPolicy: + webGLMemorySize: 32 + webGLExceptionSupport: 1 + webGLNameFilesAsHashes: 0 + webGLShowDiagnostics: 0 + webGLDataCaching: 1 + webGLDebugSymbols: 0 + webGLEmscriptenArgs: + webGLModulesDirectory: + webGLTemplate: APPLICATION:Default + webGLAnalyzeBuildSize: 0 + webGLUseEmbeddedResources: 0 + webGLCompressionFormat: 1 + webGLWasmArithmeticExceptions: 0 + webGLLinkerTarget: 1 + webGLThreadsSupport: 0 + webGLDecompressionFallback: 0 + webGLInitialMemorySize: 32 + webGLMaximumMemorySize: 2048 + webGLMemoryGrowthMode: 2 + webGLMemoryLinearGrowthStep: 16 + webGLMemoryGeometricGrowthStep: 0.2 + webGLMemoryGeometricGrowthCap: 96 + webGLPowerPreference: 2 + webGLWebAssemblyTable: 0 + webGLWebAssemblyBigInt: 0 + webGLCloseOnQuit: 0 + webWasm2023: 0 + webEnableSubmoduleStrippingCompatibility: 0 + scriptingDefineSymbols: {} + additionalCompilerArguments: {} + platformArchitecture: {} + scriptingBackend: + Android: 1 + iPhone: 1 + il2cppCompilerConfiguration: + Android: 1 + il2cppCodeGeneration: + Android: 1 + iPhone: 1 + il2cppStacktraceInformation: {} + managedStrippingLevel: + Android: 3 + iPhone: 3 + incrementalIl2cppBuild: {} + suppressCommonWarnings: 1 + allowUnsafeCode: 0 + useDeterministicCompilation: 1 + additionalIl2CppArgs: + scriptingRuntimeVersion: 1 + gcIncremental: 1 + gcWBarrierValidation: 0 + apiCompatibilityLevelPerPlatform: {} + editorAssembliesCompatibilityLevel: 1 + m_RenderingPath: 1 + m_MobileRenderingPath: 1 + metroPackageName: demo-no-location + metroPackageVersion: + metroCertificatePath: + metroCertificatePassword: + metroCertificateSubject: + metroCertificateIssuer: + metroCertificateNotAfter: 0000000000000000 + metroApplicationDescription: demo-no-location + wsaImages: {} + metroTileShortName: + metroTileShowName: 0 + metroMediumTileShowName: 0 + metroLargeTileShowName: 0 + metroWideTileShowName: 0 + metroSupportStreamingInstall: 0 + metroLastRequiredScene: 0 + metroDefaultTileSize: 1 + metroTileForegroundText: 2 + metroTileBackgroundColor: {r: 0.13333334, g: 0.17254902, b: 0.21568628, a: 0} + metroSplashScreenBackgroundColor: {r: 0.12941177, g: 0.17254902, b: 0.21568628, a: 1} + metroSplashScreenUseBackgroundColor: 0 + syncCapabilities: 0 + platformCapabilities: {} + metroTargetDeviceFamilies: {} + metroFTAName: + metroFTAFileTypes: [] + metroProtocolName: + vcxProjDefaultLanguage: + XboxOneProductId: + XboxOneUpdateKey: + XboxOneSandboxId: + XboxOneContentId: + XboxOneTitleId: + XboxOneSCId: + XboxOneGameOsOverridePath: + XboxOnePackagingOverridePath: + XboxOneAppManifestOverridePath: + XboxOneVersion: 1.0.0.0 + XboxOnePackageEncryption: 0 + XboxOnePackageUpdateGranularity: 2 + XboxOneDescription: + XboxOneLanguage: + - enus + XboxOneCapability: [] + XboxOneGameRating: {} + XboxOneIsContentPackage: 0 + XboxOneEnhancedXboxCompatibilityMode: 0 + XboxOneEnableGPUVariability: 1 + XboxOneSockets: {} + XboxOneSplashScreen: {fileID: 0} + XboxOneAllowedProductIds: [] + XboxOnePersistentLocalStorageSize: 0 + XboxOneXTitleMemory: 8 + XboxOneOverrideIdentityName: + XboxOneOverrideIdentityPublisher: + vrEditorSettings: {} + cloudServicesEnabled: {} + luminIcon: + m_Name: + m_ModelFolderPath: + m_PortalFolderPath: + luminCert: + m_CertPath: + m_SignPackage: 1 + luminIsChannelApp: 0 + luminVersion: + m_VersionCode: 1 + m_VersionName: + hmiPlayerDataPath: + hmiForceSRGBBlit: 0 + embeddedLinuxEnableGamepadInput: 0 + hmiCpuConfiguration: + hmiLogStartupTiming: 0 + qnxGraphicConfPath: + apiCompatibilityLevel: 6 + captureStartupLogs: {} + activeInputHandler: -1 + windowsGamepadBackendHint: 0 + enableDirectStorage: 0 + cloudProjectId: + framebufferDepthMemorylessMode: 0 + qualitySettingsNames: [] + projectName: + organizationId: + cloudEnabled: 0 + legacyClampBlendShapeWeights: 1 + hmiLoadingImage: {fileID: 0} + platformRequiresReadableAssets: 0 + virtualTexturingSupportEnabled: 0 + insecureHttpOption: 0 + androidVulkanDenyFilterList: [] + androidVulkanAllowFilterList: [] + androidVulkanDeviceFilterListAsset: {fileID: 0} + d3d12DeviceFilterListAsset: {fileID: 0} + allowedHttpConnections: 3 diff --git a/examples/demo-no-location/ProjectSettings/ProjectVersion.txt b/examples/demo-no-location/ProjectSettings/ProjectVersion.txt new file mode 100644 index 000000000..29501ff03 --- /dev/null +++ b/examples/demo-no-location/ProjectSettings/ProjectVersion.txt @@ -0,0 +1,2 @@ +m_EditorVersion: 6000.4.11f1 +m_EditorVersionWithRevision: 6000.4.11f1 (b0a1d6caadd2) diff --git a/examples/demo-no-location/README.md b/examples/demo-no-location/README.md new file mode 100644 index 000000000..7f7c1ef9b --- /dev/null +++ b/examples/demo-no-location/README.md @@ -0,0 +1,130 @@ +# OneSignal No-Location Demo + +Minimal Unity project for apps that use OneSignal without the native location module. + +This demo opts out of location two ways, so it stays no-location whether you build from the Editor or the command line: + +- The `run-ios.sh` and `run-android.sh` scripts export `ONESIGNAL_DISABLE_LOCATION=true` before launching Unity. The environment variable takes precedence over the Editor toggle. +- The Editor toggle is checked in for interactive use (`ProjectSettings/OneSignalSettings.json`): + + ```json + { + "disableLocation": true + } + ``` + +If you open the project in the Editor without the environment variable, confirm **OneSignal > Disable Location Module** is checked before resolving Android dependencies or building iOS. + +## Configure App ID + +For scripted builds, `run-android.sh` and `run-ios.sh` read `ONESIGNAL_APP_ID` from the shell environment or from `.env` in this folder. The environment variable wins if both are set. + +```sh +cp .env.example .env +``` + +Then edit `.env`: + +```sh +ONESIGNAL_APP_ID=YOUR-ONESIGNAL-APP-ID +``` + +The build injects that value into the generated app without saving it into the tracked scene file. + +For Play Mode in the Unity Editor: + +1. Open `Assets/Scenes/Main.unity`. +2. Select the `OneSignal No Location Demo` GameObject. +3. Set `One Signal App Id` on the `NoLocationDemo` component. + +If the value is left as `YOUR-ONESIGNAL-APP-ID`, the app starts but does not initialize OneSignal. + +## Run On Android + +Have an Android emulator running, then run: + +```sh +./run-android.sh +``` + +Useful options: + +```sh +./run-android.sh --no-install +./run-android.sh --install-only +``` + +Set `UNITY_PATH` if you want to use a specific Unity executable. Set `ADB` or `ANDROID_HOME` if the script cannot find `adb`. + +## Run On iOS + +Have an iOS simulator booted, then run: + +```sh +./run-ios.sh +``` + +Recent macOS ships `openrsync` as `/usr/bin/rsync`, which fails the CocoaPods "Copy XCFrameworks" build phase (`renameat: No such file or directory` on the OneSignal dSYM). Install a real rsync once and `run-ios.sh` will prefer it automatically: + +```sh +brew install rsync +``` + +Useful options: + +```sh +./run-ios.sh --no-install +./run-ios.sh --install-only +./run-ios.sh --open +``` + +Set `UNITY_PATH` if you want to use a specific Unity executable. + +The iOS script generates a minimal Podfile when External Dependency Manager does not create one, then runs `pod install` and builds the generated Xcode workspace. + +## Native Dependencies + +The SDK generates the EDM4U manifests per project at `Assets/OneSignal/Editor/OneSignal{Android,iOS}Dependencies.xml` based on the location flag, so the granular (no-location) dependency set below is what EDM4U resolves for this demo. + +### Android + +The resolver snapshot uses OneSignal native modules without the location artifact: + +```xml +com.onesignal:core:5.9.5 +com.onesignal:notifications:5.9.5 +com.onesignal:in-app-messages:5.9.5 +``` + +If you force-resolve again, keep the location module disabled. + +### iOS + +When location is disabled, iOS uses OneSignal pods without `OneSignalLocation`: + +```xml + + +``` + +The notification service extension still uses `OneSignalXCFramework/OneSignalExtension`. + +## App Code + +`NoLocationDemo.cs` initializes OneSignal, requests push permission, sends a test push to the current subscription via the OneSignal REST API, and includes a test button for `OneSignal.Location.RequestPermission()`. With the native location module excluded, location calls no-op and `OneSignal.Location.IsShared` returns `false`. + +The test push is sent with the app ID only (no REST API key), targeting the current `include_subscription_ids`, matching the other OneSignal no-location demos. + +## Code Stripping (`link.xml`) + +`Assets/OneSignal/link.xml` is required. Do not delete it. + +The scripted builds use `ManagedStrippingLevel.High`, and the OneSignal platform implementations (`OneSignaliOS`, `OneSignalAndroid`) are resolved by reflection at runtime. Without this file, IL2CPP strips those types, so `OneSignal.Default` throws on first use and the SDK never initializes (the app shows `Not initialized` and no permission prompt appears). + +In a normal SDK integration the OneSignal Setup window generates this file automatically; this demo is built headlessly via `BuildScript`, so the file is checked in instead. + +## Generated Files + +Unity build output is generated under `Build/`, `Library/`, `Logs/`, and `UserSettings/`. These folders are ignored. + +Unity may also generate extra files under `ProjectSettings/`; this demo tracks only the minimal settings files needed to keep the project reproducible. diff --git a/examples/demo-no-location/run-android.sh b/examples/demo-no-location/run-android.sh new file mode 100755 index 000000000..255d90fb3 --- /dev/null +++ b/examples/demo-no-location/run-android.sh @@ -0,0 +1,105 @@ +#!/bin/sh +# Build the OneSignal Unity no-location demo APK and install it on a running emulator. +# +# Usage: +# ./run-android.sh [--no-install] [--install-only] +set -eu + +# Opt out of the OneSignal location module for this build. The SDK reads this at +# dependency-resolution time and links the granular artifacts without location. +export ONESIGNAL_DISABLE_LOCATION=true + +SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)" + +find_unity() { + if [ -n "${UNITY_PATH:-}" ]; then + echo "$UNITY_PATH" + return + fi + for d in $(ls -1 /Applications/Unity/Hub/Editor 2>/dev/null | sort -rV); do + BIN="/Applications/Unity/Hub/Editor/$d/Unity.app/Contents/MacOS/Unity" + [ -x "$BIN" ] && echo "$BIN" && return + done +} +UNITY="$(find_unity)" + +find_adb() { + if [ -n "${ADB:-}" ] && [ -x "$ADB" ]; then echo "$ADB"; return; fi + for CANDIDATE in \ + "${ANDROID_HOME:-}/platform-tools/adb" \ + "${ANDROID_SDK_ROOT:-}/platform-tools/adb" \ + "$HOME/Library/Android/sdk/platform-tools/adb"; do + [ -x "$CANDIDATE" ] && echo "$CANDIDATE" && return + done + if command -v adb >/dev/null 2>&1; then command -v adb; return; fi + if [ -n "$UNITY" ]; then + UNITY_DIR=$(dirname "$(dirname "$(dirname "$(dirname "$UNITY")")")") + CANDIDATE="$UNITY_DIR/PlaybackEngines/AndroidPlayer/SDK/platform-tools/adb" + [ -x "$CANDIDATE" ] && echo "$CANDIDATE" && return + fi +} +ADB="$(find_adb)" + +OUTPUT="$SCRIPT_DIR/Build/Android/onesignal-demo-no-location.apk" +LOG="$SCRIPT_DIR/Build/build-android.log" +INSTALL=true +SKIP_BUILD=false + +for arg in "$@"; do + case "$arg" in + --no-install) INSTALL=false ;; + --install-only) SKIP_BUILD=true ;; + esac +done + +pick_emulator() { + [ -z "$ADB" ] && echo "adb not found. Set ADB or ANDROID_HOME to your Android SDK." && exit 1 + LIST=$("$ADB" devices | awk '/emulator-[0-9]+[[:space:]]+device/{print $1}') + COUNT=$(printf '%s\n' "$LIST" | grep -c . || true) + + [ "$COUNT" -eq 0 ] && echo "No running emulators found." && exit 1 + [ "$COUNT" -eq 1 ] && EMULATOR="$LIST" && return + + echo "Multiple emulators running - pick one:" + i=1 + printf '%s\n' "$LIST" | while IFS= read -r S; do + NAME=$("$ADB" -s "$S" emu avd name 2>/dev/null | sed -n '1p' | tr -d '\r') + printf " [%d] %s (%s)\n" "$i" "$S" "$NAME" + i=$((i + 1)) + done + printf "Choice [1-%d]: " "$COUNT" + read -r CHOICE + EMULATOR=$(printf '%s\n' "$LIST" | sed -n "${CHOICE}p") + [ -z "$EMULATOR" ] && echo "Invalid choice." && exit 1 +} + +EMULATOR="" +[ "$INSTALL" = true ] && pick_emulator && echo "Target: $EMULATOR" && echo "" + +if [ "$SKIP_BUILD" = true ]; then + [ ! -f "$OUTPUT" ] && echo "No existing build. Run without --install-only first." && exit 1 + echo "Skipping build, using existing $(du -sh "$OUTPUT" | awk '{print $1}') APK" +else + [ ! -x "$UNITY" ] && echo "Unity not found at $UNITY - set UNITY_PATH" && exit 1 + mkdir -p "$SCRIPT_DIR/Build/Android" + echo "Building no-location APK (ARM64 / IL2CPP)..." + echo "Log: $LOG" + echo "" + + START=$(date +%s) + "$UNITY" -batchmode -nographics -quit -buildTarget Android \ + -projectPath "$SCRIPT_DIR" -executeMethod BuildScript.BuildAndroidEmulator \ + -logFile "$LOG" + ELAPSED=$(( $(date +%s) - START )) + + [ ! -f "$OUTPUT" ] && echo "Build failed after $((ELAPSED/60))m $((ELAPSED%60))s. Check $LOG" && exit 1 + echo "Build complete in $((ELAPSED/60))m $((ELAPSED%60))s - $(du -sh "$OUTPUT" | awk '{print $1}') $OUTPUT" +fi + +if [ "$INSTALL" = true ] && [ -n "$EMULATOR" ]; then + "$ADB" start-server >/dev/null 2>&1 + "$ADB" -s "$EMULATOR" wait-for-device + echo "Installing on $EMULATOR..." + "$ADB" -s "$EMULATOR" install -r "$OUTPUT" + "$ADB" -s "$EMULATOR" shell am start -n com.onesignal.example/com.unity3d.player.UnityPlayerActivity +fi diff --git a/examples/demo-no-location/run-ios.sh b/examples/demo-no-location/run-ios.sh new file mode 100755 index 000000000..c3f1bed78 --- /dev/null +++ b/examples/demo-no-location/run-ios.sh @@ -0,0 +1,214 @@ +#!/bin/sh +# Build the OneSignal Unity no-location demo for iOS simulator. +# +# Usage: +# ./run-ios.sh [--no-install] [--install-only] [--open] +set -eu + +# Opt out of the OneSignal location module for this build. The SDK reads this at +# dependency-resolution time and links the granular pods without OneSignalLocation. +export ONESIGNAL_DISABLE_LOCATION=true + +SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)" + +find_unity() { + if [ -n "${UNITY_PATH:-}" ]; then + echo "$UNITY_PATH" + return + fi + for d in $(ls -1 /Applications/Unity/Hub/Editor 2>/dev/null | sort -rV); do + BIN="/Applications/Unity/Hub/Editor/$d/Unity.app/Contents/MacOS/Unity" + [ -x "$BIN" ] && echo "$BIN" && return + done +} +UNITY="$(find_unity)" + +XCODE_DIR="$SCRIPT_DIR/Build/iOS" +LOG="$SCRIPT_DIR/Build/build-ios.log" +SCHEME="Unity-iPhone" +DERIVED="$SCRIPT_DIR/Build/iOS-DerivedData" +APP_BUNDLE_ID="com.onesignal.example" +INSTALL=true +SKIP_BUILD=false +OPEN_XCODE=false + +for arg in "$@"; do + case "$arg" in + --no-install) INSTALL=false ;; + --install-only) SKIP_BUILD=true ;; + --open) OPEN_XCODE=true; INSTALL=false; SKIP_BUILD=true ;; + esac +done + +pick_simulator() { + LIST=$(xcrun simctl list devices booted -j \ + | python3 -c " +import json,sys +d=json.load(sys.stdin) +for r,devs in d['devices'].items(): + for dev in devs: + if dev['state']=='Booted': + print(dev['udid'] + '|' + dev['name']) +" 2>/dev/null || true) + COUNT=$(printf '%s\n' "$LIST" | grep -c . || true) + + [ "$COUNT" -eq 0 ] && echo "No booted simulators found. Boot one with: xcrun simctl boot " && exit 1 + [ "$COUNT" -eq 1 ] && SIM_UDID=$(echo "$LIST" | cut -d'|' -f1) && SIM_NAME=$(echo "$LIST" | cut -d'|' -f2) && return + + echo "Multiple simulators booted - pick one:" + i=1 + printf '%s\n' "$LIST" | while IFS='|' read -r UDID NAME; do + printf " [%d] %s (%s)\n" "$i" "$NAME" "$UDID" + i=$((i + 1)) + done + printf "Choice [1-%d]: " "$COUNT" + read -r CHOICE + LINE=$(printf '%s\n' "$LIST" | sed -n "${CHOICE}p") + [ -z "$LINE" ] && echo "Invalid choice." && exit 1 + SIM_UDID=$(echo "$LINE" | cut -d'|' -f1) + SIM_NAME=$(echo "$LINE" | cut -d'|' -f2) +} + +# Fallback Podfile generator: EDM4U's iOS resolver normally emits the Podfile +# during the Unity build from the generated per-project dependency manifest. This +# only runs if that didn't happen, so the no-location build still works offline. +ensure_podfile() { + [ -f "$XCODE_DIR/Podfile" ] && return + + DEPS="$SCRIPT_DIR/Assets/OneSignal/Editor/OneSignaliOSDependencies.xml" + [ ! -f "$DEPS" ] && return + + python3 - "$DEPS" "$XCODE_DIR/Podfile" <<'PY' +import os +import sys +import xml.etree.ElementTree as ET + +deps_path, podfile_path = sys.argv[1:3] +root = ET.parse(deps_path).getroot() +pods = [] + +for pod in root.findall("./iosPods/iosPod"): + name = pod.get("name") + version = pod.get("version") + if name and version: + pods.append((name, version)) + +if not pods: + sys.exit(0) + +onesignal_version = next( + (version for name, version in pods if name.startswith("OneSignalXCFramework")), + None, +) + +lines = [ + "source 'https://cdn.cocoapods.org/'", + "install! 'cocoapods', :disable_input_output_paths => true", + "platform :ios, '13.0'", + "use_frameworks! :linkage => :static", + "", +] + +for target in ("UnityFramework", "Unity-iPhone"): + lines.append(f"target '{target}' do") + for name, version in pods: + lines.append(f" pod '{name}', '{version}'") + lines.extend(["end", ""]) + +if onesignal_version: + lines.extend([ + "target 'OneSignalNotificationServiceExtension' do", + f" pod 'OneSignalXCFramework/OneSignalExtension', '{onesignal_version}'", + "end", + "", + ]) + +os.makedirs(os.path.dirname(podfile_path), exist_ok=True) +with open(podfile_path, "w", encoding="utf-8") as podfile: + podfile.write("\n".join(lines)) +PY +} + +SIM_UDID="" +SIM_NAME="" +[ "$INSTALL" = true ] && pick_simulator && echo "Target: $SIM_NAME ($SIM_UDID)" && echo "" + +if [ "$OPEN_XCODE" = true ]; then + WS="$XCODE_DIR/Unity-iPhone.xcworkspace" + [ ! -d "$WS" ] && echo "No workspace found. Run without --open first." && exit 1 + echo "Opening $WS..." + open "$WS" + exit 0 +fi + +if [ "$SKIP_BUILD" = true ]; then + [ ! -d "$XCODE_DIR/Unity-iPhone.xcodeproj" ] && echo "No existing build. Run without --install-only first." && exit 1 + echo "Skipping Unity build, using existing Xcode project" +else + [ ! -x "$UNITY" ] && echo "Unity not found at $UNITY - set UNITY_PATH" && exit 1 + mkdir -p "$XCODE_DIR" + echo "Generating no-location Xcode project (IL2CPP / Simulator)..." + echo "Log: $LOG" + echo "" + + START=$(date +%s) + "$UNITY" -batchmode -nographics -quit -buildTarget iOS \ + -projectPath "$SCRIPT_DIR" -executeMethod BuildScript.BuildiOSSimulator \ + -logFile "$LOG" + ELAPSED=$(( $(date +%s) - START )) + + [ ! -d "$XCODE_DIR/Unity-iPhone.xcodeproj" ] && echo "Build failed after $((ELAPSED/60))m $((ELAPSED%60))s. Check $LOG" && exit 1 + echo "Xcode project generated in $((ELAPSED/60))m $((ELAPSED%60))s" +fi + +ensure_podfile + +if [ -f "$XCODE_DIR/Podfile" ]; then + echo "Running pod install..." + (cd "$XCODE_DIR" && pod install --repo-update) +fi + +if [ "$INSTALL" = true ] && [ -n "$SIM_UDID" ]; then + echo "" + echo "Building with xcodebuild for simulator..." + WS="$XCODE_DIR/Unity-iPhone.xcworkspace" + [ ! -d "$WS" ] && WS="" + + # macOS ships openrsync as /usr/bin/rsync, which fails the CocoaPods "Copy + # XCFrameworks" phase ("renameat: No such file or directory" on the dSYM + # DWARF). Prefer a real rsync (brew install rsync) on PATH if present. + if [ -x /opt/homebrew/bin/rsync ]; then + PATH="/opt/homebrew/bin:$PATH" + export PATH + elif [ -x /usr/local/bin/rsync ]; then + PATH="/usr/local/bin:$PATH" + export PATH + else + echo "Warning: only macOS openrsync found; the XCFramework copy phase may fail." + echo " Install a real rsync with: brew install rsync" + fi + + BUILD_START=$(date +%s) + if [ -n "$WS" ]; then + xcodebuild -workspace "$WS" -scheme "$SCHEME" \ + -destination "id=$SIM_UDID" \ + -derivedDataPath "$DERIVED" \ + -quiet \ + build + else + xcodebuild -project "$XCODE_DIR/Unity-iPhone.xcodeproj" -scheme "$SCHEME" \ + -destination "id=$SIM_UDID" \ + -derivedDataPath "$DERIVED" \ + -quiet \ + build + fi + BUILD_ELAPSED=$(( $(date +%s) - BUILD_START )) + echo "xcodebuild finished in $((BUILD_ELAPSED/60))m $((BUILD_ELAPSED%60))s" + + APP_PATH=$(find "$DERIVED" -name "*.app" -path "*/Build/Products/*" | sed -n '1p') + [ -z "$APP_PATH" ] && echo "Could not find .app bundle in derived data." && exit 1 + + echo "Installing on $SIM_NAME..." + xcrun simctl install "$SIM_UDID" "$APP_PATH" + xcrun simctl launch "$SIM_UDID" "$APP_BUNDLE_ID" +fi diff --git a/examples/demo/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/com.onesignal.unity.android/Editor/OneSignalAndroidDependencies.xml b/examples/demo/Assets/OneSignal/Editor/OneSignalAndroidDependencies.xml similarity index 100% rename from com.onesignal.unity.android/Editor/OneSignalAndroidDependencies.xml rename to examples/demo/Assets/OneSignal/Editor/OneSignalAndroidDependencies.xml 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/com.onesignal.unity.ios/Editor/OneSignaliOSDependencies.xml b/examples/demo/Assets/OneSignal/Editor/OneSignaliOSDependencies.xml similarity index 100% rename from com.onesignal.unity.ios/Editor/OneSignaliOSDependencies.xml rename to examples/demo/Assets/OneSignal/Editor/OneSignaliOSDependencies.xml 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: 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)