Skip to content
This repository was archived by the owner on Feb 22, 2023. It is now read-only.

Commit a4eea5b

Browse files
committed
[device_info] add PackageManager's SystemFeatures to AndroidDeviceInfo
There's a variety of scenarios where checking at runtime which system features are available is useful. System features are device capabilities that do not change at runtime (for example, FEATURE_BLUETOOTH is always present if the device has a bluetooth radio, even if Bluetooth is presently disabled), so DeviceInfo seems like the right place to put this.
1 parent 2349099 commit a4eea5b

6 files changed

Lines changed: 41 additions & 12 deletions

File tree

packages/device_info/CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,7 @@
1+
## 0.4.2
2+
3+
* Add systemFeatures to AndroidDeviceInfo.
4+
15
## 0.4.1+5
26

37
* Make the pedantic dev_dependency explicit.

packages/device_info/android/src/main/java/io/flutter/plugins/deviceinfo/DeviceInfoPlugin.java

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

55
package io.flutter.plugins.deviceinfo;
66

7-
import android.content.ContentResolver;
7+
import android.content.Context;
88
import io.flutter.embedding.engine.plugins.FlutterPlugin;
99
import io.flutter.plugin.common.BinaryMessenger;
1010
import io.flutter.plugin.common.MethodChannel;
@@ -18,24 +18,24 @@ public class DeviceInfoPlugin implements FlutterPlugin {
1818
/** Plugin registration. */
1919
public static void registerWith(Registrar registrar) {
2020
DeviceInfoPlugin plugin = new DeviceInfoPlugin();
21-
plugin.setupMethodChannel(registrar.messenger(), registrar.context().getContentResolver());
21+
plugin.setupMethodChannel(registrar.messenger(), registrar.context());
2222
}
2323

2424
@Override
2525
public void onAttachedToEngine(FlutterPlugin.FlutterPluginBinding binding) {
2626
setupMethodChannel(
27-
binding.getFlutterEngine().getDartExecutor(),
28-
binding.getApplicationContext().getContentResolver());
27+
binding.getFlutterEngine().getDartExecutor(), binding.getApplicationContext());
2928
}
3029

3130
@Override
3231
public void onDetachedFromEngine(FlutterPlugin.FlutterPluginBinding binding) {
3332
tearDownChannel();
3433
}
3534

