-
Notifications
You must be signed in to change notification settings - Fork 62
chore: [SDK-4406] prepare Unity demo app for Appium E2E tests #869
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
44c3756
99a80dd
207de0d
b225f34
5d10a9a
5f59a7d
ce4aaef
976475e
44978e3
185d13d
bd65c0b
ba1e616
dd0d6de
fad8cf5
66d364e
45acb10
cbd0970
cd675ec
e166afb
90cb3b2
89178bb
f6feee1
144d88b
5db7c85
73517f2
15eac3f
0119424
24c5076
386b6de
e5f7ac8
459c708
a9aa1ad
3654d95
f3832a0
a712965
152d6da
d119746
acbfa62
5f0312e
9270923
71f3fc4
d163e13
e16974f
d6cbdc5
ec0d7df
ef04560
74a1c22
3f8bb50
f7a94f6
c204543
f8ba425
c35fb86
a213803
384badd
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,4 +1,9 @@ | ||
| -keep class com.onesignal.** { *; } | ||
|
|
||
| # Work around for IllegalStateException with kotlinx-coroutines-android | ||
| -keep class kotlinx.coroutines.android.AndroidDispatcherFactory {*;} | ||
| -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.** { *; } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1 +1,4 @@ | ||
| # Default App ID (used when ONESIGNAL_APP_ID is empty or missing): 77e32082-ea27-42e3-a898-c72e141824ef | ||
| ONESIGNAL_APP_ID=your-onesignal-app-id | ||
| ONESIGNAL_API_KEY=your_rest_api_key | ||
| E2E_MODE=false |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,154 @@ | ||
| #if UNITY_IOS | ||
|
|
||
| using System.IO; | ||
| using UnityEditor; | ||
| using UnityEditor.Build; | ||
| using UnityEditor.Build.Reporting; | ||
| using UnityEditor.iOS.Xcode; | ||
| using UnityEngine; | ||
|
|
||
| namespace App.Editor.iOS | ||
| { | ||
| /// <summary> | ||
| /// Final iOS post-processor for the demo app. Runs AFTER the OneSignal | ||
| /// SDK and demo widget post-processors so it can correct things they set: | ||
| /// | ||
| /// 1. Flips the main target's aps-environment from "production" (the SDK | ||
| /// default) to "development". The demo only ever runs on simulator or | ||
| /// a development device; "production" mismatches the simulator's APNS | ||
| /// environment and triggers iOS's "Keep receiving notifications?" | ||
| /// tuning prompt on first delivery (matches what the Flutter demo | ||
| /// ships with). | ||
| /// | ||
| /// 2. Normalizes extension bundle IDs to short suffixes (`.NSE`, `.LA`) | ||
| /// to match the Flutter demo and keep provisioning profile names | ||
| /// consistent across SDKs. | ||
| /// | ||
| /// 3. Pins DEVELOPMENT_TEAM on all targets so a future Manual signing | ||
| /// setup with the OneSignal-owned profiles works without manual | ||
| /// fix-up in Xcode. | ||
| /// </summary> | ||
| public class SigningPostProcessor : IPostprocessBuildWithReport | ||
| { | ||
| private const string AppleTeamId = "99SW8E36CT"; | ||
| private const string ApsEnvironment = "development"; | ||
|
|
||
| private const string NseTargetName = "OneSignalNotificationServiceExtension"; | ||
| private const string WidgetTargetName = "OneSignalWidget"; | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🔴 🔴 Extended reasoning...What the bug is
private const string WidgetTargetName = "OneSignalWidget";That string is the widget extension's folder/relative path ( The specific code path that triggers it
extensionGuid = project.AddAppExtension(
project.GetUnityMainTargetGuid(),
WidgetExtensionTargetName, // "OneSignalWidgetExtension"
$"{PlayerSettings.GetApplicationIdentifier(BuildTargetGroup.iOS)}.{WidgetExtensionTargetName}",
$"{WidgetExtensionTargetRelativePath}/Info.plist"
);So the PBX target is literally named
if (string.IsNullOrEmpty(guid))
{
Debug.LogWarning($"[SigningPostProcessor] Target '{targetName}' not found; skipping.");
return;
}Neither Why existing code doesn't prevent itThere is no callsite that resolves the target by file path; Step-by-step proof
ImpactCI/build-time regression introduced by this PR. The PR description explicitly lists "Normalizes extension bundle IDs to short suffixes (.NSE, .LA)" and adds FixOne-line change at private const string WidgetTargetName = "OneSignalWidgetExtension"; |
||
|
|
||
| // Short bundle-id suffixes (match the Flutter demo). | ||
| private const string NseBundleSuffix = "NSE"; | ||
| private const string WidgetBundleSuffix = "LA"; | ||
|
|
||
| // Run after both demo widget post-processor (45) and SDK | ||
| // post-processor (45). 100 puts us after pod install (50) too. | ||
| public int callbackOrder => 100; | ||
|
|
||
| public void OnPostprocessBuild(BuildReport report) | ||
| { | ||
| if (report.summary.platform != BuildTarget.iOS) | ||
| return; | ||
|
|
||
| var outputPath = report.summary.outputPath; | ||
| FixupApsEnvironment(outputPath); | ||
| FixupSigningAndBundleIds(outputPath); | ||
| } | ||
|
|
||
| private static void FixupApsEnvironment(string outputPath) | ||
| { | ||
| var project = new PBXProject(); | ||
| var projectPath = PBXProject.GetPBXProjectPath(outputPath); | ||
| project.ReadFromString(File.ReadAllText(projectPath)); | ||
|
|
||
| var mainTargetGuid = project.GetUnityMainTargetGuid(); | ||
| var relPath = project.GetBuildPropertyForAnyConfig( | ||
| mainTargetGuid, | ||
| "CODE_SIGN_ENTITLEMENTS" | ||
| ); | ||
|
|
||
| if (string.IsNullOrEmpty(relPath)) | ||
| { | ||
| Debug.LogWarning( | ||
| "[SigningPostProcessor] Main target has no CODE_SIGN_ENTITLEMENTS; " | ||
| + "skipping aps-environment fixup." | ||
| ); | ||
| return; | ||
| } | ||
|
|
||
| var fullPath = Path.Combine(outputPath, relPath); | ||
| if (!File.Exists(fullPath)) | ||
| { | ||
| Debug.LogWarning( | ||
| $"[SigningPostProcessor] Entitlements file not found at {fullPath}; skipping." | ||
| ); | ||
| return; | ||
| } | ||
|
|
||
| var plist = new PlistDocument(); | ||
| plist.ReadFromFile(fullPath); | ||
| plist.root.SetString("aps-environment", ApsEnvironment); | ||
| plist.WriteToFile(fullPath); | ||
|
|
||
| Debug.Log( | ||
| $"[SigningPostProcessor] Set aps-environment=\"{ApsEnvironment}\" in {relPath}" | ||
| ); | ||
| } | ||
|
|
||
| private static void FixupSigningAndBundleIds(string outputPath) | ||
| { | ||
| var project = new PBXProject(); | ||
| var projectPath = PBXProject.GetPBXProjectPath(outputPath); | ||
| project.ReadFromString(File.ReadAllText(projectPath)); | ||
|
|
||
| var appId = PlayerSettings.GetApplicationIdentifier(BuildTargetGroup.iOS); | ||
|
|
||
| ApplyTeamId(project, project.GetUnityMainTargetGuid(), "Unity-iPhone"); | ||
|
|
||
| ApplyExtensionFixup( | ||
| project, | ||
| NseTargetName, | ||
| $"{appId}.{NseBundleSuffix}" | ||
| ); | ||
| ApplyExtensionFixup( | ||
| project, | ||
| WidgetTargetName, | ||
| $"{appId}.{WidgetBundleSuffix}" | ||
| ); | ||
|
|
||
| File.WriteAllText(projectPath, project.WriteToString()); | ||
| } | ||
|
|
||
| private static void ApplyTeamId(PBXProject project, string targetGuid, string label) | ||
| { | ||
| if (string.IsNullOrEmpty(targetGuid)) | ||
| return; | ||
|
|
||
| project.SetBuildProperty(targetGuid, "DEVELOPMENT_TEAM", AppleTeamId); | ||
| Debug.Log($"[SigningPostProcessor] Pinned DEVELOPMENT_TEAM={AppleTeamId} on {label}"); | ||
| } | ||
|
|
||
| private static void ApplyExtensionFixup( | ||
| PBXProject project, | ||
| string targetName, | ||
| string bundleId | ||
| ) | ||
| { | ||
| var guid = project.TargetGuidByName(targetName); | ||
| if (string.IsNullOrEmpty(guid)) | ||
| { | ||
| Debug.LogWarning( | ||
| $"[SigningPostProcessor] Target '{targetName}' not found; skipping." | ||
| ); | ||
| return; | ||
| } | ||
|
|
||
| project.SetBuildProperty(guid, "PRODUCT_BUNDLE_IDENTIFIER", bundleId); | ||
| ApplyTeamId(project, guid, targetName); | ||
| Debug.Log( | ||
| $"[SigningPostProcessor] Set {targetName} PRODUCT_BUNDLE_IDENTIFIER={bundleId}" | ||
| ); | ||
| } | ||
| } | ||
| } | ||
|
|
||
| #endif | ||
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,4 +1,9 @@ | ||
| -keep class com.onesignal.** { *; } | ||
|
|
||
| # Work around for IllegalStateException with kotlinx-coroutines-android | ||
| -keep class kotlinx.coroutines.android.AndroidDispatcherFactory {*;} | ||
| -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.** { *; } |
Uh oh!
There was an error while loading. Please reload this page.