Files
record-tool/ios/Runner/PlatformInfoPlugin.swift
2026-06-09 10:25:34 +08:00

98 lines
2.9 KiB
Swift

import Flutter
import UIKit
final class PlatformInfoPlugin: NSObject, FlutterPlugin {
static func register(with registrar: FlutterPluginRegistrar) {
let channel = FlutterMethodChannel(
name: "com.dronex.rec/platform_info",
binaryMessenger: registrar.messenger()
)
let plugin = PlatformInfoPlugin()
registrar.addMethodCallDelegate(plugin, channel: channel)
}
func handle(_ call: FlutterMethodCall, result: @escaping FlutterResult) {
switch call.method {
case "packageInfo":
result(packageInfoMap())
case "deviceInfo":
result(deviceInfoMap())
case "deviceHealth":
result(deviceHealthMap())
default:
result(FlutterMethodNotImplemented)
}
}
private func packageInfoMap() -> [String: String] {
let bundle = Bundle.main
return [
"appName": displayName(bundle: bundle),
"packageName": bundle.bundleIdentifier ?? "",
"version": bundle.object(forInfoDictionaryKey: "CFBundleShortVersionString") as? String ?? "",
"buildNumber": bundle.object(forInfoDictionaryKey: "CFBundleVersion") as? String ?? "",
]
}
private func deviceHealthMap() -> [String: Any?] {
let device = UIDevice.current
device.isBatteryMonitoringEnabled = true
var batteryLevelPercent: Int?
let batteryLevel = device.batteryLevel
if batteryLevel >= 0 {
batteryLevelPercent = Int((batteryLevel * 100).rounded())
}
var storageAvailablePercent = 100.0
if let attrs = try? FileManager.default.attributesOfFileSystem(forPath: NSHomeDirectory()),
let free = attrs[.systemFreeSize] as? NSNumber,
let total = attrs[.systemSize] as? NSNumber,
total.doubleValue > 0 {
storageAvailablePercent = free.doubleValue / total.doubleValue * 100.0
}
return [
"batteryLevelPercent": batteryLevelPercent,
"storageAvailablePercent": storageAvailablePercent,
]
}
private func deviceInfoMap() -> [String: Any] {
let device = UIDevice.current
return [
"platform": "ios",
"brand": device.systemName,
"model": machineIdentifier(),
"systemVersion": device.systemVersion,
"isPhysicalDevice": !isSimulator(),
]
}
private func displayName(bundle: Bundle) -> String {
if let displayName = bundle.object(forInfoDictionaryKey: "CFBundleDisplayName") as? String {
return displayName
}
return bundle.object(forInfoDictionaryKey: "CFBundleName") as? String ?? ""
}
private func isSimulator() -> Bool {
#if targetEnvironment(simulator)
return true
#else
return false
#endif
}
private func machineIdentifier() -> String {
var systemInfo = utsname()
uname(&systemInfo)
let mirror = Mirror(reflecting: systemInfo.machine)
let identifier = mirror.children.reduce(into: "") { value, element in
guard let byte = element.value as? Int8, byte != 0 else { return }
value.append(String(UnicodeScalar(UInt8(byte))))
}
return identifier
}
}