Post

Unity iOS TestFlight Upload Error Fix - Asset validation failed (90206) Invalid Bundle

Unity iOS TestFlight Upload Error Fix - Asset validation failed (90206) Invalid Bundle
Visitors

Error Analysis

  • When attempting to upload to TestFlight using Transporter, the following error occurred:
1
2
Asset validation failed (90206)
Invalid Bundle. The bundle at 'TOYVERSE.app/Frameworks/UnityFramework.framework' contains disallowed file 'Frameworks'.(ID: 54a900bb-b251-492a-bed7-ee556a02d857)

Desktop View

  • Traces of disaster…

Desktop View



Solution

  • Checked StackOverflow thread
  • Go to the xcworkspace of the Xcode project built from Unity.
  • Search for embed in Build Settings for both Unity-iPhone app and UnityFramework.
  • You will see Always Embed Swift Standard Libraries. If this is set to Yes, the upload is highly likely to fail.

Desktop View

Desktop View


  • Therefore, disable these two in the Unity build script PostProcessBuild via post-processing.
1
2
3
4
5
6
7
8
9
10
11
...
foreach (var targetGuid in new[] { mainTargetGuid, project.GetUnityFrameworkTargetGuid() })
{
  project.SetBuildProperty(targetGuid, "ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES", "No");

  project.SetBuildProperty(targetGuid, "LD_RUNPATH_SEARCH_PATHS", "$(inherited) /usr/lib/swift @executable_path/Frameworks");
  //project.AddBuildProperty(targetGuid, "LD_RUNPATH_SEARCH_PATHS", "/usr/lib/swift");
}

project.SetBuildProperty(mainTargetGuid, "ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES", "No");
...


  • Build again and upload, and it succeeds!

Desktop View



Full Build Post-processing Code
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
class PBR : IPostprocessBuildWithReport
{
    public int callbackOrder { get { return 0; } }
    
