Skip to content

Commit 160a018

Browse files
authored
feat(device_info_plus): add ram information (#3535)
1 parent 0a19d46 commit 160a018

File tree

8 files changed

+81
-4
lines changed

8 files changed

+81
-4
lines changed

packages/device_info_plus/device_info_plus/android/src/main/kotlin/dev/fluttercommunity/plus/device_info/MethodCallHandlerImpl.kt

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,11 +5,10 @@ import android.content.ContentResolver
55
import android.content.pm.FeatureInfo
66
import android.content.pm.PackageManager
77
import android.os.Build
8+
import android.provider.Settings
89
import io.flutter.plugin.common.MethodCall
910
import io.flutter.plugin.common.MethodChannel
1011
import io.flutter.plugin.common.MethodChannel.MethodCallHandler
11-
import kotlin.collections.HashMap
12-
import android.provider.Settings
1312

1413
/**
1514
* The implementation of [MethodChannel.MethodCallHandler] for the plugin. Responsible for
@@ -68,7 +67,13 @@ internal class MethodCallHandlerImpl(
6867
version["release"] = Build.VERSION.RELEASE
6968
version["sdkInt"] = Build.VERSION.SDK_INT
7069
build["version"] = version
71-
build["isLowRamDevice"] = activityManager.isLowRamDevice
70+
71+
val memoryInfo: ActivityManager.MemoryInfo = ActivityManager.MemoryInfo()
72+
activityManager.getMemoryInfo(memoryInfo)
73+
build["isLowRamDevice"] = memoryInfo.lowMemory
74+
build["physicalRamSize"] = memoryInfo.totalMem / 1048576L // Mb
75+
build["availableRamSize"] = memoryInfo.availMem / 1048576L // Mb
76+
7277
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
7378
build["serialNumber"] = try {
7479
Build.getSerial()

packages/device_info_plus/device_info_plus/example/lib/main.dart

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -104,6 +104,8 @@ class _MyAppState extends State<MyApp> {
104104
'systemFeatures': build.systemFeatures,
105105
'serialNumber': build.serialNumber,
106106
'isLowRamDevice': build.isLowRamDevice,
107+
'physicalRamSize': build.physicalRamSize,
108+
'availableRamSize': build.availableRamSize,
107109
};
108110
}
109111

@@ -118,6 +120,8 @@ class _MyAppState extends State<MyApp> {
118120
'identifierForVendor': data.identifierForVendor,
119121
'isPhysicalDevice': data.isPhysicalDevice,
120122
'isiOSAppOnMac': data.isiOSAppOnMac,
123+
'physicalRamSize': data.physicalRamSize,
124+
'availableRamSize': data.availableRamSize,
121125
'utsname.sysname:': data.utsname.sysname,
122126
'utsname.nodename:': data.utsname.nodename,
123127
'utsname.release:': data.utsname.release,

packages/device_info_plus/device_info_plus/ios/device_info_plus/Sources/device_info_plus/FPPDeviceInfoPlusPlugin.m

Lines changed: 25 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44

55
#import "./include/device_info_plus/FPPDeviceInfoPlusPlugin.h"
66
#import "./include/device_info_plus/DeviceIdentifiers.h"
7+
#import <mach/mach.h>
78
#import <sys/utsname.h>
89

910
@implementation FPPDeviceInfoPlusPlugin
@@ -38,6 +39,9 @@ - (void)handleMethodCall:(FlutterMethodCall *)call
3839
}
3940
deviceName = [DeviceIdentifiers userKnownDeviceModel:machine];
4041

42+
NSNumber *physicalRamSize = @([NSProcessInfo processInfo].physicalMemory / 1048576); // Mb
43+
NSNumber *availableRamSize = @([self availableMemoryInbMB]);
44+
4145
result(@{
4246
@"name" : [device name],
4347
@"systemName" : [device systemName],
@@ -49,6 +53,8 @@ - (void)handleMethodCall:(FlutterMethodCall *)call
4953
?: [NSNull null],
5054
@"isPhysicalDevice" : isPhysicalNumber,
5155
@"isiOSAppOnMac" : isiOSAppOnMac,
56+
@"physicalRamSize": physicalRamSize,
57+
@"availableRamSize": availableRamSize,
5258
@"utsname" : @{
5359
@"sysname" : @(un.sysname),
5460
@"nodename" : @(un.nodename),
@@ -62,7 +68,25 @@ - (void)handleMethodCall:(FlutterMethodCall *)call
6268
}
6369
}
6470

65-
// return value is false if code is run on a simulator
71+
// Return available memory in megabytes
72+
- (int)availableMemoryInbMB {
73+
mach_port_t host_port = mach_host_self();
74+
mach_msg_type_number_t host_size = sizeof(vm_statistics_data_t) / sizeof(integer_t);
75+
76+
vm_size_t page_size;
77+
host_page_size(host_port, &page_size);
78+
79+
vm_statistics_data_t vm_stat;
80+
if (host_statistics(host_port, HOST_VM_INFO, (host_info_t)&vm_stat, &host_size) != KERN_SUCCESS) {
81+
// Failed to fetch vm statistics
82+
return -1;
83+
}
84+
85+
natural_t mem_free = vm_stat.free_count * page_size;
86+
return mem_free / 1048576;
87+
}
88+
89+
// Return value is false if code is run on a simulator
6690
- (BOOL)isDevicePhysical {
6791
BOOL isPhysicalDevice = NO;
6892
#if TARGET_OS_SIMULATOR

packages/device_info_plus/device_info_plus/lib/src/model/android_device_info.dart

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,8 @@ class AndroidDeviceInfo extends BaseDeviceInfo {
3434
required List<String> systemFeatures,
3535
required this.serialNumber,
3636
required this.isLowRamDevice,
37+
required this.physicalRamSize,
38+
required this.availableRamSize,
3739
}) : supported32BitAbis = List<String>.unmodifiable(supported32BitAbis),
3840
supported64BitAbis = List<String>.unmodifiable(supported64BitAbis),
3941
supportedAbis = List<String>.unmodifiable(supportedAbis),
@@ -146,6 +148,16 @@ class AndroidDeviceInfo extends BaseDeviceInfo {
146148
/// `true` if the application is running on a low-RAM device, `false` otherwise.
147149
final bool isLowRamDevice;
148150

151+
/// Total physical RAM size of the device in megabytes
152+
///
153+
/// https://developer.android.com/reference/android/app/ActivityManager.MemoryInfo#totalMem
154+
final int physicalRamSize;
155+
156+
/// Current unallocated RAM size of the device in megabytes
157+
///
158+
/// https://developer.android.com/reference/android/app/ActivityManager.MemoryInfo#availMem
159+
final int availableRamSize;
160+
149161
/// Deserializes from the message received from [_kChannel].
150162
static AndroidDeviceInfo fromMap(Map<String, dynamic> map) {
151163
return AndroidDeviceInfo._(
@@ -174,6 +186,8 @@ class AndroidDeviceInfo extends BaseDeviceInfo {
174186
systemFeatures: _fromList(map['systemFeatures'] ?? []),
175187
serialNumber: map['serialNumber'],
176188
isLowRamDevice: map['isLowRamDevice'],
189+
physicalRamSize: map['physicalRamSize'],
190+
availableRamSize: map['availableRamSize'],
177191
);
178192
}
179193

@@ -203,6 +217,8 @@ class AndroidDeviceInfo extends BaseDeviceInfo {
203217
required List<String> systemFeatures,
204218
required String serialNumber,
205219
required bool isLowRamDevice,
220+
required int physicalRamSize,
221+
required int availableRamSize,
206222
}) {
207223
final Map<String, dynamic> data = {
208224
'version': {
@@ -236,6 +252,8 @@ class AndroidDeviceInfo extends BaseDeviceInfo {
236252
'systemFeatures': systemFeatures,
237253
'serialNumber': serialNumber,
238254
'isLowRamDevice': isLowRamDevice,
255+
'physicalRamSize': physicalRamSize,
256+
'availableRamSize': availableRamSize,
239257
};
240258

241259
return AndroidDeviceInfo._(
@@ -263,6 +281,8 @@ class AndroidDeviceInfo extends BaseDeviceInfo {
263281
systemFeatures: _fromList(systemFeatures),
264282
serialNumber: serialNumber,
265283
isLowRamDevice: isLowRamDevice,
284+
physicalRamSize: physicalRamSize,
285+
availableRamSize: availableRamSize,
266286
);
267287
}
268288

packages/device_info_plus/device_info_plus/lib/src/model/ios_device_info.dart

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,8 @@ class IosDeviceInfo extends BaseDeviceInfo {
2020
required this.localizedModel,
2121
this.identifierForVendor,
2222
required this.isPhysicalDevice,
23+
required this.physicalRamSize,
24+
required this.availableRamSize,
2325
required this.isiOSAppOnMac,
2426
required this.utsname,
2527
}) : super(data);
@@ -59,6 +61,12 @@ class IosDeviceInfo extends BaseDeviceInfo {
5961
/// `false` if the application is running in a simulator, `true` otherwise.
6062
final bool isPhysicalDevice;
6163

64+
/// Total physical RAM size of the device in megabytes
65+
final int physicalRamSize;
66+
67+
/// Current unallocated RAM size of the device in megabytes
68+
final int availableRamSize;
69+
6270
/// that indicates whether the process is an iPhone or iPad app running on a Mac.
6371
/// https://developer.apple.com/documentation/foundation/nsprocessinfo/3608556-iosapponmac
6472
final bool isiOSAppOnMac;
@@ -78,6 +86,8 @@ class IosDeviceInfo extends BaseDeviceInfo {
7886
localizedModel: map['localizedModel'],
7987
identifierForVendor: map['identifierForVendor'],
8088
isPhysicalDevice: map['isPhysicalDevice'],
89+
physicalRamSize: map['physicalRamSize'],
90+
availableRamSize: map['availableRamSize'],
8191
isiOSAppOnMac: map['isiOSAppOnMac'],
8292
utsname:
8393
IosUtsname._fromMap(map['utsname']?.cast<String, dynamic>() ?? {}),
@@ -96,6 +106,8 @@ class IosDeviceInfo extends BaseDeviceInfo {
96106
String? identifierForVendor,
97107
required bool isPhysicalDevice,
98108
required bool isiOSAppOnMac,
109+
required int physicalRamSize,
110+
required int availableRamSize,
99111
required IosUtsname utsname,
100112
}) {
101113
final Map<String, dynamic> data = {
@@ -108,6 +120,8 @@ class IosDeviceInfo extends BaseDeviceInfo {
108120
'identifierForVendor': identifierForVendor,
109121
'isPhysicalDevice': isPhysicalDevice,
110122
'isiOSAppOnMac': isiOSAppOnMac,
123+
'physicalRamSize': physicalRamSize,
124+
'availableRamSize': availableRamSize,
111125
'utsname': {
112126
'sysname': utsname.sysname,
113127
'nodename': utsname.nodename,
@@ -127,6 +141,8 @@ class IosDeviceInfo extends BaseDeviceInfo {
127141
identifierForVendor: identifierForVendor,
128142
isPhysicalDevice: isPhysicalDevice,
129143
isiOSAppOnMac: isiOSAppOnMac,
144+
physicalRamSize: physicalRamSize,
145+
availableRamSize: availableRamSize,
130146
utsname: utsname,
131147
);
132148
}

packages/device_info_plus/device_info_plus/test/model/android_device_info_fake.dart

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,4 +39,6 @@ const _fakeAndroidDeviceInfo = <String, dynamic>{
3939
'supported32BitAbis': _fakeSupported32BitAbis,
4040
'serialNumber': 'SERIAL',
4141
'isLowRamDevice': false,
42+
'physicalRamSize': 8192,
43+
'availableRamSize': 4096,
4244
};

packages/device_info_plus/device_info_plus/test/model/android_device_info_test.dart

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,8 @@ void main() {
4040
expect(androidDeviceInfo.version.securityPatch, 'securityPatch');
4141
expect(androidDeviceInfo.serialNumber, 'SERIAL');
4242
expect(androidDeviceInfo.isLowRamDevice, false);
43+
expect(androidDeviceInfo.physicalRamSize, 8192);
44+
expect(androidDeviceInfo.availableRamSize, 4096);
4345
});
4446

4547
test('toMap should return map with correct key and map', () {

packages/device_info_plus/device_info_plus/test/model/ios_device_info_test.dart

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,8 @@ void main() {
2222
'systemName': 'systemName',
2323
'isPhysicalDevice': true,
2424
'isiOSAppOnMac': true,
25+
'physicalRamSize': 8192,
26+
'availableRamSize': 4096,
2527
'systemVersion': 'systemVersion',
2628
'localizedModel': 'localizedModel',
2729
'identifierForVendor': 'identifierForVendor',
@@ -36,6 +38,8 @@ void main() {
3638
expect(iosDeviceInfo.modelName, 'modelName');
3739
expect(iosDeviceInfo.isPhysicalDevice, isTrue);
3840
expect(iosDeviceInfo.isiOSAppOnMac, isTrue);
41+
expect(iosDeviceInfo.physicalRamSize, 8192);
42+
expect(iosDeviceInfo.availableRamSize, 4096);
3943
expect(iosDeviceInfo.systemName, 'systemName');
4044
expect(iosDeviceInfo.systemVersion, 'systemVersion');
4145
expect(iosDeviceInfo.localizedModel, 'localizedModel');

0 commit comments

Comments
 (0)