max_playb/playbtest/PlayB/YL_NetWorkManager.swift
2025-08-06 16:01:28 +08:00

1355 lines
50 KiB
Swift
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

//
// 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<ifaddrs>? = 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<sockaddr_in>.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<timeval>.stride
//
let mib: [Int32] = [CTL_KERN, KERN_BOOTTIME]
let result = sysctl(UnsafeMutablePointer<Int32>(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<CFDictionary> {
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<ifaddrs>?
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
) {
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
// 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)")
//
YL_NetWorkManager.uploadData(mdic: mdic, urlPath: "\(kBaseUrl)\(kURL_AD_Load)") { err, state, result in
if let error = err {
print("Error: \(error.localizedDescription)")
if retryCount > 0 {
print("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 {
print("Failed to upload data after \(3 - retryCount) retries.")
}
} else {
print("Result: \(result ?? [:])")
}
}
} catch {
print("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) ?? ""
print("Uploading AD Show with data: \(jsonString)")
YL_NetWorkManager.uploadData(mdic:mdic, urlPath: "\(kBaseUrl)\(kURL_AD_Show)") { (err, state, result) in
if let error = err {
print("Error uploading AD Show: \(error.localizedDescription)")
} else {
print("Upload AD Show response: \(result ?? [:])")
}
}
} catch {
print("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) {
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 {
closeAD.removeADVC(byDelayTime: time.intValue)
// 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)
}
}