    public void OnPostprocessBuild(BuildReport report)
    {
        if (report.summary.platform == BuildTarget.iOS)
        {
            Debug.Log("OnPostProceeBuild");
            string projectPath = report.summary.outputPath + "/Unity-iPhone.xcodeproj/project.pbxproj";
            var entitlementFilePath = "Entitlements.entitlements";
            var project = new PBXProject();

            project.ReadFromFile(projectPath);
            
            var manager = new ProjectCapabilityManager(projectPath, entitlementFilePath, null, project.GetUnityMainTargetGuid());
            manager.AddPushNotifications(true);
            manager.AddAssociatedDomains(new string[] { "applinks:nkmb.adj.st" });// Universal-Link Support.
            manager.WriteToFile();

            var mainTargetGuid = project.GetUnityMainTargetGuid();
            project.SetBuildProperty(mainTargetGuid, "ENABLE_BITCODE", "NO");
            
            // Code temporarily added only for Enterprise.
            // Xcode build error occurs because Sign In With Apple Framework is not activated in Enterprise
            
            // Code to exclude iPad support in Supported Destinations
            // 1 means iPhone.
            //project.SetBuildProperty(mainTargetGuid, "TARGETED_DEVICE_FAMILY", "1"); // 1 corresponds to iPhone

            project.RemoveFrameworkFromProject(mainTargetGuid, "SIGN_IN_WITH_APPLE");
            project.SetBuildProperty(mainTargetGuid, "CODE_SIGN_ENTITLEMENTS", entitlementFilePath);
            project.AddFrameworkToProject(mainTargetGuid, "UserNotifications.framework", false);

            foreach (var targetGuid in new[] { mainTargetGuid, project.GetUnityFrameworkTargetGuid() })
            {
                project.SetBuildProperty(targetGuid, "ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES", "No");

                project.SetBuildProperty(targetGuid, "LD_RUNPATH_SEARCH_PATHS", "$(inherited) /usr/lib/swift @executable_path/Frameworks");
                //project.AddBuildProperty(targetGuid, "LD_RUNPATH_SEARCH_PATHS", "/usr/lib/swift");
            }

            project.SetBuildProperty(mainTargetGuid, "ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES", "No");

#if DEV
            // // instrument test
            // // Enable 'get-task-allow' for Debug configuration
            // project.SetBuildProperty(target, "GCC_GENERATE_DEBUGGING_SYMBOLS", "YES");
            // project.SetBuildProperty(target, "ENABLE_TESTABILITY", "YES");
            //
            // project.WriteToFile(projectPath);
            //
            // // Fix the 'get-task-allow' error by enabling debugging in the entitlements file
            // string entitlementsContents = System.IO.File.ReadAllText("/Users/YOUR_USERNAME/Xcode_dev/Entitlements.entitlements");
            //
            // // Make sure the debugging entitlement is present
            // if (!entitlementsContents.Contains("<key>get-task-allow</key>"))
            // {
            //     // Add the entitlement for debugging
            //     entitlementsContents = entitlementsContents.Replace("</dict>", "<key>get-task-allow</key><true/></dict>");
            //     System.IO.File.WriteAllText("/Users/YOUR_USERNAME/Xcode_dev/Entitlements.entitlements", entitlementsContents);
            // }
#endif
        }
    }
}

 [PostProcessBuild(callbackOrder:999)]
    public static void OnPostprocessBuild(BuildTarget target, string pathToBuiltProject)
    {
#if UNITY_IPHONE
        if (target == BuildTarget.iOS)
        {
            var projectPath = PBXProject.GetPBXProjectPath(pathToBuiltProject);
            var project = new PBXProject();
            Debug.Log($"Post Process Build callback : {projectPath}");
            project.ReadFromString(File.ReadAllText(projectPath));

            // UnityFramework separation support since Unity 2019.3
            project.AddFrameworkToProject(project.GetUnityMainTargetGuid(), "UnityFramework.framework", false);

            // iOS 14 support
            var frameworkTarget = project.GetUnityFrameworkTargetGuid();
            project.AddFrameworkToProject(frameworkTarget, "AppTrackingTransparency.framework", true);
            project.AddFrameworkToProject(frameworkTarget, "AdSupport.framework", true);

            string infoPlistPath = pathToBuiltProject + "/Info.plist";
            PlistDocument plistDoc = new PlistDocument();
            plistDoc.ReadFromFile(infoPlistPath);
            if (plistDoc.root != null)
            {
                plistDoc.root.SetBoolean("ITSAppUsesNonExemptEncryption", false);


                var locale = new string[] { "en", "ja" };
                var mainTargetGuid = project.GetUnityMainTargetGuid();
                var array = plistDoc.root.CreateArray("CFBundleLocalizations");
                foreach (var localization in locale)
                {
                    array.AddString(localization);
                }

                plistDoc.root.SetString("NSUserTrackingUsageDescription", "Please allow permission to provide service and personalized marketing. It will be used only for the purpose of providing personalized advertising based on Apple's policy.");

                // var entry = LocalizationSettings.StringDatabase.GetTableEntryAsync("LocalizeTable", "LZ_SRT_038");
                // if (entry.IsDone)
                // {
                //     var comment = entry.Result.Entry.GetMetadata<Comment>();
                //     var sharedEntry = entry.Result.Table.SharedData.GetEntry("LZ_SRT_038");
                //     var sharedComment = sharedEntry.Metadata.GetMetadata<Comment>();
                //     plistDoc.root.SetString("NSUserTrackingUsageDescription", sharedComment.CommentText);
                // }

                //plistDoc.root.SetString("NSUserTrackingUsageDescription", sharedComment);

                plistDoc.WriteToFile(projectPath);

                for (int i = 0; i < locale.Length; i++)
                {
                    var guid = project.AddFolderReference(Application.dataPath + string.Format("/Editor/iOS/Localization/{0}.lproj", locale[i]), string.Format("{0}.lproj", locale[i]), PBXSourceTree.Source);
                    project.AddFileToBuild(mainTargetGuid, guid);
                }
                // Set to Japanese
                //plistDoc.root.SetString("CFBundleDevelopmentRegion", "en");

                // For displaying iOS 14 AppTracking popup
                //var attMessage = StringManager.GetLZString("LZ_SRT_038") ?? "Localize is null";

                //var attMessage = "Please allow permission to provide service and personalized marketing. It will be used only for the purpose of providing personalized advertising based on Apple's policy.";
                //var attMessage = "att tracking test";
                //var attMessage = "If permitted, the information collected from you in this service will be used to improve the quality of the app." +
                //    "\nPlease configure tracking settings for future service improvement." +
                //    "\n*Tracking settings can be changed at any time from your device settings.";
                //var info = new UnityEngine.Localization.Platform.iOS.AppInfo();
                //UnityEngine.Localization.Platform.iOS.AppInfo appInfo = info;
                //var attMessage = info.UserTrackingUsageDescription.ToString();
                //plistDoc.root.SetString("NSUserTrackingUsageDescription", attMessage);



                // Background mode configuration required for Firebase
                PlistElementArray backgroundModes;
                if (plistDoc.root.values.ContainsKey("UIBackgroundModes"))
                {
                    backgroundModes = plistDoc.root["UIBackgroundModes"].AsArray();
                }
                else
                {
                    backgroundModes = plistDoc.root.CreateArray("UIBackgroundModes");
                }
                backgroundModes.AddString("remote-notification");
                plistDoc.WriteToFile(infoPlistPath);
            }
            else
            {
                Debug.LogError("ERROR: Can't open " + infoPlistPath);
            }
            project.WriteToFile(projectPath);
        }
#endif
    }

This post is licensed under CC BY 4.0 by the author.