2024-09-04 05:01:33 +00:00
|
|
|
|
//
|
|
|
|
|
|
// Constants.swift
|
|
|
|
|
|
// AgoraChatRoom
|
|
|
|
|
|
//
|
|
|
|
|
|
// Created by LXH on 2019/11/27.
|
|
|
|
|
|
// Copyright © 2019 CavanSu. All rights reserved.
|
|
|
|
|
|
//
|
|
|
|
|
|
|
|
|
|
|
|
import UIKit
|
|
|
|
|
|
|
|
|
|
|
|
internal struct Constants {
|
|
|
|
|
|
|
|
|
|
|
|
private static let appVersion: String = {
|
|
|
|
|
|
guard let infoDict = Bundle.main.infoDictionary,
|
|
|
|
|
|
let currentVersion = infoDict["CFBundleShortVersionString"] as? String else {
|
|
|
|
|
|
return ""
|
|
|
|
|
|
}
|
|
|
|
|
|
return currentVersion
|
|
|
|
|
|
}()
|
|
|
|
|
|
|
|
|
|
|
|
private static let appBundleIdentifier: String = {
|
|
|
|
|
|
guard let infoDictionary = Bundle.main.infoDictionary,
|
|
|
|
|
|
let shortVersion = infoDictionary["CFBundleIdentifier"] as? String else {
|
|
|
|
|
|
return ""
|
|
|
|
|
|
}
|
|
|
|
|
|
return shortVersion
|
|
|
|
|
|
}()
|
|
|
|
|
|
|
2025-08-08 10:12:14 +00:00
|
|
|
|
private static let guruAnalyticsSDKVersion: String = {
|
2024-09-23 02:53:09 +00:00
|
|
|
|
guard let infoDict = Bundle(for: Manager.self).infoDictionary,
|
|
|
|
|
|
let currentVersion = infoDict["CFBundleShortVersionString"] as? String else {
|
|
|
|
|
|
return ""
|
|
|
|
|
|
}
|
|
|
|
|
|
return currentVersion
|
|
|
|
|
|
}()
|
|
|
|
|
|
|
2025-08-08 10:12:14 +00:00
|
|
|
|
/// 中台库版本,由外部更新
|
|
|
|
|
|
static var guruSDKVersion: String = "";
|
|
|
|
|
|
|
2024-09-04 05:01:33 +00:00
|
|
|
|
private static let preferredLocale: Locale = {
|
|
|
|
|
|
guard let preferredIdentifier = Locale.preferredLanguages.first else {
|
|
|
|
|
|
return Locale.current
|
|
|
|
|
|
}
|
|
|
|
|
|
return Locale(identifier: preferredIdentifier)
|
|
|
|
|
|
}()
|
|
|
|
|
|
|
|
|
|
|
|
private static let countryCode: String = {
|
|
|
|
|
|
return preferredLocale.regionCode?.uppercased() ?? ""
|
|
|
|
|
|
}()
|
|
|
|
|
|
|
|
|
|
|
|
private static let timeZone: String = {
|
|
|
|
|
|
return TimeZone.current.identifier
|
|
|
|
|
|
}()
|
|
|
|
|
|
|
|
|
|
|
|
private static let languageCode: String = {
|
|
|
|
|
|
return preferredLocale.languageCode ?? ""
|
|
|
|
|
|
}()
|
|
|
|
|
|
|
|
|
|
|
|
private static let localeCode: String = {
|
|
|
|
|
|
return preferredLocale.identifier
|
|
|
|
|
|
}()
|
|
|
|
|
|
|
|
|
|
|
|
private static let modelName: String = {
|
|
|
|
|
|
return platform().deviceType.rawValue
|
|
|
|
|
|
}()
|
|
|
|
|
|
|
|
|
|
|
|
private static let model: String = {
|
|
|
|
|
|
return hardwareString()
|
|
|
|
|
|
}()
|
|
|
|
|
|
|
|
|
|
|
|
private static let systemVersion: String = {
|
|
|
|
|
|
return UIDevice.current.systemVersion
|
|
|
|
|
|
}()
|
|
|
|
|
|
|
|
|
|
|
|
private static let screenSize: (w: CGFloat, h: CGFloat) = {
|
|
|
|
|
|
return (UIScreen.main.bounds.width, UIScreen.main.bounds.height)
|
|
|
|
|
|
}()
|
|
|
|
|
|
|
|
|
|
|
|
/// 时区偏移毫秒数
|
|
|
|
|
|
private static let tzOffset: Int64 = {
|
|
|
|
|
|
return Int64(TimeZone.current.secondsFromGMT(for: Date())) * 1000
|
|
|
|
|
|
}()
|
|
|
|
|
|
|
|
|
|
|
|
static var deviceInfo: [String : Any] {
|
|
|
|
|
|
return [
|
|
|
|
|
|
"country": countryCode,
|
|
|
|
|
|
"platform": "IOS",
|
|
|
|
|
|
"appId" : appBundleIdentifier,
|
|
|
|
|
|
"version" : appVersion,
|
|
|
|
|
|
"tzOffset": tzOffset,
|
|
|
|
|
|
"deviceType" : modelName,
|
|
|
|
|
|
"brand": "Apple",
|
|
|
|
|
|
"model": model,
|
|
|
|
|
|
"screenH": Int(screenSize.h),
|
|
|
|
|
|
"screenW": Int(screenSize.w),
|
|
|
|
|
|
"osVersion": systemVersion,
|
2024-09-23 02:53:09 +00:00
|
|
|
|
"language" : languageCode,
|
2025-08-08 10:12:14 +00:00
|
|
|
|
"guruAnalyticsVersion" : guruAnalyticsSDKVersion,
|
|
|
|
|
|
"gurusdkVersion" : guruSDKVersion,
|
2024-09-04 05:01:33 +00:00
|
|
|
|
]
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/// This method returns the hardware type
|
|
|
|
|
|
///
|
|
|
|
|
|
///
|
|
|
|
|
|
/// - returns: raw `String` of device type, e.g. iPhone5,1
|
|
|
|
|
|
///
|
|
|
|
|
|
private static func hardwareString() -> String {
|
2025-08-08 10:12:14 +00:00
|
|
|
|
var name: [Int32] = [CTL_HW, HW_MACHINE]
|
|
|
|
|
|
var size: size_t = 0
|
|
|
|
|
|
|
|
|
|
|
|
// 🛡️ 安全检查1:获取缓冲区大小
|
|
|
|
|
|
guard sysctl(&name, 2, nil, &size, nil, 0) == 0,
|
|
|
|
|
|
size > 0 && size < 256 else {
|
|
|
|
|
|
return "iPhone14,1" // 安全默认值
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 🛡️ 安全检查2:创建缓冲区
|
|
|
|
|
|
let bufferSize = Int(size) + 1
|
|
|
|
|
|
var hw_machine = [CChar](repeating: 0, count: bufferSize)
|
|
|
|
|
|
var actualSize = size
|
|
|
|
|
|
|
|
|
|
|
|
// 🛡️ 安全检查3:获取数据
|
|
|
|
|
|
guard sysctl(&name, 2, &hw_machine, &actualSize, nil, 0) == 0 else {
|
|
|
|
|
|
return "iPhone14,1" // 安全默认值
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 🛡️ 安全检查4:确保null终止(防止越界)
|
|
|
|
|
|
let safeIndex = min(Int(actualSize), bufferSize - 1)
|
|
|
|
|
|
hw_machine[safeIndex] = 0
|
|
|
|
|
|
|
|
|
|
|
|
var hardware: String = String(cString: hw_machine)
|
|
|
|
|
|
|
|
|
|
|
|
// 🛡️ 安全检查5:验证结果
|
|
|
|
|
|
if hardware.isEmpty {
|
|
|
|
|
|
return "iPhone14,1" // 安全默认值
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// Check for simulator
|
|
|
|
|
|
if hardware == "x86_64" || hardware == "i386" || hardware == "arm64" {
|
|
|
|
|
|
if let deviceID = ProcessInfo.processInfo.environment["SIMULATOR_MODEL_IDENTIFIER"] {
|
|
|
|
|
|
hardware = deviceID
|
|
|
|
|
|
} else {
|
|
|
|
|
|
hardware = "Simulator"
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
return hardware
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//这里不可用,有崩溃!!!用上边的方法!!
|
|
|
|
|
|
private static func hardwareStringError() -> String {
|
2024-09-04 05:01:33 +00:00
|
|
|
|
var name: [Int32] = [CTL_HW, HW_MACHINE]
|
|
|
|
|
|
var size: Int = 2
|
|
|
|
|
|
sysctl(&name, 2, nil, &size, nil, 0)
|
|
|
|
|
|
var hw_machine = [CChar](repeating: 0, count: Int(size))
|
|
|
|
|
|
sysctl(&name, 2, &hw_machine, &size, nil, 0)
|
|
|
|
|
|
|
|
|
|
|
|
var hardware: String = String(cString: hw_machine)
|
|
|
|
|
|
|
|
|
|
|
|
// Check for simulator
|
|
|
|
|
|
if hardware == "x86_64" || hardware == "i386" || hardware == "arm64" {
|
|
|
|
|
|
if let deviceID = ProcessInfo.processInfo.environment["SIMULATOR_MODEL_IDENTIFIER"] {
|
|
|
|
|
|
hardware = deviceID
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
2025-08-08 10:12:14 +00:00
|
|
|
|
|
2024-09-04 05:01:33 +00:00
|
|
|
|
return hardware
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-08-08 10:12:14 +00:00
|
|
|
|
|
|
|
|
|
|
|
2024-09-04 05:01:33 +00:00
|
|
|
|
/// This method returns the Platform enum depending upon harware string
|
|
|
|
|
|
///
|
|
|
|
|
|
///
|
|
|
|
|
|
/// - returns: `Platform` type of the device
|
|
|
|
|
|
///
|
|
|
|
|
|
static func platform() -> Platform {
|
|
|
|
|
|
|
|
|
|
|
|
let hardware = hardwareString()
|
|
|
|
|
|
|
|
|
|
|
|
if (hardware.hasPrefix("iPhone")) { return .iPhone }
|
|
|
|
|
|
if (hardware.hasPrefix("iPod")) { return .iPodTouch }
|
|
|
|
|
|
if (hardware.hasPrefix("iPad")) { return .iPad }
|
|
|
|
|
|
if (hardware.hasPrefix("Watch")) { return .appleWatch }
|
|
|
|
|
|
if (hardware.hasPrefix("AppleTV")) { return .appleTV }
|
|
|
|
|
|
|
|
|
|
|
|
return .unknown
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
enum Platform {
|
|
|
|
|
|
case iPhone
|
|
|
|
|
|
case iPodTouch
|
|
|
|
|
|
case iPad
|
|
|
|
|
|
case appleWatch
|
|
|
|
|
|
case appleTV
|
|
|
|
|
|
case unknown
|
|
|
|
|
|
|
|
|
|
|
|
enum DeviceType: String {
|
|
|
|
|
|
case mobile, tablet, desktop, smartTV, watch, other
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
var deviceType: DeviceType {
|
|
|
|
|
|
switch self {
|
|
|
|
|
|
case .iPad:
|
|
|
|
|
|
return .tablet
|
|
|
|
|
|
case .iPhone, .iPodTouch:
|
|
|
|
|
|
return .mobile
|
|
|
|
|
|
case .appleTV:
|
|
|
|
|
|
return .smartTV
|
|
|
|
|
|
case .appleWatch:
|
|
|
|
|
|
return .watch
|
|
|
|
|
|
case .unknown:
|
|
|
|
|
|
return .other
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
}
|