Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(device_info_plus)!: refactor of device_info_plus platform implementation #1293

Merged
merged 14 commits into from
Oct 27, 2022
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ internal class MethodCallHandlerImpl(
) : MethodCallHandler {

override fun onMethodCall(call: MethodCall, result: MethodChannel.Result) {
if (call.method.equals("getAndroidDeviceInfo")) {
if (call.method.equals("getDeviceInfo")) {
val build: MutableMap<String, Any> = HashMap()

build["board"] = Build.BOARD
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ + (void)registerWithRegistrar:(NSObject<FlutterPluginRegistrar> *)registrar {

- (void)handleMethodCall:(FlutterMethodCall *)call
result:(FlutterResult)result {
if ([@"getIosDeviceInfo" isEqualToString:call.method]) {
if ([@"getDeviceInfo" isEqualToString:call.method]) {
UIDevice *device = [UIDevice currentDevice];
struct utsname un;
uname(&un);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,20 +6,25 @@ import 'dart:async';
import 'dart:io';

import 'package:device_info_plus_platform_interface/device_info_plus_platform_interface.dart';
import 'package:device_info_plus_platform_interface/model/base_device_info.dart';
import 'package:flutter/foundation.dart';

import 'src/model/android_device_info.dart';
import 'src/model/ios_device_info.dart';
import 'src/model/linux_device_info.dart';
import 'src/model/macos_device_info.dart';
import 'src/model/web_browser_info.dart';
import 'src/model/windows_device_info.dart';

export 'package:device_info_plus_platform_interface/device_info_plus_platform_interface.dart'
show
AndroidBuildVersion,
AndroidDeviceInfo,
BaseDeviceInfo,
IosDeviceInfo,
IosUtsname,
LinuxDeviceInfo,
MacOsDeviceInfo,
WindowsDeviceInfo,
WebBrowserInfo,
BrowserName;
show BaseDeviceInfo;

export 'src/model/android_device_info.dart';
export 'src/model/ios_device_info.dart';
export 'src/model/linux_device_info.dart';
export 'src/model/macos_device_info.dart';
export 'src/model/web_browser_info.dart';
export 'src/model/windows_device_info.dart';

export 'src/device_info_plus_linux.dart';
export 'src/device_info_plus_windows.dart'
Expand All @@ -45,64 +50,50 @@ class DeviceInfoPlugin {
///
/// See: https://developer.android.com/reference/android/os/Build.html
Future<AndroidDeviceInfo> get androidInfo async =>
_cachedAndroidDeviceInfo ??= await _platform.androidInfo();
_cachedAndroidDeviceInfo ??=
AndroidDeviceInfo.fromMap((await _platform.deviceInfo()).data);

/// This information does not change from call to call. Cache it.
IosDeviceInfo? _cachedIosDeviceInfo;

/// Information derived from `UIDevice`.
///
/// See: https://developer.apple.com/documentation/uikit/uidevice
Future<IosDeviceInfo> get iosInfo async =>
_cachedIosDeviceInfo ??= await _platform.iosInfo();
Future<IosDeviceInfo> get iosInfo async => _cachedIosDeviceInfo ??=
IosDeviceInfo.fromMap((await _platform.deviceInfo()).data);

/// This information does not change from call to call. Cache it.
LinuxDeviceInfo? _cachedLinuxDeviceInfo;

/// Information derived from `/etc/os-release`.
///
/// See: https://www.freedesktop.org/software/systemd/man/os-release.html
Future<LinuxDeviceInfo> get linuxInfo async =>
_cachedLinuxDeviceInfo ??= await _platform.linuxInfo();
Future<LinuxDeviceInfo> get linuxInfo async => _cachedLinuxDeviceInfo ??=
await _platform.deviceInfo() as LinuxDeviceInfo;

/// This information does not change from call to call. Cache it.
WebBrowserInfo? _cachedWebBrowserInfo;

/// Information derived from `Navigator`.
Future<WebBrowserInfo> get webBrowserInfo async =>
_cachedWebBrowserInfo ??= await _platform.webBrowserInfo();
_cachedWebBrowserInfo ??= await _platform.deviceInfo() as WebBrowserInfo;

/// This information does not change from call to call. Cache it.
MacOsDeviceInfo? _cachedMacosDeviceInfo;

/// Returns device information for macos. Information sourced from Sysctl.
Future<MacOsDeviceInfo> get macOsInfo async =>
_cachedMacosDeviceInfo ??= await _platform.macosInfo();
Future<MacOsDeviceInfo> get macOsInfo async => _cachedMacosDeviceInfo ??=
MacOsDeviceInfo.fromMap((await _platform.deviceInfo()).data);

WindowsDeviceInfo? _cachedWindowsDeviceInfo;

/// Returns device information for Windows.
Future<WindowsDeviceInfo> get windowsInfo async =>
_cachedWindowsDeviceInfo ??= await _platform.windowsInfo()!;
_cachedWindowsDeviceInfo ??=
await _platform.deviceInfo() as WindowsDeviceInfo;

/// Returns device information for the current platform.
Future<BaseDeviceInfo> get deviceInfo async {
if (kIsWeb) {
return webBrowserInfo;
} else {
if (Platform.isAndroid) {
return androidInfo;
} else if (Platform.isIOS) {
return iosInfo;
} else if (Platform.isLinux) {
return linuxInfo;
} else if (Platform.isMacOS) {
return macOsInfo;
} else if (Platform.isWindows) {
return windowsInfo;
}
}

throw UnsupportedError('Unsupported platform');
return _platform.deviceInfo();
}
}
Original file line number Diff line number Diff line change
@@ -1,10 +1,14 @@
import 'dart:async';

import 'package:device_info_plus/device_info_plus.dart';
import 'package:device_info_plus_platform_interface/device_info_plus_platform_interface.dart';
import 'package:device_info_plus_platform_interface/model/base_device_info.dart';
import 'package:file/file.dart';
import 'package:file/local.dart';
import 'package:meta/meta.dart';

import 'model/linux_device_info.dart';

/// See [DeviceInfoPlatform]
class DeviceInfoPlusLinuxPlugin extends DeviceInfoPlatform {
/// Register this dart class as the platform implementation for linux
Expand All @@ -20,10 +24,14 @@ class DeviceInfoPlusLinuxPlugin extends DeviceInfoPlatform {
: _fileSystem = fileSystem ?? const LocalFileSystem();

@override
Future<LinuxDeviceInfo> linuxInfo() async {
Future<BaseDeviceInfo> deviceInfo() async {
return _cache ??= await _getInfo();
}

Future<LinuxDeviceInfo> linuxInfo() async {
return (await deviceInfo()) as LinuxDeviceInfo;
}

Future<LinuxDeviceInfo> _getInfo() async {
final os = await _getOsRelease() ?? {};
final lsb = await _getLsbRelease() ?? {};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ import 'dart:html' as html show window, Navigator;
import 'package:device_info_plus_platform_interface/device_info_plus_platform_interface.dart';
import 'package:flutter_web_plugins/flutter_web_plugins.dart';

import 'model/web_browser_info.dart';

/// The web implementation of the BatteryPlusPlatform of the BatteryPlus plugin.
class DeviceInfoPlusWebPlugin extends DeviceInfoPlatform {
/// Constructs a DeviceInfoPlusPlugin.
Expand Down Expand Up @@ -42,3 +44,9 @@ class DeviceInfoPlusWebPlugin extends DeviceInfoPlatform {
);
}
}

extension WebDeviceInfoPlugin on DeviceInfoPlatform {
Future<WebBrowserInfo> webInfo() async {
return deviceInfo as WebBrowserInfo;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@ import 'package:ffi/ffi.dart';
import 'package:meta/meta.dart';
import 'package:win32/win32.dart';

import 'model/windows_device_info.dart';

/// The Windows implementation of [DeviceInfoPlatform].
class DeviceInfoPlusWindowsPlugin extends DeviceInfoPlatform {
/// Register this dart class as the platform implementation for windows
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,14 @@
// found in the LICENSE file.

import 'dart:math' as math show sqrt;
import 'base_device_info.dart';
import 'package:device_info_plus_platform_interface/model/base_device_info.dart';

/// Information derived from `android.os.Build`.
///
/// See: https://developer.android.com/reference/android/os/Build.html
class AndroidDeviceInfo implements BaseDeviceInfo {
/// Android device Info class.
AndroidDeviceInfo({
class AndroidDeviceInfo extends BaseDeviceInfo {
AndroidDeviceInfo._({
required Map<String, dynamic> data,
Comment on lines +12 to +13
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This private constructor and the fromMap method could be refactored further, probably, but I didn't do it yet. At least I marked this constructor as private now, which shouldn't be used outside the plugin.

required this.version,
required this.board,
required this.bootloader,
Expand All @@ -35,7 +35,8 @@ class AndroidDeviceInfo implements BaseDeviceInfo {
}) : supported32BitAbis = List<String>.unmodifiable(supported32BitAbis),
supported64BitAbis = List<String>.unmodifiable(supported64BitAbis),
supportedAbis = List<String>.unmodifiable(supportedAbis),
systemFeatures = List<String>.unmodifiable(systemFeatures);
systemFeatures = List<String>.unmodifiable(systemFeatures),
super(data);

/// Android operating system version values derived from `android.os.Build.VERSION`.
final AndroidBuildVersion version;
Expand Down Expand Up @@ -116,38 +117,10 @@ class AndroidDeviceInfo implements BaseDeviceInfo {
/// Information about the current android display.
final AndroidDisplayMetrics displayMetrics;

/// Serializes [AndroidDeviceInfo] to map.
@Deprecated('[toMap] method will be discontinued')
@override
Map<String, dynamic> toMap() {
return {
'id': id,
Comment on lines -119 to -124
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The original toMap disappears and now instead the data returned by the platform channel is returned. Rather than re-creating the map out of the class data, we return the same data the Android code created, which should be 100% serializable.

'host': host,
'tags': tags,
'type': type,
'model': model,
'board': board,
'brand': brand,
'device': device,
'product': product,
'display': display,
'hardware': hardware,
'bootloader': bootloader,
'version': version.toMap(),
'fingerprint': fingerprint,
'manufacturer': manufacturer,
'supportedAbis': supportedAbis,
'systemFeatures': systemFeatures,
'isPhysicalDevice': isPhysicalDevice,
'supported32BitAbis': supported32BitAbis,
'supported64BitAbis': supported64BitAbis,
'displayMetrics': displayMetrics.toMap(),
};
}

/// Deserializes from the message received from [_kChannel].
static AndroidDeviceInfo fromMap(Map<String, dynamic> map) {
return AndroidDeviceInfo(
return AndroidDeviceInfo._(
data: map,
version: AndroidBuildVersion._fromMap(
map['version']?.cast<String, dynamic>() ?? {}),
board: map['board'],
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,15 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

import 'base_device_info.dart';
import 'package:device_info_plus_platform_interface/model/base_device_info.dart';

/// Information derived from `UIDevice`.
///
/// See: https://developer.apple.com/documentation/uikit/uidevice
class IosDeviceInfo implements BaseDeviceInfo {
class IosDeviceInfo extends BaseDeviceInfo {
/// IOS device info class.
const IosDeviceInfo({
IosDeviceInfo._({
required Map<String, dynamic> data,
this.name,
this.systemName,
this.systemVersion,
Expand All @@ -18,7 +19,7 @@ class IosDeviceInfo implements BaseDeviceInfo {
this.identifierForVendor,
required this.isPhysicalDevice,
required this.utsname,
});
}) : super(data);

/// Device name.
final String? name;
Expand Down Expand Up @@ -46,7 +47,8 @@ class IosDeviceInfo implements BaseDeviceInfo {

/// Deserializes from the map message received from [_kChannel].
static IosDeviceInfo fromMap(Map<String, dynamic> map) {
return IosDeviceInfo(
return IosDeviceInfo._(
data: map,
name: map['name'],
systemName: map['systemName'],
systemVersion: map['systemVersion'],
Expand All @@ -58,22 +60,6 @@ class IosDeviceInfo implements BaseDeviceInfo {
IosUtsname._fromMap(map['utsname']?.cast<String, dynamic>() ?? {}),
);
}

/// Serializes [IosDeviceInfo] to a map.
@Deprecated('[toMap] method will be discontinued')
@override
Map<String, dynamic> toMap() {
return {
'name': name,
'model': model,
'systemName': systemName,
'utsname': utsname._toMap(),
'systemVersion': systemVersion,
'localizedModel': localizedModel,
'identifierForVendor': identifierForVendor,
'isPhysicalDevice': isPhysicalDevice.toString(),
};
}
}

/// Information derived from `utsname`.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

import 'base_device_info.dart';
import 'package:device_info_plus_platform_interface/model/base_device_info.dart';

/// Device information for a Linux system.
///
Expand Down Expand Up @@ -139,8 +139,11 @@ class LinuxDeviceInfo implements BaseDeviceInfo {
/// decoded from hexadecimal, this corresponds to a 16-byte/128-bit value.
final String? machineId;

/// Serializes [LinuxDeviceInfo] to a map.
@Deprecated('[toMap] method will be discontinued')
@override
// ignore: deprecated_member_use_from_same_package
Map<String, dynamic> get data => toMap();

@Deprecated('Use [data] getter instead')
Comment on lines +142 to +146
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

With dart plugins, they can implement the BaseDeviceInfo directly but still need to provide the data. At the moment, there's no warranty that the data is serializable, but that's out of scope for this PR.

@override
Map<String, dynamic> toMap() {
return {
Expand Down
Loading