From 89609dea585329b65eebc40e9c572384a77bef9b Mon Sep 17 00:00:00 2001 From: yuqucheng <> Date: Mon, 6 Jul 2026 16:49:18 +0800 Subject: [PATCH] =?UTF-8?q?fix(iOS):=20=E4=BF=AE=E5=A4=8DiOS=2014+?= =?UTF-8?q?=E8=8E=B7=E5=8F=96WiFi=E5=90=8D=E7=A7=B0=E7=9A=84=E6=9D=83?= =?UTF-8?q?=E9=99=90=E4=B8=8E=E9=80=82=E9=85=8D=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 1. 添加位置权限请求逻辑适配iOS 14+ NEHotspotNetwork要求 2. 新增NetworkExtension框架依赖并更新Xcode项目配置 3. 修复构建脚本中的日志标识与应用名大小写问题 4. 更新启动图标配置与iOS项目设置 5. 优化WiFi SSID获取的兼容逻辑与日志输出 --- Assets/Editor/iOSFixDuplicateShellScript.cs | 39 +++++--- Assets/Plugins/iOS/WiFiHelper.mm | 94 ++++++++++++++++--- .../UI/Pages/DeviceInfoPage/SetWifiPage.cs | 8 +- ProjectSettings/ProjectSettings.asset | 56 +++++------ 4 files changed, 143 insertions(+), 54 deletions(-) diff --git a/Assets/Editor/iOSFixDuplicateShellScript.cs b/Assets/Editor/iOSFixDuplicateShellScript.cs index ae3f5b2..01a4fcb 100644 --- a/Assets/Editor/iOSFixDuplicateShellScript.cs +++ b/Assets/Editor/iOSFixDuplicateShellScript.cs @@ -1,6 +1,6 @@ -#if UNITY_IOS using UnityEditor; using UnityEditor.Callbacks; +using UnityEditor.iOS.Xcode; using System.IO; using System.Text.RegularExpressions; using UnityEngine; @@ -14,6 +14,7 @@ public class iOSFixDuplicateShellScript FixDuplicateShellScript(pathToBuiltProject); FixPodfile(pathToBuiltProject); + AddNetworkExtensionFramework(pathToBuiltProject); } private static void FixDuplicateShellScript(string pathToBuiltProject) @@ -21,7 +22,7 @@ public class iOSFixDuplicateShellScript string projPath = Path.Combine(pathToBuiltProject, "Unity-iPhone.xcodeproj/project.pbxproj"); if (!File.Exists(projPath)) { - Debug.LogWarning("[FixDupShellScript] pbxproj not found: " + projPath); + Debug.LogWarning("[PostProcess] pbxproj not found: " + projPath); return; } @@ -33,12 +34,13 @@ public class iOSFixDuplicateShellScript if (newContent != content) { File.WriteAllText(projPath, newContent); - Debug.Log("[FixDupShellScript] Removed duplicate ShellScript from GameAssembly target"); - } - else - { - Debug.Log("[FixDupShellScript] No duplicate ShellScript found"); + Debug.Log("[PostProcess] Removed duplicate ShellScript from GameAssembly target"); } + + // 修复光子矩阵 app 大小写 + newContent = newContent.Replace("photonmatrix.app", "PhotonMatrix.app"); + + File.WriteAllText(projPath, newContent); } private static void FixPodfile(string pathToBuiltProject) @@ -46,21 +48,19 @@ public class iOSFixDuplicateShellScript string podfilePath = Path.Combine(pathToBuiltProject, "Podfile"); if (!File.Exists(podfilePath)) { - Debug.LogWarning("[FixPodfile] Podfile not found"); + Debug.LogWarning("[PostProcess] Podfile not found"); return; } string content = File.ReadAllText(podfilePath); bool modified = false; - // 移除不需要的 Firebase/Analytics if (content.Contains("Firebase/Analytics")) { content = Regex.Replace(content, @"\s*pod\s+'Firebase/Analytics'[^\n]*\n?", "\n"); modified = true; } - // 将 12.4.0 统一为 12.14.0 if (content.Contains("12.4.0")) { content = content.Replace("12.4.0", "12.14.0"); @@ -70,12 +70,23 @@ public class iOSFixDuplicateShellScript if (modified) { File.WriteAllText(podfilePath, content); - Debug.Log("[FixPodfile] Cleaned up Podfile"); + Debug.Log("[PostProcess] Cleaned up Podfile"); } - else + } + + private static void AddNetworkExtensionFramework(string pathToBuiltProject) + { + string projPath = PBXProject.GetPBXProjectPath(pathToBuiltProject); + PBXProject proj = new PBXProject(); + proj.ReadFromString(File.ReadAllText(projPath)); + + string unityFrameworkGuid = proj.GetUnityFrameworkTargetGuid(); + bool added = proj.AddFrameworkToProject(unityFrameworkGuid, "NetworkExtension.framework", false); + + if (added) { - Debug.Log("[FixPodfile] Podfile already clean"); + File.WriteAllText(projPath, proj.WriteToString()); + Debug.Log("[PostProcess] Added NetworkExtension.framework"); } } } -#endif diff --git a/Assets/Plugins/iOS/WiFiHelper.mm b/Assets/Plugins/iOS/WiFiHelper.mm index 99cc2bc..fb32c82 100644 --- a/Assets/Plugins/iOS/WiFiHelper.mm +++ b/Assets/Plugins/iOS/WiFiHelper.mm @@ -1,28 +1,100 @@ #import #import +#import +#import + +static CLLocationManager *locationManager = nil; extern "C" { + void RequestLocationPermission() { + if (locationManager != nil) return; + + locationManager = [[CLLocationManager alloc] init]; + + CLAuthorizationStatus status = [CLLocationManager authorizationStatus]; + if (status == kCLAuthorizationStatusAuthorizedWhenInUse || + status == kCLAuthorizationStatusAuthorizedAlways) { + NSLog(@"[WiFiHelper] Location permission already granted (status: %d)", (int)status); + // 位置权限已获得但还需要启动定位才能让WiFi API工作 + [locationManager startUpdatingLocation]; + // 短暂启动后停止(不需要持续定位,只是激活权限链) + dispatch_after(dispatch_time(DISPATCH_TIME_NOW, 0.5 * NSEC_PER_SEC), dispatch_get_main_queue(), ^{ + [locationManager stopUpdatingLocation]; + }); + return; + } + + if (status == kCLAuthorizationStatusNotDetermined) { + NSLog(@"[WiFiHelper] Requesting WhenInUse location permission"); + [locationManager requestWhenInUseAuthorization]; + } else { + NSLog(@"[WiFiHelper] Location permission denied/restricted (status: %d)", (int)status); + } + } + const char* GetWiFiSSID() { - NSString *ssid = nil; + // 确保位置已启动至少一次(NEHotspotNetwork 的隐式要求) + if (locationManager != nil && [CLLocationManager authorizationStatus] == kCLAuthorizationStatusAuthorizedWhenInUse) { + [locationManager startUpdatingLocation]; + } - NSArray *interfaces = (__bridge_transfer NSArray *)CNCopySupportedInterfaces(); + __block NSString *resultSSID = nil; + __block BOOL finished = NO; - for (NSString *interfaceName in interfaces) { - NSDictionary *info = (__bridge_transfer NSDictionary *)CNCopyCurrentNetworkInfo((__bridge CFStringRef)interfaceName); + if (@available(iOS 14.0, *)) { + NSLog(@"[WiFiHelper] Using NEHotspotNetwork.fetchCurrent"); - if (info && info[@"SSID"]) { - ssid = info[@"SSID"]; - break; + [NEHotspotNetwork fetchCurrentWithCompletionHandler:^(NEHotspotNetwork * _Nullable network) { + if (network && network.SSID.length > 0) { + resultSSID = network.SSID; + } + finished = YES; + }]; + + // 用 CFRunLoop 等待,不阻塞主线程事件处理 + NSTimeInterval deadline = [[NSDate date] timeIntervalSinceReferenceDate] + 3.0; + while (!finished && [[NSDate date] timeIntervalSinceReferenceDate] < deadline) { + [[NSRunLoop currentRunLoop] runMode:NSDefaultRunLoopMode beforeDate:[NSDate dateWithTimeIntervalSinceNow:0.01]]; + } + + if (resultSSID != nil) { + NSLog(@"[WiFiHelper] NEHotspotNetwork SSID: %@", resultSSID); + } else { + NSLog(@"[WiFiHelper] NEHotspotNetwork returned nil (finished=%d)", finished); } } - if (ssid == nil) { + // Fallback + if (resultSSID == nil) { + NSLog(@"[WiFiHelper] Fallback to CNCopyCurrentNetworkInfo"); + NSArray *interfaces = (__bridge_transfer NSArray *)CNCopySupportedInterfaces(); + if (interfaces != nil) { + for (NSString *interfaceName in interfaces) { + NSDictionary *info = (__bridge_transfer NSDictionary *)CNCopyCurrentNetworkInfo((__bridge CFStringRef)interfaceName); + if (info && info[(NSString *)kCNNetworkInfoKeySSID]) { + resultSSID = info[(NSString *)kCNNetworkInfoKeySSID]; + break; + } + } + } + } + + if (locationManager != nil) { + [locationManager stopUpdatingLocation]; + } + + if (resultSSID == nil) { + NSLog(@"[WiFiHelper] No WiFi SSID found."); return NULL; } - const char *utf8String = [ssid UTF8String]; - char *result = (char *)malloc(strlen(utf8String) + 1); - strcpy(result, utf8String); + NSLog(@"[WiFiHelper] SSID: %@", resultSSID); + + const char *utf8String = [resultSSID UTF8String]; + size_t len = strlen(utf8String) + 1; + char *result = (char *)malloc(len); + if (result == NULL) return NULL; + memcpy(result, utf8String, len); return result; } diff --git a/Assets/Scripts/UI/Pages/DeviceInfoPage/SetWifiPage.cs b/Assets/Scripts/UI/Pages/DeviceInfoPage/SetWifiPage.cs index e9604d6..488c0c1 100644 --- a/Assets/Scripts/UI/Pages/DeviceInfoPage/SetWifiPage.cs +++ b/Assets/Scripts/UI/Pages/DeviceInfoPage/SetWifiPage.cs @@ -150,13 +150,19 @@ namespace Kill.UI.Pages [System.Runtime.InteropServices.DllImport("__Internal")] private static extern System.IntPtr GetWiFiSSID(); + [System.Runtime.InteropServices.DllImport("__Internal")] + private static extern void RequestLocationPermission(); + /// - /// iOS 获取 WiFi 名称 + /// iOS 获取 WiFi 名称(先请求位置权限) /// private string GetWiFiNameIOS() { try { + // iOS 14+ NEHotspotNetwork 需要位置权限 + RequestLocationPermission(); + System.IntPtr ptr = GetWiFiSSID(); if (ptr == System.IntPtr.Zero) { diff --git a/ProjectSettings/ProjectSettings.asset b/ProjectSettings/ProjectSettings.asset index 5d2522f..0b6908a 100644 --- a/ProjectSettings/ProjectSettings.asset +++ b/ProjectSettings/ProjectSettings.asset @@ -414,34 +414,7 @@ PlayerSettings: m_Kind: 4 m_SubKind: App Store - m_Textures: - - {fileID: 2800000, guid: 72592ba5df3304ad8a664eb6c0ab04da, type: 3} - m_Width: 180 - m_Height: 180 - m_Kind: 0 - m_SubKind: iPhone - - m_Textures: - - {fileID: 2800000, guid: d89f75d2829914aefabc2c12ee61e74d, type: 3} - 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: - - {fileID: 2800000, guid: d89f75d2829914aefabc2c12ee61e74d, type: 3} + - {fileID: 0} m_Width: 120 m_Height: 120 m_Kind: 3 @@ -514,6 +487,33 @@ PlayerSettings: m_Height: 20 m_Kind: 2 m_SubKind: iPad + - m_Textures: + - {fileID: 2800000, guid: 29fdb52e7fc6c411891c323b5d5b6f01, type: 3} + m_Width: 180 + m_Height: 180 + m_Kind: 0 + m_SubKind: iPhone + - m_Textures: + - {fileID: 2800000, guid: 2fe29f66f37c34d5ca39cf642d8a2ba3, type: 3} + 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_BuildTargetBatching: [] m_BuildTargetShaderSettings: [] m_BuildTargetGraphicsJobs: []