diff --git a/.github/workflows/device_info_plus.yaml b/.github/workflows/device_info_plus.yaml
index 7403b99129..d44783a388 100644
--- a/.github/workflows/device_info_plus.yaml
+++ b/.github/workflows/device_info_plus.yaml
@@ -88,7 +88,7 @@ jobs:
script: ./.github/workflows/scripts/integration-test.sh android device_info_plus_example
ios_example_build:
- runs-on: macos-14
+ runs-on: macos-15
timeout-minutes: 30
steps:
- name: "Checkout repository"
@@ -101,7 +101,7 @@ jobs:
run: ./.github/workflows/scripts/build-examples.sh ios ./lib/main.dart
ios_integration_test:
- runs-on: macos-14
+ runs-on: macos-15
timeout-minutes: 30
steps:
- name: "Checkout repository"
@@ -115,12 +115,12 @@ jobs:
- name: "Start Simulator"
uses: futureware-tech/simulator-action@v4
with:
- model: 'iPhone 15'
+ model: 'iPhone 16'
- name: "Run Integration Test"
run: ./.github/workflows/scripts/integration-test.sh ios device_info_plus_example
macos_example_build:
- runs-on: macos-14
+ runs-on: macos-15
timeout-minutes: 30
steps:
- name: "Checkout repository"
@@ -133,7 +133,7 @@ jobs:
run: ./.github/workflows/scripts/build-examples.sh macos ./lib/main.dart
macos_integration_test:
- runs-on: macos-14
+ runs-on: macos-15
timeout-minutes: 30
steps:
- name: "Checkout repository"
diff --git a/packages/device_info_plus/device_info_plus/example/integration_test/device_info_plus_test.dart b/packages/device_info_plus/device_info_plus/example/integration_test/device_info_plus_test.dart
index 84d2630492..bf8cd3c970 100644
--- a/packages/device_info_plus/device_info_plus/example/integration_test/device_info_plus_test.dart
+++ b/packages/device_info_plus/device_info_plus/example/integration_test/device_info_plus_test.dart
@@ -117,6 +117,7 @@ void main() {
expect(macosInfo.hostName, isNotNull);
expect(macosInfo.arch, isNotNull);
expect(macosInfo.model, isNotNull);
+ expect(macosInfo.modelName, isNotNull);
expect(macosInfo.kernelVersion, isNotNull);
expect(macosInfo.osRelease, isNotNull);
expect(macosInfo.activeCPUs, isNotNull);
diff --git a/packages/device_info_plus/device_info_plus/example/ios/Flutter/AppFrameworkInfo.plist b/packages/device_info_plus/device_info_plus/example/ios/Flutter/AppFrameworkInfo.plist
index 4f8d4d2456..8c6e56146e 100644
--- a/packages/device_info_plus/device_info_plus/example/ios/Flutter/AppFrameworkInfo.plist
+++ b/packages/device_info_plus/device_info_plus/example/ios/Flutter/AppFrameworkInfo.plist
@@ -21,6 +21,6 @@
CFBundleVersion
1.0
MinimumOSVersion
- 11.0
+ 12.0
diff --git a/packages/device_info_plus/device_info_plus/example/ios/Runner.xcodeproj/project.pbxproj b/packages/device_info_plus/device_info_plus/example/ios/Runner.xcodeproj/project.pbxproj
index 90d1082afa..075d8eecde 100644
--- a/packages/device_info_plus/device_info_plus/example/ios/Runner.xcodeproj/project.pbxproj
+++ b/packages/device_info_plus/device_info_plus/example/ios/Runner.xcodeproj/project.pbxproj
@@ -214,7 +214,7 @@
97C146E61CF9000F007C117D /* Project object */ = {
isa = PBXProject;
attributes = {
- LastUpgradeCheck = 1430;
+ LastUpgradeCheck = 1510;
ORGANIZATIONNAME = "";
TargetAttributes = {
331C8080294A63A400263BE5 = {
@@ -451,7 +451,7 @@
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
- IPHONEOS_DEPLOYMENT_TARGET = 11.0;
+ IPHONEOS_DEPLOYMENT_TARGET = 12.0;
MTL_ENABLE_DEBUG_INFO = NO;
SDKROOT = iphoneos;
SUPPORTED_PLATFORMS = iphoneos;
@@ -579,7 +579,7 @@
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
- IPHONEOS_DEPLOYMENT_TARGET = 11.0;
+ IPHONEOS_DEPLOYMENT_TARGET = 12.0;
MTL_ENABLE_DEBUG_INFO = YES;
ONLY_ACTIVE_ARCH = YES;
SDKROOT = iphoneos;
@@ -628,7 +628,7 @@
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
- IPHONEOS_DEPLOYMENT_TARGET = 11.0;
+ IPHONEOS_DEPLOYMENT_TARGET = 12.0;
MTL_ENABLE_DEBUG_INFO = NO;
SDKROOT = iphoneos;
SUPPORTED_PLATFORMS = iphoneos;
diff --git a/packages/device_info_plus/device_info_plus/example/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme b/packages/device_info_plus/device_info_plus/example/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme
index 87131a09be..8e3ca5dfe1 100644
--- a/packages/device_info_plus/device_info_plus/example/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme
+++ b/packages/device_info_plus/device_info_plus/example/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme
@@ -1,6 +1,6 @@
+ CADisableMinimumFrameDurationOnPhone
+
CFBundleDevelopmentRegion
$(DEVELOPMENT_LANGUAGE)
CFBundleDisplayName
@@ -24,6 +26,8 @@
$(FLUTTER_BUILD_NUMBER)
LSRequiresIPhoneOS
+ UIApplicationSupportsIndirectInputEvents
+
UILaunchStoryboardName
LaunchScreen
UIMainStoryboardFile
@@ -43,9 +47,5 @@
UIViewControllerBasedStatusBarAppearance
- CADisableMinimumFrameDurationOnPhone
-
- UIApplicationSupportsIndirectInputEvents
-
diff --git a/packages/device_info_plus/device_info_plus/example/lib/main.dart b/packages/device_info_plus/device_info_plus/example/lib/main.dart
index 5ea541c5dd..c188b03538 100644
--- a/packages/device_info_plus/device_info_plus/example/lib/main.dart
+++ b/packages/device_info_plus/device_info_plus/example/lib/main.dart
@@ -112,6 +112,7 @@ class _MyAppState extends State {
'systemName': data.systemName,
'systemVersion': data.systemVersion,
'model': data.model,
+ 'modelName': data.modelName,
'localizedModel': data.localizedModel,
'identifierForVendor': data.identifierForVendor,
'isPhysicalDevice': data.isPhysicalDevice,
@@ -166,6 +167,7 @@ class _MyAppState extends State {
'hostName': data.hostName,
'arch': data.arch,
'model': data.model,
+ 'modelName': data.modelName,
'kernelVersion': data.kernelVersion,
'majorVersion': data.majorVersion,
'minorVersion': data.minorVersion,
diff --git a/packages/device_info_plus/device_info_plus/example/macos/Runner.xcodeproj/project.pbxproj b/packages/device_info_plus/device_info_plus/example/macos/Runner.xcodeproj/project.pbxproj
index 02a8e04d7d..17738f85dc 100644
--- a/packages/device_info_plus/device_info_plus/example/macos/Runner.xcodeproj/project.pbxproj
+++ b/packages/device_info_plus/device_info_plus/example/macos/Runner.xcodeproj/project.pbxproj
@@ -259,7 +259,7 @@
isa = PBXProject;
attributes = {
LastSwiftUpdateCheck = 0920;
- LastUpgradeCheck = 1430;
+ LastUpgradeCheck = 1510;
ORGANIZATIONNAME = "";
TargetAttributes = {
331C80D4294CF70F00263BE5 = {
diff --git a/packages/device_info_plus/device_info_plus/example/macos/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme b/packages/device_info_plus/device_info_plus/example/macos/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme
index bcdcdc013c..7bb1c7dfdf 100644
--- a/packages/device_info_plus/device_info_plus/example/macos/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme
+++ b/packages/device_info_plus/device_info_plus/example/macos/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme
@@ -1,6 +1,6 @@
Bool {
return true
diff --git a/packages/device_info_plus/device_info_plus/example/pubspec.yaml b/packages/device_info_plus/device_info_plus/example/pubspec.yaml
index d54544c328..718ea2f843 100644
--- a/packages/device_info_plus/device_info_plus/example/pubspec.yaml
+++ b/packages/device_info_plus/device_info_plus/example/pubspec.yaml
@@ -1,5 +1,6 @@
name: device_info_plus_example
description: Demonstrates how to use the device_info_plus plugin.
+version: 1.0.0
dependencies:
flutter:
diff --git a/packages/device_info_plus/device_info_plus/ios/device_info_plus/Sources/device_info_plus/DeviceIdentifiers.m b/packages/device_info_plus/device_info_plus/ios/device_info_plus/Sources/device_info_plus/DeviceIdentifiers.m
new file mode 100644
index 0000000000..cda41d953f
--- /dev/null
+++ b/packages/device_info_plus/device_info_plus/ios/device_info_plus/Sources/device_info_plus/DeviceIdentifiers.m
@@ -0,0 +1,208 @@
+//
+// DeviceIdentifiers.m
+// device_info_plus
+//
+// Created by Volodymyr on 06.11.2024.
+//
+#import "./include/device_info_plus/DeviceIdentifiers.h"
+
+@implementation DeviceIdentifiers
+
++ (NSString *)userKnownDeviceModel:(NSString *)identifier {
+ if ([identifier isEqualToString:@"iPhone6,1"]) {
+ return @"iPhone 5s";
+ } else if ([identifier isEqualToString:@"iPhone6,2"]) {
+ return @"iPhone 5s";
+ } else if ([identifier isEqualToString:@"iPhone7,2"]) {
+ return @"iPhone 6";
+ } else if ([identifier isEqualToString:@"iPhone7,1"]) {
+ return @"iPhone 6 Plus";
+ } else if ([identifier isEqualToString:@"iPhone8,1"]) {
+ return @"iPhone 6s";
+ } else if ([identifier isEqualToString:@"iPhone8,2"]) {
+ return @"iPhone 6s Plus";
+ } else if ([identifier isEqualToString:@"iPhone9,1"] ||
+ [identifier isEqualToString:@"iPhone9,3"]) {
+ return @"iPhone 7";
+ } else if ([identifier isEqualToString:@"iPhone9,2"] ||
+ [identifier isEqualToString:@"iPhone9,4"]) {
+ return @"iPhone 7 Plus";
+ } else if ([identifier isEqualToString:@"iPhone8,4"]) {
+ return @"iPhone SE";
+ } else if ([identifier isEqualToString:@"iPhone10,1"] ||
+ [identifier isEqualToString:@"iPhone10,4"]) {
+ return @"iPhone 8";
+ } else if ([identifier isEqualToString:@"iPhone10,2"] ||
+ [identifier isEqualToString:@"iPhone10,5"]) {
+ return @"iPhone 8 Plus";
+ } else if ([identifier isEqualToString:@"iPhone10,3"] ||
+ [identifier isEqualToString:@"iPhone10,6"]) {
+ return @"iPhone X";
+ } else if ([identifier isEqualToString:@"iPhone11,2"]) {
+ return @"iPhone XS";
+ } else if ([identifier isEqualToString:@"iPhone11,4"] ||
+ [identifier isEqualToString:@"iPhone11,6"]) {
+ return @"iPhone XS Max";
+ } else if ([identifier isEqualToString:@"iPhone11,8"]) {
+ return @"iPhone XR";
+ } else if ([identifier isEqualToString:@"iPhone12,1"]) {
+ return @"iPhone 11";
+ } else if ([identifier isEqualToString:@"iPhone12,3"]) {
+ return @"iPhone 11 Pro";
+ } else if ([identifier isEqualToString:@"iPhone12,5"]) {
+ return @"iPhone 11 Pro Max";
+ } else if ([identifier isEqualToString:@"iPhone12,8"]) {
+ return @"iPhone SE 2";
+ } else if ([identifier isEqualToString:@"iPhone13,2"]) {
+ return @"iPhone 12";
+ } else if ([identifier isEqualToString:@"iPhone13,1"]) {
+ return @"iPhone 12 Mini";
+ } else if ([identifier isEqualToString:@"iPhone13,3"]) {
+ return @"iPhone 12 Pro";
+ } else if ([identifier isEqualToString:@"iPhone13,4"]) {
+ return @"iPhone 12 Pro Max";
+ } else if ([identifier isEqualToString:@"iPhone14,5"]) {
+ return @"iPhone 13";
+ } else if ([identifier isEqualToString:@"iPhone14,4"]) {
+ return @"iPhone 13 Mini";
+ } else if ([identifier isEqualToString:@"iPhone14,2"]) {
+ return @"iPhone 13 Pro";
+ } else if ([identifier isEqualToString:@"iPhone14,3"]) {
+ return @"iPhone 13 Pro Max";
+ } else if ([identifier isEqualToString:@"iPhone14,6"]) {
+ return @"iPhone SE 3";
+ } else if ([identifier isEqualToString:@"iPhone14,7"]) {
+ return @"iPhone 14";
+ } else if ([identifier isEqualToString:@"iPhone14,8"]) {
+ return @"iPhone 14 Plus";
+ } else if ([identifier isEqualToString:@"iPhone15,2"]) {
+ return @"iPhone 14 Pro";
+ } else if ([identifier isEqualToString:@"iPhone15,3"]) {
+ return @"iPhone 14 Pro Max";
+ } else if ([identifier isEqualToString:@"iPhone15,4"]) {
+ return @"iPhone 15";
+ } else if ([identifier isEqualToString:@"iPhone15,5"]) {
+ return @"iPhone 15 Plus";
+ } else if ([identifier isEqualToString:@"iPhone16,1"]) {
+ return @"iPhone 15 Pro";
+ } else if ([identifier isEqualToString:@"iPhone16,2"]) {
+ return @"iPhone 15 Pro Max";
+ } else if ([identifier isEqualToString:@"iPhone17,3"]) {
+ return @"iPhone 16";
+ } else if ([identifier isEqualToString:@"iPhone17,4"]) {
+ return @"iPhone 16 Plus";
+ } else if ([identifier isEqualToString:@"iPhone17,1"]) {
+ return @"iPhone 16 Pro";
+ } else if ([identifier isEqualToString:@"iPhone17,2"]) {
+ return @"iPhone 16 Pro Max";
+ // iPads
+ } else if ([identifier isEqualToString:@"iPad4,1"] ||
+ [identifier isEqualToString:@"iPad4,2"] ||
+ [identifier isEqualToString:@"iPad4,3"]) {
+ return @"iPad Air";
+ } else if ([identifier isEqualToString:@"iPad5,3"] ||
+ [identifier isEqualToString:@"iPad5,4"]) {
+ return @"iPad Air 2";
+ } else if ([identifier isEqualToString:@"iPad6,11"] ||
+ [identifier isEqualToString:@"iPad6,12"]) {
+ return @"iPad 5";
+ } else if ([identifier isEqualToString:@"iPad7,5"] ||
+ [identifier isEqualToString:@"iPad7,6"]) {
+ return @"iPad 6";
+ } else if ([identifier isEqualToString:@"iPad11,3"] ||
+ [identifier isEqualToString:@"iPad11,4"]) {
+ return @"iPad Air 3";
+ } else if ([identifier isEqualToString:@"iPad7,11"] ||
+ [identifier isEqualToString:@"iPad7,12"]) {
+ return @"iPad 7";
+ } else if ([identifier isEqualToString:@"iPad11,6"] ||
+ [identifier isEqualToString:@"iPad11,7"]) {
+ return @"iPad 8";
+ } else if ([identifier isEqualToString:@"iPad12,1"] ||
+ [identifier isEqualToString:@"iPad12,2"]) {
+ return @"iPad 9";
+ } else if ([identifier isEqualToString:@"iPad13,18"] ||
+ [identifier isEqualToString:@"iPad13,19"]) {
+ return @"iPad 10";
+ } else if ([identifier isEqualToString:@"iPad13,1"] ||
+ [identifier isEqualToString:@"iPad13,2"]) {
+ return @"iPad Air 4";
+ } else if ([identifier isEqualToString:@"iPad13,16"] ||
+ [identifier isEqualToString:@"iPad13,17"]) {
+ return @"iPad Air 5";
+ } else if ([identifier isEqualToString:@"iPad14,8"] ||
+ [identifier isEqualToString:@"iPad14,9"]) {
+ return @"iPad Air 11-Inch M2";
+ } else if ([identifier isEqualToString:@"iPad14,10"] ||
+ [identifier isEqualToString:@"iPad14,11"]) {
+ return @"iPad Air 13-Inch M2";
+ } else if ([identifier isEqualToString:@"iPad2,5"] ||
+ [identifier isEqualToString:@"iPad2,6"] ||
+ [identifier isEqualToString:@"iPad2,7"]) {
+ return @"iPad Mini";
+ } else if ([identifier isEqualToString:@"iPad4,4"] ||
+ [identifier isEqualToString:@"iPad4,5"] ||
+ [identifier isEqualToString:@"iPad4,6"]) {
+ return @"iPad Mini 2";
+ } else if ([identifier isEqualToString:@"iPad4,7"] ||
+ [identifier isEqualToString:@"iPad4,8"] ||
+ [identifier isEqualToString:@"iPad4,9"]) {
+ return @"iPad Mini 3";
+ } else if ([identifier isEqualToString:@"iPad5,1"] ||
+ [identifier isEqualToString:@"iPad5,2"]) {
+ return @"iPad Mini 4";
+ } else if ([identifier isEqualToString:@"iPad11,1"] ||
+ [identifier isEqualToString:@"iPad11,2"]) {
+ return @"iPad Mini 5";
+ } else if ([identifier isEqualToString:@"iPad14,1"] ||
+ [identifier isEqualToString:@"iPad14,2"]) {
+ return @"iPad Mini 6";
+ } else if ([identifier isEqualToString:@"iPad6,3"] ||
+ [identifier isEqualToString:@"iPad6,4"]) {
+ return @"iPad Pro 9-Inch";
+ } else if ([identifier isEqualToString:@"iPad6,7"] ||
+ [identifier isEqualToString:@"iPad6,8"]) {
+ return @"iPad Pro 12-Inch";
+ } else if ([identifier isEqualToString:@"iPad7,1"] || [identifier isEqualToString:@"iPad7,2"]) {
+ return @"iPad Pro 12-Inch 2";
+ } else if ([identifier isEqualToString:@"iPad7,3"] || [identifier isEqualToString:@"iPad7,4"]) {
+ return @"iPad Pro 10-Inch";
+ } else if ([identifier isEqualToString:@"iPad8,1"] || [identifier isEqualToString:@"iPad8,2"] ||
+ [identifier isEqualToString:@"iPad8,3"] || [identifier isEqualToString:@"iPad8,4"]) {
+ return @"iPad Pro 11-Inch";
+ } else if ([identifier isEqualToString:@"iPad8,5"] || [identifier isEqualToString:@"iPad8,6"] ||
+ [identifier isEqualToString:@"iPad8,7"] || [identifier isEqualToString:@"iPad8,8"]) {
+ return @"iPad Pro 12-Inch 3";
+ } else if ([identifier isEqualToString:@"iPad8,9"] ||
+ [identifier isEqualToString:@"iPad8,10"]) {
+ return @"iPad Pro 11-Inch 2";
+ } else if ([identifier isEqualToString:@"iPad8,11"] ||
+ [identifier isEqualToString:@"iPad8,12"]) {
+ return @"iPad Pro 12-Inch 4";
+ } else if ([identifier isEqualToString:@"iPad13,4"] ||
+ [identifier isEqualToString:@"iPad13,5"] ||
+ [identifier isEqualToString:@"iPad13,6"] ||
+ [identifier isEqualToString:@"iPad13,7"]) {
+ return @"iPad Pro 11-Inch 3";
+ } else if ([identifier isEqualToString:@"iPad13,8"] ||
+ [identifier isEqualToString:@"iPad13,9"] ||
+ [identifier isEqualToString:@"iPad13,10"] ||
+ [identifier isEqualToString:@"iPad13,11"]) {
+ return @"iPad Pro 12-Inch 5";
+ } else if ([identifier isEqualToString:@"iPad14,3"] ||
+ [identifier isEqualToString:@"iPad14,4"]) {
+ return @"iPad Pro 11-Inch 4";
+ } else if ([identifier isEqualToString:@"iPad14,5"] ||
+ [identifier isEqualToString:@"iPad14,6"]) {
+ return @"iPad Pro 12-Inch 6";
+ } else if ([identifier isEqualToString:@"iPad16,3"] ||
+ [identifier isEqualToString:@"iPad16,4"]) {
+ return @"iPad Pro 11-Inch (M4)";
+ } else if ([identifier isEqualToString:@"iPad16,5"] ||
+ [identifier isEqualToString:@"iPad16,6"]) {
+ return @"iPad Pro 13-Inch (M4)";
+ } else {
+ return @"Unknown device";
+ }
+}
+@end
diff --git a/packages/device_info_plus/device_info_plus/ios/device_info_plus/Sources/device_info_plus/FPPDeviceInfoPlusPlugin.m b/packages/device_info_plus/device_info_plus/ios/device_info_plus/Sources/device_info_plus/FPPDeviceInfoPlusPlugin.m
index 199fd93523..2b495c7c17 100644
--- a/packages/device_info_plus/device_info_plus/ios/device_info_plus/Sources/device_info_plus/FPPDeviceInfoPlusPlugin.m
+++ b/packages/device_info_plus/device_info_plus/ios/device_info_plus/Sources/device_info_plus/FPPDeviceInfoPlusPlugin.m
@@ -3,6 +3,7 @@
// found in the LICENSE file.
#import "./include/device_info_plus/FPPDeviceInfoPlusPlugin.h"
+#import "./include/device_info_plus/DeviceIdentifiers.h"
#import
@implementation FPPDeviceInfoPlusPlugin
@@ -29,17 +30,21 @@ - (void)handleMethodCall:(FlutterMethodCall *)call
isiOSAppOnMac = [NSNumber numberWithBool:[info isiOSAppOnMac]];
}
NSString *machine;
+ NSString *deviceName;
if ([self isDevicePhysical]) {
machine = @(un.machine);
} else {
machine = [info environment][@"SIMULATOR_MODEL_IDENTIFIER"];
}
+ deviceName = [DeviceIdentifiers userKnownDeviceModel:machine];
+
result(@{
@"name" : [device name],
@"systemName" : [device systemName],
@"systemVersion" : [device systemVersion],
@"model" : [device model],
@"localizedModel" : [device localizedModel],
+ @"modelName" : deviceName,
@"identifierForVendor" : [[device identifierForVendor] UUIDString]
?: [NSNull null],
@"isPhysicalDevice" : isPhysicalNumber,
diff --git a/packages/device_info_plus/device_info_plus/ios/device_info_plus/Sources/device_info_plus/include/device_info_plus/DeviceIdentifiers.h b/packages/device_info_plus/device_info_plus/ios/device_info_plus/Sources/device_info_plus/include/device_info_plus/DeviceIdentifiers.h
new file mode 100644
index 0000000000..0f5c8d70ff
--- /dev/null
+++ b/packages/device_info_plus/device_info_plus/ios/device_info_plus/Sources/device_info_plus/include/device_info_plus/DeviceIdentifiers.h
@@ -0,0 +1,13 @@
+//
+// DeviceIdentifiers.h
+// device_info_plus
+//
+// Created by Volodymyr on 06.11.2024.
+//
+#import
+
+@interface DeviceIdentifiers : NSObject
+
++ (NSString *)userKnownDeviceModel:(NSString *)identifier;
+
+@end
diff --git a/packages/device_info_plus/device_info_plus/lib/src/model/ios_device_info.dart b/packages/device_info_plus/device_info_plus/lib/src/model/ios_device_info.dart
index 78ac9aa36a..aaf654a776 100644
--- a/packages/device_info_plus/device_info_plus/lib/src/model/ios_device_info.dart
+++ b/packages/device_info_plus/device_info_plus/lib/src/model/ios_device_info.dart
@@ -15,6 +15,7 @@ class IosDeviceInfo extends BaseDeviceInfo {
required this.systemName,
required this.systemVersion,
required this.model,
+ required this.modelName,
required this.localizedModel,
this.identifierForVendor,
required this.isPhysicalDevice,
@@ -38,10 +39,14 @@ class IosDeviceInfo extends BaseDeviceInfo {
/// https://developer.apple.com/documentation/uikit/uidevice/1620043-systemversion
final String systemVersion;
- /// Device model.
+ /// Device model according to OS
/// https://developer.apple.com/documentation/uikit/uidevice/1620044-model
final String model;
+ /// Commercial or user-known model name
+ /// Examples: `iPhone 16 Pro`, `iPad Pro 11-Inch 3`
+ final String modelName;
+
/// Localized name of the device model.
/// https://developer.apple.com/documentation/uikit/uidevice/1620029-localizedmodel
final String localizedModel;
@@ -68,6 +73,7 @@ class IosDeviceInfo extends BaseDeviceInfo {
systemName: map['systemName'],
systemVersion: map['systemVersion'],
model: map['model'],
+ modelName: map['modelName'],
localizedModel: map['localizedModel'],
identifierForVendor: map['identifierForVendor'],
isPhysicalDevice: map['isPhysicalDevice'],
diff --git a/packages/device_info_plus/device_info_plus/lib/src/model/macos_device_info.dart b/packages/device_info_plus/device_info_plus/lib/src/model/macos_device_info.dart
index 76c5c01f55..7725c5d1de 100644
--- a/packages/device_info_plus/device_info_plus/lib/src/model/macos_device_info.dart
+++ b/packages/device_info_plus/device_info_plus/lib/src/model/macos_device_info.dart
@@ -13,6 +13,7 @@ class MacOsDeviceInfo extends BaseDeviceInfo {
required this.hostName,
required this.arch,
required this.model,
+ required this.modelName,
required this.kernelVersion,
required this.osRelease,
required this.majorVersion,
@@ -34,9 +35,14 @@ class MacOsDeviceInfo extends BaseDeviceInfo {
/// Note, that on Apple Silicon Macs can return `x86_64` if app runs via Rosetta
final String arch;
- /// Device model
+ /// Device model identifier
+ /// Examples: `MacBookPro18,3`, `Mac16,2`.
final String model;
+ /// Device model name
+ /// Examples: `MacBook Pro (16-inch, 2021)`, `iMac (24-inch, 2024)`.
+ final String modelName;
+
/// Machine Kernel version.
/// Examples:
/// `Darwin Kernel Version 15.3.0: Thu Dec 10 18:40:58 PST 2015; root:xnu-3248.30.4~1/RELEASE_X86_64`
@@ -76,6 +82,7 @@ class MacOsDeviceInfo extends BaseDeviceInfo {
hostName: map['hostName'],
arch: map['arch'],
model: map['model'],
+ modelName: map['modelName'],
kernelVersion: map['kernelVersion'],
osRelease: map['osRelease'],
majorVersion: map['majorVersion'],
diff --git a/packages/device_info_plus/device_info_plus/macos/device_info_plus/Sources/device_info_plus/DeviceIdentifiers.swift b/packages/device_info_plus/device_info_plus/macos/device_info_plus/Sources/device_info_plus/DeviceIdentifiers.swift
new file mode 100644
index 0000000000..288808c159
--- /dev/null
+++ b/packages/device_info_plus/device_info_plus/macos/device_info_plus/Sources/device_info_plus/DeviceIdentifiers.swift
@@ -0,0 +1,99 @@
+import Foundation
+
+// Models list is taken from support.apple.com
+// Example of the list with models https://support.apple.com/en-us/102869
+
+func getMacModelName(modelNumber: String) -> String {
+ switch modelNumber {
+ // MacBook models (2015 and later)
+ case "MacBook8,1": return "MacBook (12-inch, 2015)"
+ case "MacBook9,1": return "MacBook (12-inch, 2016)"
+ case "MacBook10,1": return "MacBook (12-inch, 2017)"
+
+ // MacBook Air models (2013 and later)
+ case "MacBookAir6,1": return "MacBook Air (11-inch, 2013)"
+ case "MacBookAir6,2": return "MacBook Air (13-inch, 2013)"
+ case "MacBookAir7,1": return "MacBook Air (11-inch, 2015)"
+ case "MacBookAir7,2": return "MacBook Air (13-inch, 2015-2017)"
+ case "MacBookAir8,1": return "MacBook Air (13-inch, 2018)"
+ case "MacBookAir8,2": return "MacBook Air (13-inch, 2019)"
+ case "MacBookAir9,1": return "MacBook Air (13-inch, 2020)"
+ case "MacBookAir10,1": return "MacBook Air (13-inch, 2020)"
+ case "Mac14,2": return "MacBook Air (13-inch, 2022)"
+ case "Mac14,15": return "MacBook Air (15-inch, 2023)"
+ case "Mac15,12": return "MacBook Air (13-inch, 2024)"
+ case "Mac15,13": return "MacBook Air (15-inch, 2024)"
+
+ // MacBook Pro models (2012 and later)
+ case "MacBookPro10,1": return "MacBook Pro (15-inch, 2012-2013)"
+ case "MacBookPro10,2": return "MacBook Pro (13-inch, 2012-2013)"
+ case "MacBookPro11,1": return "MacBook Pro (13-inch, 2013-2014)"
+ case "MacBookPro11,2", "MacBookPro11,3": return "MacBook Pro (15-inch, 2013-2014)"
+ case "MacBookPro11,4", "MacBookPro11,5": return "MacBook Pro (15-inch, 2015)"
+ case "MacBookPro12,1": return "MacBook Pro (13-inch, 2015)"
+ case "MacBookPro13,1": return "MacBook Pro (13-inch, 2016)"
+ case "MacBookPro13,2": return "MacBook Pro (13-inch, 2016)"
+ case "MacBookPro13,3": return "MacBook Pro (15-inch, 2016)"
+ case "MacBookPro14,1": return "MacBook Pro (13-inch, 2017)"
+ case "MacBookPro14,2": return "MacBook Pro (13-inch, 2017)"
+ case "MacBookPro14,3": return "MacBook Pro (15-inch, 2017)"
+ case "MacBookPro15,1", "MacBookPro15,3": return "MacBook Pro (15-inch, 2018-2019)"
+ case "MacBookPro15,2": return "MacBook Pro (13-inch, 2018-2019)"
+ case "MacBookPro15,4": return "MacBook Pro (13-inch, 2019)"
+ case "MacBookPro16,1", "MacBookPro16,4": return "MacBook Pro (16-inch, 2019)"
+ case "MacBookPro16,2": return "MacBook Pro (13-inch, 2019)"
+ case "MacBookPro16,3": return "MacBook Pro (13-inch, 2020)"
+ case "MacBookPro17,1": return "MacBook Pro (13-inch, 2020)"
+ case "MacBookPro18,1": return "MacBook Pro (14-inch, 2021)"
+ case "MacBookPro18,2": return "MacBook Pro (16-inch, 2021)"
+ case "MacBookPro18,3": return "MacBook Pro (16-inch, 2021)"
+ case "Mac14,5", "Mac14,9": return "MacBook Pro (14-inch, 2023)"
+ case "Mac14,6", "Mac14,10": return "MacBook Pro (14-inch, 2023)"
+ case "Mac14,7": return "MacBook Pro (13-inch, 2022)"
+ case "Mac15,3": return "MacBook Pro (14-inch, 2023)"
+ case "Mac15,6", "Mac15,8", "Mac15.10": return "MacBook Pro (14-inch, 2023)"
+ case "Mac15,7", "Mac15,9", "Mac15.11": return "MacBook Pro (16-inch, 2023)"
+
+ // iMac models (2013 and later)
+ case "iMac13,1": return "iMac (21.5-inch, 2013)"
+ case "iMac13,2": return "iMac (27-inch, 2013)"
+ case "iMac14,1": return "iMac (21.5-inch, 2014)"
+ case "iMac14,2": return "iMac (27-inch, 2014)"
+ case "iMac14,4": return "iMac (21.5-inch, 2014)"
+ case "iMac15,1": return "iMac (27-inch, 2014-2015)"
+ case "iMac16,1","iMac16,2": return "iMac (21.5-inch, 2015)"
+ case "iMac17,1": return "iMac (27-inch, 2015)"
+ case "iMac18,1": return "iMac (21.5-inch, 2017)"
+ case "iMac18,2": return "iMac (21.5-inch, 2017)"
+ case "iMac18,3": return "iMac (27-inch, 2017)"
+ case "iMac19,1": return "iMac (27-inch, 2019)"
+ case "iMac19,2": return "iMac (21.5-inch, 2019)"
+ case "iMac20,1", "iMac20,2": return "iMac (27-inch, 2020)"
+ case "iMac21,1", "iMac21,2": return "iMac (24-inch, 2021)"
+ case "Mac15,4", "Mac15,5": return "iMac (24-inch, 2023)"
+ case "Mac16,2", "Mac16,3": return "iMac (24-inch, 2024)"
+
+ // Mac mini models (2012 and later)
+ case "MacMini6,1", "MacMini6,2": return "Mac mini (2012)"
+ case "MacMini7,1": return "Mac mini (2014)"
+ case "MacMini8,1": return "Mac mini (2018)"
+ case "MacMini9,1": return "Mac mini (2020)"
+ case "Mac14,12": return "Mac mini (2023)"
+ case "Mac14,3": return "Mac mini (2023)"
+ case "Mac16,15", "Mac16,10": return "Mac mini (2024)"
+
+ // Mac Pro models (2013 and later)
+ case "MacPro6,1": return "Mac Pro (Late 2013)"
+ case "MacPro7,1": return "Mac Pro (2019)"
+ case "Mac14,8": return "Mac Pro (2023)"
+
+ // iMac Pro
+ case "iMacPro1,1": return "iMac Pro (2017)"
+
+ // Mac Studio (2022 and newer)
+ case "Mac13,1", "Mac13,2": return "Mac Studio (2022)"
+ case "Mac14,13", "Mac14,14": return "Mac Studio (2023)"
+
+ default: return "Unknown Model"
+ }
+}
diff --git a/packages/device_info_plus/device_info_plus/macos/device_info_plus/Sources/device_info_plus/DeviceInfoPlusMacosPlugin.swift b/packages/device_info_plus/device_info_plus/macos/device_info_plus/Sources/device_info_plus/DeviceInfoPlusMacosPlugin.swift
index 8dbeb74203..a1f6823606 100644
--- a/packages/device_info_plus/device_info_plus/macos/device_info_plus/Sources/device_info_plus/DeviceInfoPlusMacosPlugin.swift
+++ b/packages/device_info_plus/device_info_plus/macos/device_info_plus/Sources/device_info_plus/DeviceInfoPlusMacosPlugin.swift
@@ -22,6 +22,7 @@ public class DeviceInfoPlusMacosPlugin: NSObject, FlutterPlugin {
let hostName = Sysctl.osType
let arch = Sysctl.machine
let model = Sysctl.model
+ let modelName = getMacModelName(modelNumber: Sysctl.model)
let kernelVersion = Sysctl.version
let osRelease = ProcessInfo.processInfo.operatingSystemVersionString
let osVersion = ProcessInfo.processInfo.operatingSystemVersion;
@@ -38,6 +39,7 @@ public class DeviceInfoPlusMacosPlugin: NSObject, FlutterPlugin {
"hostName": hostName,
"arch": arch,
"model": model,
+ "modelName": modelName,
"kernelVersion": kernelVersion,
"osRelease": osRelease,
"majorVersion": majorVersion,
diff --git a/packages/device_info_plus/device_info_plus/test/model/ios_device_info_test.dart b/packages/device_info_plus/device_info_plus/test/model/ios_device_info_test.dart
index 1a0a494c8e..158a17afda 100644
--- a/packages/device_info_plus/device_info_plus/test/model/ios_device_info_test.dart
+++ b/packages/device_info_plus/device_info_plus/test/model/ios_device_info_test.dart
@@ -17,6 +17,7 @@ void main() {
iosDeviceInfoMap = {
'name': 'name',
'model': 'model',
+ 'modelName': 'modelName',
'utsname': iosUtsnameMap,
'systemName': 'systemName',
'isPhysicalDevice': true,
@@ -32,6 +33,7 @@ void main() {
test('fromMap should return $IosDeviceInfo with correct values', () {
expect(iosDeviceInfo.name, 'name');
expect(iosDeviceInfo.model, 'model');
+ expect(iosDeviceInfo.modelName, 'modelName');
expect(iosDeviceInfo.isPhysicalDevice, isTrue);
expect(iosDeviceInfo.isiOSAppOnMac, isTrue);
expect(iosDeviceInfo.systemName, 'systemName');
diff --git a/packages/device_info_plus/device_info_plus/test/model/macos_device_info_test.dart b/packages/device_info_plus/device_info_plus/test/model/macos_device_info_test.dart
index 0f466608e5..ac196762e6 100644
--- a/packages/device_info_plus/device_info_plus/test/model/macos_device_info_test.dart
+++ b/packages/device_info_plus/device_info_plus/test/model/macos_device_info_test.dart
@@ -8,7 +8,8 @@ void main() {
group('fromMap | data', () {
const macosDeviceInfoMap = {
'arch': 'arch',
- 'model': 'model',
+ 'model': 'Mac16,2',
+ 'modelName': 'iMac (24-inch, 2024)',
'activeCPUs': 4,
'memorySize': 16,
'cpuFrequency': 2,
@@ -24,9 +25,9 @@ void main() {
test('fromMap should return $MacOsDeviceInfo with correct values', () {
final macosDeviceInfo = MacOsDeviceInfo.fromMap(macosDeviceInfoMap);
-
expect(macosDeviceInfo.arch, 'arch');
- expect(macosDeviceInfo.model, 'model');
+ expect(macosDeviceInfo.model, 'Mac16,2');
+ expect(macosDeviceInfo.modelName, 'iMac (24-inch, 2024)');
expect(macosDeviceInfo.activeCPUs, 4);
expect(macosDeviceInfo.memorySize, 16);
expect(macosDeviceInfo.cpuFrequency, 2);