-
Notifications
You must be signed in to change notification settings - Fork 9.8k
[device_info_platform_interface] handle null value from method channel #3609
Changes from 10 commits
6e9e671
9ba17a7
c389a6a
a9f0a0a
c6a15a8
7b5658b
fefc6db
f69f03e
dedd740
3d351f1
d7a8a6f
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -38,39 +38,63 @@ class AndroidDeviceInfo { | |
final AndroidBuildVersion version; | ||
|
||
/// The name of the underlying board, like "goldfish". | ||
/// | ||
/// The value is an empty String if it is not available. | ||
final String board; | ||
|
||
/// The system bootloader version number. | ||
/// | ||
/// The value is an empty String if it is not available. | ||
final String bootloader; | ||
|
||
/// The consumer-visible brand with which the product/hardware will be associated, if any. | ||
/// | ||
/// The value is an empty String if it is not available. | ||
final String brand; | ||
|
||
/// The name of the industrial design. | ||
/// | ||
/// The value is an empty String if it is not available. | ||
final String device; | ||
|
||
/// A build ID string meant for displaying to the user. | ||
/// | ||
/// The value is an empty String if it is not available. | ||
final String display; | ||
|
||
/// A string that uniquely identifies this build. | ||
/// | ||
/// The value is an empty String if it is not available. | ||
final String fingerprint; | ||
|
||
/// The name of the hardware (from the kernel command line or /proc). | ||
/// | ||
/// The value is an empty String if it is not available. | ||
final String hardware; | ||
|
||
/// Hostname. | ||
/// | ||
/// The value is an empty String if it is not available. | ||
final String host; | ||
|
||
/// Either a changelist number, or a label like "M4-rc20". | ||
/// | ||
/// The value is an empty String if it is not available. | ||
final String id; | ||
|
||
/// The manufacturer of the product/hardware. | ||
/// | ||
/// The value is an empty String if it is not available. | ||
final String manufacturer; | ||
|
||
/// The end-user-visible name for the end product. | ||
/// | ||
/// The value is an empty String if it is not available. | ||
final String model; | ||
|
||
/// The name of the overall product. | ||
/// | ||
/// The value is an empty String if it is not available. | ||
final String product; | ||
|
||
/// An ordered list of 32 bit ABIs supported by this device. | ||
|
@@ -83,15 +107,23 @@ class AndroidDeviceInfo { | |
final List<String> supportedAbis; | ||
|
||
/// Comma-separated tags describing the build, like "unsigned,debug". | ||
/// | ||
/// The value is an empty String if it is not available. | ||
final String tags; | ||
|
||
/// The type of build, like "user" or "eng". | ||
/// | ||
/// The value is an empty String if it is not available. | ||
final String type; | ||
|
||
/// `false` if the application is running in an emulator, `true` otherwise. | ||
/// The value is `true` if the application is running on a physical device. | ||
/// | ||
/// The value is `false` when the application is running on a emulator, or the value is unavailable. | ||
final bool isPhysicalDevice; | ||
|
||
/// The Android hardware device ID that is unique between the device + user and app signing. | ||
/// | ||
/// The value is an empty String if it is not available. | ||
final String androidId; | ||
|
||
/// Describes what features are available on the current device. | ||
|
@@ -113,35 +145,41 @@ class AndroidDeviceInfo { | |
/// Deserializes from the message received from [_kChannel]. | ||
static AndroidDeviceInfo fromMap(Map<String, dynamic> map) { | ||
return AndroidDeviceInfo( | ||
version: | ||
AndroidBuildVersion._fromMap(map['version']!.cast<String, dynamic>()), | ||
board: map['board']!, | ||
bootloader: map['bootloader']!, | ||
brand: map['brand']!, | ||
device: map['device']!, | ||
display: map['display']!, | ||
fingerprint: map['fingerprint']!, | ||
hardware: map['hardware']!, | ||
host: map['host']!, | ||
id: map['id']!, | ||
manufacturer: map['manufacturer']!, | ||
model: map['model']!, | ||
product: map['product']!, | ||
supported32BitAbis: _fromList(map['supported32BitAbis']!), | ||
supported64BitAbis: _fromList(map['supported64BitAbis']!), | ||
supportedAbis: _fromList(map['supportedAbis']!), | ||
tags: map['tags']!, | ||
type: map['type']!, | ||
isPhysicalDevice: map['isPhysicalDevice']!, | ||
androidId: map['androidId']!, | ||
systemFeatures: _fromList(map['systemFeatures']!), | ||
version: AndroidBuildVersion._fromMap(map['version'] != null | ||
? map['version'].cast<String, dynamic>() | ||
: <String, dynamic>{}), | ||
board: map['board'] ?? '', | ||
bootloader: map['bootloader'] ?? '', | ||
brand: map['brand'] ?? '', | ||
device: map['device'] ?? '', | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The empty string means that there's a bug on the platform side right? I think we should have a tracking bug to address this with Pigeon, and add TODOs. We should really try to fix this with Pigeon because I can see this being a source of bugs. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Why does it have anything to do with Pigeon? This plugin doesn't use pigeon. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I guess I was referring to the Dart API. If the empty string is documented on the Android official website, then it's correct to provide empty string values. The point about Pigeon is about making this enforcement more explicit upstream, so you don't have to manually deal with it in Dart. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Did you mean when we eventually migrate this plugin to pigeon?
It's not documented. I also don't want to make everything nullable either. I think in a null safe language, it is usually the case that we don't want to make a string nullable if empty string doesn't have a specific meaning. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. yes, eventual migration. The suggestion is to look at the official documentation for explicit mentions of "null". For example, the bug that Jason was fixing in Java. https://developer.android.com/reference/android/content/pm/FeatureInfo#name The docs explicitly say that it can be I think that is the type of work that will match the intended behavior of the platform. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Most of the properties in the documentation doesn't say it is nullable or non-null. See https://developer.android.com/reference/kotlin/android/os/Build So since they are strings, I'd prefer making them non-null and empty string for "no value" on dart side. |
||
display: map['display'] ?? '', | ||
fingerprint: map['fingerprint'] ?? '', | ||
hardware: map['hardware'] ?? '', | ||
host: map['host'] ?? '', | ||
id: map['id'] ?? '', | ||
manufacturer: map['manufacturer'] ?? '', | ||
model: map['model'] ?? '', | ||
product: map['product'] ?? '', | ||
supported32BitAbis: _fromList(map['supported32BitAbis']), | ||
supported64BitAbis: _fromList(map['supported64BitAbis']), | ||
supportedAbis: _fromList(map['supportedAbis']), | ||
tags: map['tags'] ?? '', | ||
type: map['type'] ?? '', | ||
isPhysicalDevice: map['isPhysicalDevice'] ?? false, | ||
androidId: map['androidId'] ?? '', | ||
systemFeatures: _fromList(map['systemFeatures']), | ||
); | ||
} | ||
|
||
/// Deserializes message as List<String> | ||
static List<String> _fromList(dynamic message) { | ||
final List<dynamic> list = message; | ||
return List<String>.from(list); | ||
if (message == null) { | ||
return <String>[]; | ||
} | ||
assert(message is List<dynamic>); | ||
final List<dynamic> list = List<dynamic>.from(message) | ||
..removeWhere((value) => value == null); | ||
return list.cast<String>(); | ||
} | ||
} | ||
|
||
|
@@ -173,17 +211,25 @@ class AndroidBuildVersion { | |
final String? securityPatch; | ||
|
||
/// The current development codename, or the string "REL" if this is a release build. | ||
/// | ||
/// The value is an empty String if it is not available. | ||
final String codename; | ||
|
||
/// The internal value used by the underlying source control to represent this build. | ||
/// | ||
/// The value is an empty String if it is not available. | ||
final String incremental; | ||
|
||
/// The user-visible version string. | ||
/// | ||
/// The value is an empty String if it is not available. | ||
final String release; | ||
|
||
/// The user-visible SDK version of the framework. | ||
/// | ||
/// Possible values are defined in: https://developer.android.com/reference/android/os/Build.VERSION_CODES.html | ||
/// | ||
/// The value is -1 if it is unavailable. | ||
final int sdkInt; | ||
|
||
/// Deserializes from the map message received from [_kChannel]. | ||
|
@@ -192,10 +238,10 @@ class AndroidBuildVersion { | |
baseOS: map['baseOS'], | ||
previewSdkInt: map['previewSdkInt'], | ||
securityPatch: map['securityPatch'], | ||
codename: map['codename']!, | ||
incremental: map['incremental']!, | ||
release: map['release']!, | ||
sdkInt: map['sdkInt']!, | ||
codename: map['codename'] ?? '', | ||
incremental: map['incremental'] ?? '', | ||
release: map['release'] ?? '', | ||
sdkInt: map['sdkInt'] ?? -1, | ||
); | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Don't we normally leave blank lines between the
dart:
,package:
, and local blocks?There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Oh, i didn't know that's a thing. I will add the line back.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
done