// // YL_NetWorkManager.swift // wallpaper_project // Created by 忆海16 on 2024/9/29. // import Foundation import UIKit import AdSupport import CoreTelephony import Network import SystemConfiguration import AVFoundation import OpenGLES import AppTrackingTransparency import CommonCrypto /// <#Description#> class YL_NetWorkManager{ static var kBaseUrl = YL_NetWorkManager.bFaceLocalUrl() static var kURL_AD_Start = "/top_selection/save_app_start_log" static var kURL_AD_Load = "/top_selection/save_ad_load_log" static var kURL_AD_Show = "/top_selection/save_ad_show_log" static var kURL_save_logs = "/ios/top_selection/save_iphone_logs" var ipLoadTime: DispatchTime? static var kLocalBaseUrl = BbbAdManager.config.adbrush_local_url static var kLocalUrlStr: (String) -> String { return { path in return "\(self.kLocalBaseUrl)/\(path)" } } static func bFaceLocalUrl() -> String { return BbbAdManager.config.adbrush_base_url } typealias LuxNetManagerCallback = (Error?, Bool, [String: Any]?) -> Void static func uploadData(mdic: [String: Any], urlPath: String, callback: @escaping (Error?, Bool, [String: Any]?) -> Void) { guard let url = URL(string: urlPath) else { print("Invalid URL") return } print("---------mdic \(mdic)") print("---------urlPath\(urlPath)") var request = URLRequest(url: url) request.httpMethod = "POST" request.setValue("application/json", forHTTPHeaderField: "Content-Type") do { let data = try JSONSerialization.data(withJSONObject: mdic, options: []) request.httpBody = data } catch { print("Error serializing JSON: \(error.localizedDescription)") DispatchQueue.main.async { NotificationCenter.default.post(name: NSNotification.Name("adinfo"), object: nil, userInfo: [ "text":"Error serializing JSON: \(error.localizedDescription)" ]) } return } let task = URLSession.shared.dataTask(with: request) { (data, response, error) in if let error = error { callback(error, false, nil) print("Network error: \(error.localizedDescription)") DispatchQueue.main.async { NotificationCenter.default.post(name: NSNotification.Name("adinfo"), object: nil, userInfo: [ "text":"Network error: \(error.localizedDescription)" ]) } } else { guard let data = data else { callback(nil, false, nil) print("No data received") DispatchQueue.main.async { NotificationCenter.default.post(name: NSNotification.Name("adinfo"), object: nil, userInfo: [ "text":"No data received" ]) } return } do { if let result = try JSONSerialization.jsonObject(with: data, options: []) as? [String: Any] { print("Server response: \(result)") callback(nil, true, result) DispatchQueue.main.async { NotificationCenter.default.post(name: NSNotification.Name("adinfo"), object: nil, userInfo: [ "text":"Server response: \(result)" ]) } } } catch { callback(error, false, nil) DispatchQueue.main.async { NotificationCenter.default.post(name: NSNotification.Name("adinfo"), object: nil, userInfo: [ "text":"Error parsing response JSON: \(error.localizedDescription)" ]) } print("Error parsing response JSON: \(error.localizedDescription)") } } } task.resume() } // 请求远程IP func requestRemoteIp() { ipLoadTime = DispatchTime.now() NotificationCenter.default.post(name: NSNotification.Name("adinfo"), object: nil, userInfo: ["text": "获取ip中..."]) guard let url = URL(string: "https://openapi.lux-ad.com/app/common/getIPInfo") else { return } let request = URLRequest(url: url) let task = URLSession.shared.dataTask(with: request) { data, response, error in if let error = error { print("解析ip失败....") DispatchQueue.main.async { NotificationCenter.default.post(name: NSNotification.Name("adinfo"), object: nil, userInfo: ["text": "解析ip失败...."]) } return } guard let data = data, let result = try? JSONSerialization.jsonObject(with: data, options: []) as? [String: Any], let ip = result["data"] as? [String: Any], let ipAddress = ip["ip"] as? String, let isoCode = ip["isoCode"] as? String else { print("解析ip失败....") DispatchQueue.main.async { NotificationCenter.default.post(name: NSNotification.Name("adinfo"), object: nil, userInfo: ["text": "解析ip失败...."]) } return } if !ipAddress.isEmpty { UserDefaults.standard.set(ipAddress, forKey: "kIP_key") UserDefaults.standard.set(isoCode, forKey: "kIP_key_isoCode") UserDefaults.standard.synchronize() DispatchQueue.main.async { NotificationCenter.default.post(name: NSNotification.Name("adinfo"), object: nil, userInfo: ["text": "当前ip: \(ipAddress) \n国家: \(isoCode) "]) } if let startTime = self.ipLoadTime { let loadDuration = self.IpcalculateElapsedTime(since: startTime) BbbAdManager.config.ipTime = loadDuration } } else { print("解析ip失败....") DispatchQueue.main.async { NotificationCenter.default.post(name: NSNotification.Name("adinfo"), object: nil, userInfo: ["text": "解析ip失败...."]) } } } task.resume() } // 辅助函数以毫秒为单位计算经过的时间 private func IpcalculateElapsedTime(since startTime: DispatchTime) -> Int { let endTime = DispatchTime.now() let nanoseconds = endTime.uptimeNanoseconds - startTime.uptimeNanoseconds return Int(nanoseconds / 1_000_000) // 转换为毫秒 } // DeviceId static func getDeviceId() -> String { var adbrushDeviceId = UserDefaults.standard.dictionary(forKey: "bfaceDictKey")?["adbrush_deviceid"] as? String if adbrushDeviceId == nil { adbrushDeviceId = UIDevice.current.identifierForVendor?.uuidString var bfaceDict = UserDefaults.standard.dictionary(forKey: "bfaceDictKey") ?? [:] bfaceDict["adbrush_deviceid"] = adbrushDeviceId UserDefaults.standard.set(bfaceDict, forKey: "bfaceDictKey") UserDefaults.standard.synchronize() } return adbrushDeviceId ?? "" } // 本地IP static func getLocalIp() -> String { var address = "an error occurred when obtaining ip address" var interfaces: UnsafeMutablePointer? = nil if getifaddrs(&interfaces) == 0 { var tempAddr = interfaces while tempAddr != nil { let addrFamily = tempAddr!.pointee.ifa_addr.pointee.sa_family let name = String(cString: tempAddr!.pointee.ifa_name) if addrFamily == AF_INET && name == "en0" { var ipAddress = sockaddr_in() memcpy(&ipAddress, tempAddr!.pointee.ifa_addr, MemoryLayout.size) address = String(cString: inet_ntoa(ipAddress.sin_addr)) } tempAddr = tempAddr!.pointee.ifa_next } freeifaddrs(interfaces) } return address } // 包名 static func getPackageName() -> String { return Bundle.main.bundleIdentifier ?? "" } // 版本 static func getappVersion() -> String { return Bundle.main.infoDictionary?["CFBundleShortVersionString"] as? String ?? "" } // 手机型号 static func getiphone() -> String { return UIDevice.current.localizedModel } // 系统版本 static func getosVersion() -> String { return UIDevice.current.systemVersion } // 电池电量 static func getBatteryLevel() -> Float? { return UIDevice.current.batteryLevel } // 是否在充电 static func isDeviceCharging() -> Bool { return UIDevice.current.batteryState == .charging || UIDevice.current.batteryState == .full } // 获取deviceId static func getPhoneDeviceId() -> String? { return UIDevice.current.identifierForVendor?.uuidString } // 当前的无线接入技术 static func getCurrentRadioAccessTechnology() -> String? { let networkInfo = CTTelephonyNetworkInfo() let radioAccessTechnology = networkInfo.currentRadioAccessTechnology return radioAccessTechnology } // 时间 static func getCurrentTime() -> String { let date = Date() // 获取当前日期和时间 let formatter = DateFormatter() formatter.dateFormat = "yyyy-MM-dd'T'HH:mm:ss" // 设置日期格式 formatter.locale = Locale(identifier: "en_US_POSIX") // 确保使用 ISO 8601 标准 return formatter.string(from: date) } // 字体 static func getCurrentFont() -> String { return "\(UIFont.systemFont(ofSize: UIFont.systemFontSize))" } // 语言 static func getlanguageCode() -> String { return Locale.current.languageCode ?? "" } //GAID static func getGaid() -> String { return ASIdentifierManager.shared().advertisingIdentifier.uuidString } // IDFA static func getIdfa() -> String { if ASIdentifierManager.shared().isAdvertisingTrackingEnabled { let idfa = ASIdentifierManager.shared().advertisingIdentifier.uuidString return idfa } else { return "" } } // monotonicRawClockTimeMillis 单调时钟时间戳 static func getMonotonicRawClockTimeMillis() -> UInt64 { let time = mach_absolute_time() let nanoseconds = Double(time) / Double(NSEC_PER_SEC) // Convert to nanoseconds return UInt64(nanoseconds / 1000000) // Convert to milliseconds } // 内核启动时间戳 static func getKernelBootTimeMillis() -> Int64? { // 定义变量以存储系统启动时间 var bootTime = timeval() var size = MemoryLayout.stride // 获取系统启动时间 let mib: [Int32] = [CTL_KERN, KERN_BOOTTIME] let result = sysctl(UnsafeMutablePointer(mutating: mib), 2, &bootTime, &size, nil, 0) guard result == 0 else { print("获取系统启动时间失败") return nil } // 系统启动时间(秒 + 微秒) let bootTimeInSeconds = Double(bootTime.tv_sec) + Double(bootTime.tv_usec) / 1_000_000 // 当前时间 let currentTime = Date().timeIntervalSince1970 // 计算内核运行的时间(秒) let kernelBootTimeInSeconds = currentTime - bootTimeInSeconds // 转换为毫秒 return Int64(kernelBootTimeInSeconds * 1_000) } // 获取运营商信息 static func getCarrierInfo() -> String { var carrierInfo = "" let networkInfo = CTTelephonyNetworkInfo() let carrier = networkInfo.serviceSubscriberCellularProviders?.first?.value if let carrier = carrier { carrierInfo = "\(carrier.mobileCountryCode ?? "") \(carrier.mobileNetworkCode ?? "")" } return carrierInfo } // 获取网络连接类型 static func getNetworkType() -> String { let monitor = NWPathMonitor() let queue = DispatchQueue.global(qos: .background) var type:String = "" monitor.pathUpdateHandler = { path in if path.status == .satisfied { if path.usesInterfaceType(.wifi) { type = "Wi-Fi" } else if path.usesInterfaceType(.cellular) { type = "Cellular" } else if path.usesInterfaceType(.wiredEthernet) { type = "Wired Ethernet" } else if path.usesInterfaceType(.loopback) { type = "Loopback" } else { type = "Other" } } else { type = "Unavailable" } monitor.cancel() // 停止监控,释放资源 } monitor.start(queue: queue) return type } // 是否连接VPN static func isVPNOn() -> Bool { var flag = false let version = UIDevice.current.systemVersion // Check if the system version is >= 9.0 if let versionDouble = Double(version), versionDouble >= 9.0 { // For iOS 9.0 and above if let dict = CFNetworkCopySystemProxySettings() as? Unmanaged { let bridgedDict = dict.takeUnretainedValue() as? [String: Any] if let scopedSettings = bridgedDict?["__SCOPED__"] as? [String: Any] { for key in scopedSettings.keys { if key.contains("tap") || key.contains("tun") || key.contains("ipsec") || key.contains("ppp") { flag = true break } } } } } else { // For iOS versions below 9.0 var interfaces: UnsafeMutablePointer? let success = getifaddrs(&interfaces) if success == 0 { var tempAddr = interfaces while tempAddr != nil { if let name = String(validatingUTF8: (tempAddr?.pointee.ifa_name)!) { if name.contains("tap") || name.contains("tun") || name.contains("ipsec") || name.contains("ppp") { flag = true break } } tempAddr = tempAddr?.pointee.ifa_next } } // Free memory freeifaddrs(interfaces) } return flag } static func appId() -> String { return Bundle.main.bundleIdentifier ?? "" } // 获取音量 static func isDeviceMuted() -> Bool { let audioSession = AVAudioSession.sharedInstance() do { try audioSession.setActive(true) // 获取当前音量 let currentVolume = audioSession.outputVolume return currentVolume == 0 } catch { print("Error setting audio session active: \(error.localizedDescription)") return false } } // 追踪状态 static func getAdvertisingTrackingStatus() -> String { if #available(iOS 14, *) { switch ATTrackingManager.trackingAuthorizationStatus { case .notDetermined: return "notDetermined" case .restricted: return "restricted" case .denied: return "denied" case .authorized: return "authorized" @unknown default: return "unknown" } } else { // iOS 14 以下版本 let isTrackingEnabled = ASIdentifierManager.shared().isAdvertisingTrackingEnabled return isTrackingEnabled ? "authorized" : "denied" } } // 是否启用追踪 static func isAdvertisingTrackingEnabled() -> Bool { if #available(iOS 14, *) { switch ATTrackingManager.trackingAuthorizationStatus { case .authorized: return true // 用户允许广告追踪 default: return false // 用户未授权、受限制或拒绝 } } else { // iOS 14 以下版本 return ASIdentifierManager.shared().isAdvertisingTrackingEnabled } } // 获取设备总内存 static func getTotalMemoryInBytes() -> UInt64 { return ProcessInfo.processInfo.physicalMemory } static func getTotalMemoryInReadableFormat() -> String { let totalMemoryBytes = getTotalMemoryInBytes() let formatter = ByteCountFormatter() formatter.allowedUnits = [.useGB] // 只显示为 GB formatter.countStyle = .memory return formatter.string(fromByteCount: Int64(totalMemoryBytes)) } // 是否是刘海屏 static func isNotchScreen() -> Bool { // 确保在主线程中访问 if Thread.isMainThread { guard let window = UIApplication.shared.windows.first else { return false } let topSafeArea = window.safeAreaInsets.top return topSafeArea > 20 } else { // 在非主线程中调用时,通过调度回主线程同步获取结果 return DispatchQueue.main.sync { guard let window = UIApplication.shared.windows.first else { return false } let topSafeArea = window.safeAreaInsets.top return topSafeArea > 20 } } } // 屏幕方向 static func getScreenOrientation() -> String { let orientation = UIDevice.current.orientation switch orientation { case .portrait: return "portrait" case .portraitUpsideDown: return "portraitUpsideDown" case .landscapeLeft: return "landscapeLeft" case .landscapeRight: return "landscapeRight" case .faceUp: return "faceUp" case .faceDown: return "faceDown" case .unknown: return "unknown" @unknown default: return "unknown" } } // 获取 OpenGL版本 static func getOpenGLVersion() -> String { // 尝试初始化 OpenGL ES 3.0 上下文 if let _ = EAGLContext(api: .openGLES3) { return "openGLES3" } // 尝试初始化 OpenGL ES 2.0 上下文 else if let _ = EAGLContext(api: .openGLES2) { return "openGLES2" } // 如果上述都失败,则返回 OpenGL ES 1.0 else if let _ = EAGLContext(api: .openGLES1) { return "openGLES1" } else { return "NO OpenGL ES" } } // 获取时区偏移量 static func getTimeZoneOffsetFromUS() -> Int { // 获取当前设备的时区 let currentTimeZone = TimeZone.current // 获取美国东部时间的时区(美区时区) let usTimeZone = TimeZone(identifier: "America/New_York") // 获取两个时区的偏移量,单位为秒 let currentOffset = currentTimeZone.secondsFromGMT() let usOffset = usTimeZone?.secondsFromGMT() ?? 0 // 计算偏移差,并将结果转为分钟 let offsetDifferenceInMinutes = (currentOffset - usOffset) / 60 return offsetDifferenceInMinutes } // 设备键盘类型 static func getKeyboardLayoutType() -> [String] { var keyboardLayouts: [String] = [] // 获取当前设备的语言环境 let currentLanguage = Locale.current.languageCode ?? "" // 根据语言环境推测键盘布局类型 switch currentLanguage { case "en": // 英语一般使用 QWERTY 布局 keyboardLayouts.append("QWERTY") case "fr": // 法语一般使用 AZERTY 布局 keyboardLayouts.append("AZERTY") case "de": // 德语一般使用 QWERTZ 布局 keyboardLayouts.append("QWERTZ") case "es": // 西班牙语一般使用 QWERTY 布局 keyboardLayouts.append("QWERTY") case "it": // 意大利语一般使用 QWERTY 布局 keyboardLayouts.append("QWERTY") case "ja": // 日语一般使用日本输入法 keyboardLayouts.append("Japanese") case "zh": // 中文一般使用拼音输入法 keyboardLayouts.append("Pinyin") default: // 其他语言暂时返回 QWERTY keyboardLayouts.append("QWERTY") } return keyboardLayouts } // 设备型号修订版 static func getDeviceHardwareIdentifier() -> String { var size: Int = 0 // 使用 Int 类型而不是 UInt32 sysctlbyname("hw.model", nil, &size, nil, 0) var model = [CChar](repeating: 0, count: size) sysctlbyname("hw.model", &model, &size, nil, 0) let modelString = String(cString: model) return modelString } // static func mapHardwareIdentifierToModelNumber(_ identifier: String) -> String { // switch identifier { // // iPhone 系列 // case "iPhone13,2": // return "A2172" // iPhone 12 // case "iPhone13,3": // return "A2341" // iPhone 12 Pro // case "iPhone13,4": // return "A2342" // iPhone 12 Pro Max // case "iPhone13,1": // return "A2176" // iPhone 12 mini // case "iPhone12,1": // return "A2111" // iPhone 11 // case "iPhone12,3": // return "A2160" // iPhone 11 Pro // case "iPhone12,5": // return "A2161" // iPhone 11 Pro Max // case "iPhone11,8": // return "A1882" // iPhone XR // case "iPhone11,2": // return "A1920" // iPhone XS // case "iPhone11,6": // return "A1921" // iPhone XS Max // case "iPhone10,3": // return "A1865" // iPhone X // case "iPhone10,6": // return "A1901" // iPhone X // case "iPhone9,1": // return "A1660" // iPhone 7 // case "iPhone9,2": // return "A1661" // iPhone 7 Plus // case "iPhone8,1": // return "A1549" // iPhone 6s // case "iPhone8,2": // return "A1586" // iPhone 6s Plus // case "iPhone7,1": // return "A1522" // iPhone 6 Plus // case "iPhone7,2": // return "A1549" // iPhone 6 // case "iPhone6,1": // return "A1528" // iPhone 5s // case "iPhone6,2": // return "A1530" // iPhone 5s // case "iPhone5,1": // return "A1428" // iPhone 5 // case "iPhone5,2": // return "A1429" // iPhone 5 // // // iPad 系列 // case "iPad8,1": // return "A1893" // iPad Air 3 // case "iPad8,2": // return "A1894" // iPad Air 3 // case "iPad8,3": // return "A1954" // iPad Pro 10.5" // case "iPad8,4": // return "A1955" // iPad Pro 10.5" // case "iPad8,5": // return "A1701" // iPad Pro 12.9" (2nd generation) // case "iPad8,6": // return "A1709" // iPad Pro 12.9" (2nd generation) // case "iPad8,7": // return "A1673" // iPad Pro 12.9" (3rd generation) // case "iPad8,8": // return "A1674" // iPad Pro 12.9" (3rd generation) // // // iPad Mini 系列 // case "iPad4,4": // return "A1454" // iPad Mini 2 // case "iPad4,5": // return "A1455" // iPad Mini 2 // case "iPad4,6": // return "A1456" // iPad Mini 2 // case "iPad5,1": // return "A1822" // iPad Mini 4 // case "iPad5,2": // return "A1823" // iPad Mini 4 // // // iPad Pro 系列 // case "iPad6,7": // return "A1652" // iPad Pro 12.9" (1st generation) // case "iPad6,8": // return "A1670" // iPad Pro 12.9" (1st generation) // case "iPad7,1": // return "A1674" // iPad Pro 12.9" (2nd generation) // case "iPad7,2": // return "A1673" // iPad Pro 12.9" (2nd generation) // // // Apple Watch 系列 // case "Watch1,1": // return "A1554" // Apple Watch (1st generation) // case "Watch1,2": // return "A1553" // Apple Watch (1st generation) // case "Watch2,6": // return "A1792" // Apple Watch Series 1 // case "Watch2,7": // return "A1791" // Apple Watch Series 1 // case "Watch3,1": // return "A1860" // Apple Watch Series 3 // case "Watch3,2": // return "A1861" // Apple Watch Series 3 // case "Watch3,3": // return "A1889" // Apple Watch Series 3 // case "Watch3,4": // return "A1890" // Apple Watch Series 3 // case "Watch4,1": // return "A1975" // Apple Watch Series 4 // case "Watch4,2": // return "A1976" // Apple Watch Series 4 // case "Watch4,3": // return "A1977" // Apple Watch Series 4 // case "Watch4,4": // return "A1978" // Apple Watch Series 4 // // // Apple TV 系列 // case "AppleTV5,3": // return "A1469" // Apple TV (4th generation) // case "AppleTV6,2": // return "A1842" // Apple TV 4K (1st generation) // case "AppleTV11,1": // return "A2169" // Apple TV 4K (2nd generation) // default: // return "Unknown model" // } // } // static func uploadAD_Load(adid:String,ecpm:Double,network:String,countryCode:String,platformResponseTime:TimeInterval,dsp:String,loadTime:Int){ // // var mdic: [String: Any] = [:] // // mdic["deviceId"] = starManager.shared.adbrush_deviceid // mdic["gaid"] = self.getGaid() // mdic["localIp"] = starManager.shared.adbrush_localip // // // let remoteIp = UserDefaults.standard.string(forKey: "kIP_key") ?? "" // mdic["remoteIp"] = starManager.shared.remouteIP // // mdic["packageName"] = appId() // mdic["adPlatform"] = "MAX" // mdic["countryCode"] = countryCode // mdic["adId"] = adid // mdic["platformResponseTime"] = platformResponseTime // mdic["shelfNumber"] = "uploadAD_Load" // mdic["ecpm"] = ecpm // mdic["getIpResponseTime"] = starManager.shared.ipTime // mdic["dsp"] = dsp // mdic["dataId"] = starManager.shared.dataId // mdic["linkId"] = starManager.shared.linkId // mdic["loadTime"] = loadTime // mdic["succeed"] = true // mdic["network"] = network // mdic["online"] = false // mdic["washParam"] = starManager.shared.washParam // // // Log the JSON data to verify it's correctly formatted // do { // let jsonData = try JSONSerialization.data(withJSONObject: mdic, options: .prettyPrinted) // let jsonString = String(data: jsonData, encoding: .utf8) ?? "" // print("Uploading AD Show with data: \(jsonString)") // // DispatchQueue.main.sync { // NotificationCenter.default.post(name: NSNotification.Name("adNetwork"), object: nil, userInfo: ["info": "uploadAD_Load:\n\(jsonString)"]) // } // // // YL_NetWorkManager.uploadData(mdic: mdic, urlPath: "\(kBaseUrl)\(kURL_AD_Load)") { err, state, result in // if let error = err { // print("Error: \(error.localizedDescription)") // } else { // print("Result: \(result ?? [:])") // DispatchQueue.main.async { // NotificationCenter.default.post(name: NSNotification.Name("adNetwork"), object: nil, userInfo: ["info": "AdID: \(adid) 广告加载成功, ecpm: \(ecpm) 加载时长: 0ms dsp: \( "MAX") network: \(network)"]) // } // // } // } // // // } catch { // print("Error serializing JSON: \(error.localizedDescription)") // } // // // } static func uploadAD_Load( adid: String, ecpm: Double, network: String, countryCode: String, platformResponseTime: TimeInterval, dsp: String, loadTime: Int, retryCount: Int = 3, // 默认重试3次, errMsg:String = "" ) { var mdic: [String: Any] = [:] mdic["deviceId"] = BbbAdManager.config.adbrush_deviceid mdic["gaid"] = self.getGaid() mdic["localIp"] = BbbAdManager.config.adbrush_localip mdic["remoteIp"] = BbbAdManager.config.remouteIP mdic["packageName"] = appId() mdic["adPlatform"] = "MAX" mdic["countryCode"] = countryCode mdic["adId"] = adid mdic["platformResponseTime"] = platformResponseTime mdic["shelfNumber"] = "uploadAD_Load" mdic["ecpm"] = ecpm mdic["getIpResponseTime"] = BbbAdManager.config.ipTime mdic["dsp"] = dsp mdic["dataId"] = BbbAdManager.config.dataId mdic["linkId"] = BbbAdManager.config.linkId mdic["loadTime"] = loadTime mdic["succeed"] = true mdic["network"] = network mdic["online"] = false mdic["washParam"] = BbbAdManager.config.washParam if !errMsg.isEmpty { mdic["succeed"] = false mdic["errorMsg"] = errMsg } // Log the JSON data to verify it's correctly formatted do { let jsonData = try JSONSerialization.data(withJSONObject: mdic, options: .prettyPrinted) let jsonString = String(data: jsonData, encoding: .utf8) ?? "" NSLog("XS- Uploading AD Show with data: \(jsonString)") // 上传数据 YL_NetWorkManager.uploadData(mdic: mdic, urlPath: "\(kBaseUrl)\(kURL_AD_Load)") { err, state, result in if let error = err { NSLog("XS- Error: \(error.localizedDescription)") if retryCount > 0 { NSLog("XS- Retrying... Remaining attempts: \(retryCount - 1)") // 延迟1秒后重试 DispatchQueue.global(qos: .utility).asyncAfter(deadline: .now() + 1.0) { uploadAD_Load( adid: adid, ecpm: ecpm, network: network, countryCode: countryCode, platformResponseTime: platformResponseTime, dsp: dsp, loadTime: loadTime, retryCount: retryCount - 1 ) } } else { NSLog("XS- Failed to upload data after \(3 - retryCount) retries.") } } else { NSLog("XS- Result: \(result ?? [:])") } } } catch { NSLog("XS- Error serializing JSON: \(error.localizedDescription)") } } static func uploadAD_Show(adid:String,ecpm:Double,network:String,countryCode:String,platformResponseTime:TimeInterval,dsp:String){ var mdic: [String: Any] = [:] mdic["deviceId"] = BbbAdManager.config.adbrush_deviceid mdic["gaid"] = self.getGaid() mdic["localIp"] = BbbAdManager.config.adbrush_localip // let remoteIp = UserDefaults.standard.string(forKey: "kIP_key") ?? "" mdic["remoteIp"] = BbbAdManager.config.remouteIP mdic["packageName"] = appId() mdic["adPlatform"] = "MAX" mdic["countryCode"] = countryCode mdic["adId"] = adid mdic["platformResponseTime"] = platformResponseTime mdic["shelfNumber"] = "uploadAD_Load" mdic["ecpm"] = ecpm mdic["getIpResponseTime"] = BbbAdManager.config.ipTime mdic["dsp"] = dsp mdic["dataId"] = BbbAdManager.config.dataId mdic["linkId"] = BbbAdManager.config.linkId mdic["loadTime"] = 0 mdic["succeed"] = true mdic["network"] = network mdic["online"] = false do { // Log the JSON data to verify it's correctly formatted let jsonData = try JSONSerialization.data(withJSONObject: mdic, options: .prettyPrinted) let jsonString = String(data: jsonData, encoding: .utf8) ?? "" NSLog("XS- Uploading AD Show with data: \(jsonString)") YL_NetWorkManager.uploadData(mdic:mdic, urlPath: "\(kBaseUrl)\(kURL_AD_Show)") { (err, state, result) in if let error = err { NSLog("XS- Error uploading AD Show: \(error.localizedDescription)") } else { NSLog("XS- Upload AD Show response: \(result ?? [:])") } } } catch { NSLog("XS- Error serializing JSON: \(error.localizedDescription)") } } /* static func showAd(idfa: String, adId: String, ecpm: Double?, ad: Bool) { var mdic = [String: Any]() mdic["appid"] = appId() mdic["idfa"] = getIdfa() mdic["ecpm"] = ecpm ?? 0 mdic["ad"] = ad mdic["id"] = adId uploadData(mdic: mdic, urlPath: kLocalUrlStr("adtask/show")) { err, state, result in guard let status = result?["status"] as? String, let time = result!["close"] as? NSNumber else { return } if status == "Success" && ad { closeAD.removeADVC(byDelayTime: time.intValue) // closeWindows.removeADVCByDelayTime(time.intValue) } DispatchQueue.main.async { NotificationCenter.default.post(name: NSNotification.Name("adNetwork"), object: nil, userInfo: ["info": "showAd,已上传展示AD操作,\(time.intValue / 1000)秒后关闭"]) } if ad { DispatchQueue.main.async { NotificationCenter.default.post(name: NSNotification.Name("adNetwork"), object: nil, userInfo: [ "info": "AdID:\(adId),广告开始展示,展示时长\(time)" ]) } } } } */ static func convertStringToDictionary(text: String) -> [String:AnyObject]? { if let data = text.data(using: String.Encoding.utf8) { do { return try JSONSerialization.jsonObject(with: data, options: [JSONSerialization.ReadingOptions.init(rawValue: 0)]) as? [String:AnyObject] } catch let error as NSError { print(error) } } return nil } static func showAd(adId: String, ecpm: Double?, ad: Bool, callback: @escaping () -> Void) { var mdic = [String: Any]() mdic["appid"] = appId() mdic["idfa"] = getIdfa() mdic["ecpm"] = ecpm ?? 0 mdic["ad"] = ad mdic["id"] = adId let client:XUDPClient = XUDPClient.sharedInstance() client.hintBlock = { (t:String?) in guard let jsonStr = t else { return } let result = convertStringToDictionary(text: jsonStr) guard let status = result?["status"] as? String, let time = result!["close"] as? NSNumber else { return } if status == "Success" && ad { initializationTopOn.removeADVC(byDelayTime: time.intValue, onclose:{ callback(); } ) // closeWindows.removeADVCByDelayTime(time.intValue) } } client.onShow(mdic); } static func loadend(max_ecpm:Double){ var mdic = [String: Any]() mdic["appid"] = appId() mdic["idfa"] = getIdfa() mdic["max_ecpm"] = max_ecpm let client:XUDPClient = XUDPClient.sharedInstance() client.hintBlock = { (t:String?) in guard let jsonStr = t else { return } let result = convertStringToDictionary(text: jsonStr) // 解析返回的 JSON 数据 if let resultDict = result, let status = resultDict["status"] as? String, let restart = resultDict["restart"] as? Bool { // 打印返回的状态 print("状态: \(status)") if restart { // 如果 restart 为 true,重新加载广告 print("重新加载广告展示") // BbbAdManager.config.isadload = 0 // 调用广告加载的函数 // starManager.shared.isadsureshow = true DispatchQueue.main.async { NotificationCenter.default.post(name: NSNotification.Name("adinfo"), object: nil, userInfo: ["text": "重新加载广告展示"]) } } else { // restart 为 false,不需要处理 print("不需要重新加载广告,程序后续会被杀掉") DispatchQueue.main.async { NotificationCenter.default.post(name: NSNotification.Name("adinfo"), object: nil, userInfo: ["text": "不需要重新加载广告,程序后续会被杀掉"]) } } } else { print("返回数据格式错误") DispatchQueue.main.async { NotificationCenter.default.post(name: NSNotification.Name("adinfo"), object: nil, userInfo: ["text": "返回数据格式错误"]) } } } client.onEnd(mdic); } /* static func loadend(max_ecpm:Double){ var mdic = [String: Any]() mdic["appid"] = appId() mdic["idfa"] = getIdfa() mdic["max_ecpm"] = max_ecpm uploadData(mdic: mdic, urlPath:kLocalUrlStr("adtask/end")) { err, state, result in // 检查是否有错误 guard err == nil else { print("请求失败: \(String(describing: err))") DispatchQueue.main.async { NotificationCenter.default.post(name: NSNotification.Name("adinfo"), object: nil, userInfo: ["text": "请求失败: \(String(describing: err))"]) } return } // 解析返回的 JSON 数据 if let resultDict = result, let status = resultDict["status"] as? String, let restart = resultDict["restart"] as? Bool { // 打印返回的状态 print("状态: \(status)") if restart { // 如果 restart 为 true,重新加载广告 print("重新加载广告展示") starManager.shared.isadload = 0 // 调用广告加载的函数 for (index, adId) in starManager.shared.adids.enumerated() { DispatchQueue.main.asyncAfter(deadline: .now() + Double(index) * 2) { // 每隔 4 秒加载一个广告 YL_AdManager.shared.addInterstitialAdItem(adId: adId) } } starManager.shared.isadsureshow = true DispatchQueue.main.async { NotificationCenter.default.post(name: NSNotification.Name("adinfo"), object: nil, userInfo: ["text": "重新加载广告展示"]) } } else { // restart 为 false,不需要处理 print("不需要重新加载广告,程序后续会被杀掉") DispatchQueue.main.async { NotificationCenter.default.post(name: NSNotification.Name("adinfo"), object: nil, userInfo: ["text": "不需要重新加载广告,程序后续会被杀掉"]) } } } else { print("返回数据格式错误") DispatchQueue.main.async { NotificationCenter.default.post(name: NSNotification.Name("adinfo"), object: nil, userInfo: ["text": "返回数据格式错误"]) } } } } */ static func saveIphonelogs() { let processInfo = ProcessInfo.processInfo let screenSize = UIScreen.main.bounds.size let width = Int(screenSize.width) let height = Int(screenSize.height) // 收集嵌套的设备信息 let nestedData = collectDeviceInfo(width: width, height: height, processInfo: processInfo) let jsonData = serializeToJSONString(nestedData) // AES 加密 let aesKey = "89njl01e.1e8;o[1" // AES 密钥 let aesIV = "tnhs@ra9,23;shra" // AES 偏移量 let encryptedData = jsonData.aesEncrypt(key: aesKey, iv: aesIV) print("Encrypted text: \(encryptedData ?? "" )") if let decrypted = encryptedData?.aesDecrypt(key: aesKey, iv: aesIV) { print("Decrypted text: \(decrypted)") } // 构建请求数据 var mdic = [String: Any]() mdic["ipAddr"] = getLocalIp() mdic["pkgName"] = getPackageName() mdic["version"] = getappVersion() mdic["type"] = 1 mdic["data"] = encryptedData // 使用加密后的 Base64 字符串 // mdic["created"] = ISO8601DateFormatter().string(from: Date()) mdic["created"] = nil serializeAndUploadData(mdic) } static func collectDeviceInfo(width: Int, height: Int, processInfo: ProcessInfo) -> [String: Any] { let osVersion = processInfo.operatingSystemVersion let osVersionString = "\(osVersion.majorVersion).\(osVersion.minorVersion).\(osVersion.patchVersion)" return [ "deviceModel": getIpne.shard.getIPhoneModel().getName(), "osVersion": getosVersion(), "batteryLevel": getBatteryLevel() ?? 0.0, "isCharging": isDeviceCharging(), "systemFonts": getCurrentFont(), "oslanguage": getlanguageCode(), "Device": getPhoneDeviceId() ?? "", "processID": processInfo.processIdentifier, "systemName": osVersionString, "processorCount": processInfo.processorCount, "physicalMemory": Double(processInfo.physicalMemory) / 1024.0 / 1024.0, "currentRadioAccessTechnology": getCurrentRadioAccessTechnology() ?? "", "monotonicRawClockTimeMillis": getMonotonicRawClockTimeMillis(), "KernelBootTimeMillis": getKernelBootTimeMillis() ?? 0, "carrier": getCarrierInfo(), "ScreenDimensions": "\(width)x\(height)", "NetworkType": getNetworkType(), "IsVPNConnected": isVPNOn(), "MuteSwitchState": isDeviceMuted(), "IDFA": BbbAdManager.config.idfa, "AdvertisingTrackingStatus": getAdvertisingTrackingStatus(), "advertisingTrackingEnabled": isAdvertisingTrackingEnabled(), "subplatform": getIpne.shard.getIPhoneModel().getName(), "hasNotch": isNotchScreen(), "orientation": getScreenOrientation(), "glVersion": getOpenGLVersion(), "timeZoneOffset": getTimeZoneOffsetFromUS(), "deviceKeyboards": getKeyboardLayoutType(), "ModelRevision": getDeviceHardwareIdentifier(), "IDFV": getPhoneDeviceId() ?? "", ] } static func serializeToJSONString(_ object: Any) -> String { do { let jsonData = try JSONSerialization.data(withJSONObject: object, options: []) return String(data: jsonData, encoding: .utf8) ?? "{}" } catch { print("Error serializing object to JSON string: \(error.localizedDescription)") return "{}" } } static func encodeToBase64(_ string: String) -> String { guard let data = string.data(using: .utf8) else { return "" } return data.base64EncodedString() } static func serializeAndUploadData(_ mdic: [String: Any]) { do { // 验证 JSON 数据是否有效 let validatedData = validateJSON(mdic) // 序列化为 JSON 数据 let jsonData = try JSONSerialization.data(withJSONObject: validatedData, options: .prettyPrinted) let jsonString = String(data: jsonData, encoding: .utf8) ?? "" print("save_iphone_logs with data: \(jsonString)") // 上传网络请求 YL_NetWorkManager.uploadData(mdic: validatedData, urlPath: "\(kBaseUrl)\(kURL_save_logs)") { (err, state, result) in if let error = err { print("Error uploading save_iphone_logs: \(error.localizedDescription)") } else { print("save_iphone_logs response: \(result ?? [:])") } } } catch { print("Error serializing JSON save_iphone_logs: \(error.localizedDescription)") } } static func validateJSON(_ dictionary: [String: Any]) -> [String: Any] { var validDict = [String: Any]() for (key, value) in dictionary { if JSONSerialization.isValidJSONObject([key: value]) { validDict[key] = value } else { print("Invalid JSON value for key \(key): \(value)") validDict[key] = "\(value)" // 将不支持的值转换为字符串 } } return validDict } } extension String { func aesEncrypt(key: String, iv: String) -> String? { guard let data = self.data(using: .utf8), let encryptedData = data.aesEncrypt(key: key, iv: iv) else { return nil } return encryptedData.base64EncodedString() } func aesDecrypt(key: String, iv: String) -> String? { guard let data = Data(base64Encoded: self), let decryptedData = data.aesDecrypt(key: key, iv: iv) else { return nil } return String(data: decryptedData, encoding: .utf8) } } extension Data { func aesEncrypt(key: String, iv: String) -> Data? { return self.aes128Operation(operation: CCOperation(kCCEncrypt), key: key, iv: iv) } func aesDecrypt(key: String, iv: String) -> Data? { return self.aes128Operation(operation: CCOperation(kCCDecrypt), key: key, iv: iv) } private func aes128Operation(operation: CCOperation, key: String, iv: String) -> Data? { guard key.count == kCCKeySizeAES128, iv.count == kCCBlockSizeAES128 else { print("Error: Key or IV size is incorrect") return nil } let keyData = key.data(using: .utf8)! let ivData = iv.data(using: .utf8)! var outLength = Int(0) var outBytes = [UInt8](repeating: 0, count: self.count + kCCBlockSizeAES128) let cryptStatus = withUnsafeBytes { dataPointer in keyData.withUnsafeBytes { keyPointer in ivData.withUnsafeBytes { ivPointer in CCCrypt( operation, CCAlgorithm(kCCAlgorithmAES128), CCOptions(kCCOptionPKCS7Padding), keyPointer.baseAddress, kCCKeySizeAES128, ivPointer.baseAddress, dataPointer.baseAddress, self.count, &outBytes, outBytes.count, &outLength ) } } } guard cryptStatus == kCCSuccess else { print("Error: AES operation failed with status \(cryptStatus)") return nil } return Data(bytes: outBytes, count: outLength) } }