36-
private void setupMethodChannel(BinaryMessenger messenger, ContentResolver contentResolver) {
35+
private void setupMethodChannel(BinaryMessenger messenger, Context context) {
3736
channel = new MethodChannel(messenger, "plugins.flutter.io/device_info");
38-
final MethodCallHandlerImpl handler = new MethodCallHandlerImpl(contentResolver);
37+
final MethodCallHandlerImpl handler =
38+
new MethodCallHandlerImpl(context.getContentResolver(), context.getPackageManager());
3939
channel.setMethodCallHandler(handler);
4040
}
4141

packages/device_info/android/src/main/java/io/flutter/plugins/deviceinfo/MethodCallHandlerImpl.java

Lines changed: 21 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@
66

77
import android.annotation.SuppressLint;
88
import android.content.ContentResolver;
9+
import android.content.pm.FeatureInfo;
10+
import android.content.pm.PackageManager;
911
import android.os.Build;
1012
import android.provider.Settings;
1113
import io.flutter.plugin.common.MethodCall;
@@ -20,14 +22,16 @@
2022
*/
2123
class MethodCallHandlerImpl implements MethodChannel.MethodCallHandler {
2224

23-
private ContentResolver contentResolver;
25+
private final ContentResolver contentResolver;
26+
private final PackageManager packageManager;
2427

2528
/** Substitute for missing values. */
2629
private static final String[] EMPTY_STRING_LIST = new String[] {};
2730

28-
/** Constructs DeviceInfo. The {@code contentResolver} must not be null. */
29-
MethodCallHandlerImpl(ContentResolver contentResolver) {
31+
/** Constructs DeviceInfo. {@code contentResolver} and {@code packageManager} must not be null. */
32+
MethodCallHandlerImpl(ContentResolver contentResolver, PackageManager packageManager) {
3033
this.contentResolver = contentResolver;
34+
this.packageManager = packageManager;
3135
}
3236

3337
@Override
@@ -60,6 +64,8 @@ public void onMethodCall(MethodCall call, MethodChannel.Result result) {
6064
build.put("isPhysicalDevice", !isEmulator());
6165
build.put("androidId", getAndroidId());
6266

67+
build.put("systemFeatures", Arrays.asList(getSystemFeatures()));
68+
6369
Map<String, Object> version = new HashMap<>();
6470
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
6571
version.put("baseOS", Build.VERSION.BASE_OS);
@@ -78,6 +84,18 @@ public void onMethodCall(MethodCall call, MethodChannel.Result result) {
7884
}
7985
}
8086

87+
private String[] getSystemFeatures() {
88+
FeatureInfo[] featureInfos = packageManager.getSystemAvailableFeatures();
89+
if (featureInfos == null) {
90+
return EMPTY_STRING_LIST;
91+
}
92+
String[] features = new String[featureInfos.length];
93+
for (int i = 0; i < featureInfos.length; i++) {
94+
features[i] = featureInfos[i].name;
95+
}
96+
return features;
97+
}
98+
8199
/**
82100
* Returns the Android hardware device ID that is unique between the device + user and app
83101
* signing. This key will change if the app is uninstalled or its data is cleared. Device factory

packages/device_info/example/lib/main.dart

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,7 @@ class _MyAppState extends State<MyApp> {
8585
'type': build.type,
8686
'isPhysicalDevice': build.isPhysicalDevice,
8787
'androidId': build.androidId,
88+
'systemFeatures': build.systemFeatures,
8889
};
8990
}
9091

@@ -114,7 +115,6 @@ class _MyAppState extends State<MyApp> {
114115
Platform.isAndroid ? 'Android Device Info' : 'iOS Device Info'),
115116
),
116117
body: ListView(
117-
shrinkWrap: true,
118118
children: _deviceData.keys.map((String property) {
119119
return Row(
120120
children: <Widget>[
@@ -132,6 +132,7 @@ class _MyAppState extends State<MyApp> {
132132
padding: const EdgeInsets.fromLTRB(0.0, 10.0, 0.0, 10.0),
133133
child: Text(
134134
'${_deviceData[property]}',
135+
maxLines: 10,
135136
overflow: TextOverflow.ellipsis,
136137
),
137138
)),

packages/device_info/lib/device_info.dart

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -62,9 +62,11 @@ class AndroidDeviceInfo {
6262
this.type,
6363
this.isPhysicalDevice,
6464
this.androidId,
65+
List<String> systemFeatures,
6566
}) : supported32BitAbis = List<String>.unmodifiable(supported32BitAbis),
6667
supported64BitAbis = List<String>.unmodifiable(supported64BitAbis),
67-
supportedAbis = List<String>.unmodifiable(supportedAbis);
68+
supportedAbis = List<String>.unmodifiable(supportedAbis),
69+
systemFeatures = List<String>.unmodifiable(systemFeatures);
6870

6971
/// Android operating system version values derived from `android.os.Build.VERSION`.
7072
final AndroidBuildVersion version;
@@ -126,6 +128,9 @@ class AndroidDeviceInfo {
126128
/// The Android hardware device ID that is unique between the device + user and app signing.
127129
final String androidId;
128130

131+
/// A list of available features, from PackageManager.getSystemAvailableFeatures.
132+
final List<String> systemFeatures;
133+
129134
/// Deserializes from the message received from [_kChannel].
130135
static AndroidDeviceInfo _fromMap(Map<String, dynamic> map) {
131136
return AndroidDeviceInfo._(
@@ -150,6 +155,7 @@ class AndroidDeviceInfo {
150155
type: map['type'],
151156
isPhysicalDevice: map['isPhysicalDevice'],
152157
androidId: map['androidId'],
158+
systemFeatures: _fromList(map['systemFeatures']),
153159
);
154160
}
155161

packages/device_info/pubspec.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ name: device_info
22
description: Flutter plugin providing detailed information about the device
33
(make, model, etc.), and Android or iOS version the app is running on.
44
homepage: https://github.com/flutter/plugins/tree/master/packages/device_info
5-
version: 0.4.1+5
5+
version: 0.4.2
66

77
flutter:
88
plugin:

0 commit comments

Comments
 (0)