Show warning when attempting to flutter run on an ios device with developer mode turned off (#125710)
This PR adds a warning when a user attempt to `flutter run -d <device id>` on a device without developer mode enabled. <img width="738" alt="Screenshot 2023-05-09 at 3 53 18 AM" src="https://github.com/flutter/flutter/assets/36148254/6f473a6a-5a0d-438b-9e6f-06d09eb1f3a9"> Also handles multiple partial matches. <img width="788" alt="Screenshot 2023-05-09 at 3 52 24 AM" src="https://github.com/flutter/flutter/assets/36148254/60c82b3c-d501-4a01-95ad-d6309fe39576"> Fixes https://github.com/flutter/flutter/issues/111988
This commit is contained in:
parent
487ed57388
commit
e345a830ba
@ -261,6 +261,7 @@ class IOSDevice extends Device {
|
||||
required this.cpuArchitecture,
|
||||
required this.connectionInterface,
|
||||
required this.isConnected,
|
||||
required this.devModeEnabled,
|
||||
String? sdkVersion,
|
||||
required Platform platform,
|
||||
required IOSDeploy iosDeploy,
|
||||
@ -323,6 +324,8 @@ class IOSDevice extends Device {
|
||||
|
||||
DevicePortForwarder? _portForwarder;
|
||||
|
||||
bool devModeEnabled = false;
|
||||
|
||||
@visibleForTesting
|
||||
IOSDeployDebugger? iosDeployDebugger;
|
||||
|
||||
|
@ -505,7 +505,7 @@ class XCDevice {
|
||||
if (identifier == null || name == null) {
|
||||
continue;
|
||||
}
|
||||
|
||||
bool devModeEnabled = true;
|
||||
bool isConnected = true;
|
||||
final Map<String, Object?>? errorProperties = _errorProperties(device);
|
||||
if (errorProperties != null) {
|
||||
@ -525,6 +525,10 @@ class XCDevice {
|
||||
if (code != -10) {
|
||||
isConnected = false;
|
||||
}
|
||||
|
||||
if (code == 6) {
|
||||
devModeEnabled = false;
|
||||
}
|
||||
}
|
||||
|
||||
String? sdkVersion = _sdkVersion(device);
|
||||
@ -549,6 +553,7 @@ class XCDevice {
|
||||
iosDeploy: _iosDeploy,
|
||||
iMobileDevice: _iMobileDevice,
|
||||
platform: globals.platform,
|
||||
devModeEnabled: devModeEnabled
|
||||
));
|
||||
}
|
||||
}
|
||||
|
@ -29,6 +29,8 @@ String _foundSpecifiedDevicesMessage(int count, String deviceId) =>
|
||||
'Found $count devices with name or id matching $deviceId:';
|
||||
String _noMatchingDeviceMessage(String deviceId) => 'No supported devices found with name or id '
|
||||
"matching '$deviceId'.";
|
||||
String flutterSpecifiedDeviceDevModeDisabled(String deviceName) => 'To use '
|
||||
"'$deviceName' for development, enable Developer Mode in Settings → Privacy & Security.";
|
||||
|
||||
/// This class handles functionality of finding and selecting target devices.
|
||||
///
|
||||
@ -486,18 +488,39 @@ class TargetDevicesWithExtendedWirelessDeviceDiscovery extends TargetDevices {
|
||||
// If there are multiple matches, continue on to wait for all attached
|
||||
// and wireless devices to load so the user can select between all
|
||||
// connected matches.
|
||||
final List<Device> devices = await _getDeviceById(
|
||||
final List<Device> specifiedDevices = await _getDeviceById(
|
||||
includeDevicesUnsupportedByProject: includeDevicesUnsupportedByProject,
|
||||
includeDisconnected: true,
|
||||
);
|
||||
if (devices.length == 1) {
|
||||
Device? matchedDevice = devices.first;
|
||||
|
||||
if (specifiedDevices.length == 1) {
|
||||
Device? matchedDevice = specifiedDevices.first;
|
||||
// If the only matching device does not have Developer Mode enabled,
|
||||
// print a warning
|
||||
if (matchedDevice is IOSDevice && !matchedDevice.devModeEnabled) {
|
||||
_logger.printStatus(
|
||||
flutterSpecifiedDeviceDevModeDisabled(matchedDevice.name)
|
||||
);
|
||||
return null;
|
||||
}
|
||||
|
||||
if (!matchedDevice.isConnected && matchedDevice is IOSDevice) {
|
||||
matchedDevice = await _waitForIOSDeviceToConnect(matchedDevice);
|
||||
}
|
||||
|
||||
if (matchedDevice != null && matchedDevice.isConnected) {
|
||||
return <Device>[matchedDevice];
|
||||
}
|
||||
|
||||
} else {
|
||||
for (final Device device in specifiedDevices) {
|
||||
// Print warning for every matching device that does not have Developer Mode enabled.
|
||||
if (device is IOSDevice && !device.devModeEnabled) {
|
||||
_logger.printStatus(
|
||||
flutterSpecifiedDeviceDevModeDisabled(device.name)
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -76,6 +76,7 @@ void main() {
|
||||
cpuArchitecture: DarwinArch.arm64,
|
||||
connectionInterface: DeviceConnectionInterface.attached,
|
||||
isConnected: true,
|
||||
devModeEnabled: true,
|
||||
);
|
||||
expect(device.isSupported(), isTrue);
|
||||
});
|
||||
@ -93,6 +94,7 @@ void main() {
|
||||
cpuArchitecture: DarwinArch.armv7,
|
||||
connectionInterface: DeviceConnectionInterface.attached,
|
||||
isConnected: true,
|
||||
devModeEnabled: true,
|
||||
);
|
||||
expect(device.isSupported(), isFalse);
|
||||
});
|
||||
@ -111,6 +113,7 @@ void main() {
|
||||
sdkVersion: '1.0.0',
|
||||
connectionInterface: DeviceConnectionInterface.attached,
|
||||
isConnected: true,
|
||||
devModeEnabled: true,
|
||||
).majorSdkVersion, 1);
|
||||
expect(IOSDevice(
|
||||
'device-123',
|
||||
@ -125,6 +128,7 @@ void main() {
|
||||
sdkVersion: '13.1.1',
|
||||
connectionInterface: DeviceConnectionInterface.attached,
|
||||
isConnected: true,
|
||||
devModeEnabled: true,
|
||||
).majorSdkVersion, 13);
|
||||
expect(IOSDevice(
|
||||
'device-123',
|
||||
@ -139,6 +143,7 @@ void main() {
|
||||
sdkVersion: '10',
|
||||
connectionInterface: DeviceConnectionInterface.attached,
|
||||
isConnected: true,
|
||||
devModeEnabled: true,
|
||||
).majorSdkVersion, 10);
|
||||
expect(IOSDevice(
|
||||
'device-123',
|
||||
@ -153,6 +158,7 @@ void main() {
|
||||
sdkVersion: '0',
|
||||
connectionInterface: DeviceConnectionInterface.attached,
|
||||
isConnected: true,
|
||||
devModeEnabled: true,
|
||||
).majorSdkVersion, 0);
|
||||
expect(IOSDevice(
|
||||
'device-123',
|
||||
@ -167,6 +173,7 @@ void main() {
|
||||
sdkVersion: 'bogus',
|
||||
connectionInterface: DeviceConnectionInterface.attached,
|
||||
isConnected: true,
|
||||
devModeEnabled: true,
|
||||
).majorSdkVersion, 0);
|
||||
});
|
||||
|
||||
@ -184,6 +191,7 @@ void main() {
|
||||
cpuArchitecture: DarwinArch.arm64,
|
||||
connectionInterface: DeviceConnectionInterface.attached,
|
||||
isConnected: true,
|
||||
devModeEnabled: true,
|
||||
);
|
||||
|
||||
expect(await device.sdkNameAndVersion,'iOS 13.3 17C54');
|
||||
@ -203,6 +211,7 @@ void main() {
|
||||
cpuArchitecture: DarwinArch.arm64,
|
||||
connectionInterface: DeviceConnectionInterface.attached,
|
||||
isConnected: true,
|
||||
devModeEnabled: true,
|
||||
);
|
||||
|
||||
expect(device.supportsRuntimeMode(BuildMode.debug), true);
|
||||
@ -228,6 +237,7 @@ void main() {
|
||||
cpuArchitecture: DarwinArch.arm64,
|
||||
connectionInterface: DeviceConnectionInterface.attached,
|
||||
isConnected: true,
|
||||
devModeEnabled: true,
|
||||
);
|
||||
},
|
||||
throwsAssertionError,
|
||||
@ -319,6 +329,7 @@ void main() {
|
||||
cpuArchitecture: DarwinArch.arm64,
|
||||
connectionInterface: DeviceConnectionInterface.attached,
|
||||
isConnected: true,
|
||||
devModeEnabled: true,
|
||||
);
|
||||
logReader1 = createLogReader(device, appPackage1, process1);
|
||||
logReader2 = createLogReader(device, appPackage2, process2);
|
||||
@ -381,6 +392,7 @@ void main() {
|
||||
fileSystem: MemoryFileSystem.test(),
|
||||
connectionInterface: DeviceConnectionInterface.attached,
|
||||
isConnected: true,
|
||||
devModeEnabled: true,
|
||||
);
|
||||
|
||||
device2 = IOSDevice(
|
||||
@ -396,6 +408,7 @@ void main() {
|
||||
fileSystem: MemoryFileSystem.test(),
|
||||
connectionInterface: DeviceConnectionInterface.attached,
|
||||
isConnected: true,
|
||||
devModeEnabled: true,
|
||||
);
|
||||
});
|
||||
|
||||
@ -687,6 +700,7 @@ void main() {
|
||||
fileSystem: MemoryFileSystem.test(),
|
||||
connectionInterface: DeviceConnectionInterface.attached,
|
||||
isConnected: false,
|
||||
devModeEnabled: true,
|
||||
);
|
||||
});
|
||||
|
||||
|
@ -360,5 +360,6 @@ IOSDevice setUpIOSDevice({
|
||||
iProxy: IProxy.test(logger: logger, processManager: processManager),
|
||||
connectionInterface: interfaceType ?? DeviceConnectionInterface.attached,
|
||||
isConnected: true,
|
||||
devModeEnabled: true,
|
||||
);
|
||||
}
|
||||
|
@ -101,5 +101,6 @@ IOSDevice setUpIOSDevice(FileSystem fileSystem) {
|
||||
iProxy: IProxy.test(logger: logger, processManager: processManager),
|
||||
connectionInterface: DeviceConnectionInterface.attached,
|
||||
isConnected: true,
|
||||
devModeEnabled: true,
|
||||
);
|
||||
}
|
||||
|
@ -339,6 +339,7 @@ IOSDevice setUpIOSDevice({
|
||||
cpuArchitecture: DarwinArch.arm64,
|
||||
connectionInterface: DeviceConnectionInterface.attached,
|
||||
isConnected: true,
|
||||
devModeEnabled: true,
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -649,6 +649,7 @@ IOSDevice setUpIOSDevice({
|
||||
cpuArchitecture: DarwinArch.arm64,
|
||||
connectionInterface: interfaceType,
|
||||
isConnected: true,
|
||||
devModeEnabled: true,
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -1262,6 +1262,45 @@ target-device (mobile) • xxx • ios • iOS 16 (unsupported)
|
||||
expect(deviceManager.iosDiscoverer.xcdevice.waitedForDeviceToConnect, isFalse);
|
||||
});
|
||||
|
||||
testUsingContext('when only matching device is dev mode disabled', () async {
|
||||
deviceManager.iosDiscoverer.deviceList = <Device>[FakeIOSDevice(deviceName: 'target-device', devModeEnabled: false)];
|
||||
|
||||
final List<Device>? devices = await targetDevices.findAllTargetDevices();
|
||||
|
||||
expect(logger.statusText, equals('''
|
||||
To use 'target-device' for development, enable Developer Mode in Settings → Privacy & Security.
|
||||
'''));
|
||||
expect(devices, isNull);
|
||||
});
|
||||
|
||||
testUsingContext('when one of the matching devices has dev mode disabled', () async {
|
||||
deviceManager.iosDiscoverer.deviceList = <Device>[FakeIOSDevice(deviceName: 'target-device-1', devModeEnabled: false, isConnected: false),
|
||||
FakeIOSDevice(deviceName: 'target-device-2', devModeEnabled: true)];
|
||||
|
||||
final List<Device>? devices = await targetDevices.findAllTargetDevices();
|
||||
expect(logger.statusText, equals('''
|
||||
To use 'target-device-1' for development, enable Developer Mode in Settings → Privacy & Security.
|
||||
Checking for wireless devices...
|
||||
'''));
|
||||
expect(devices, isNotNull);
|
||||
});
|
||||
|
||||
testUsingContext('when all matching devices are dev mode disabled', () async {
|
||||
deviceManager.iosDiscoverer.deviceList = <Device>[FakeIOSDevice(deviceName: 'target-device-1', devModeEnabled: false, isConnected: false),
|
||||
FakeIOSDevice(deviceName: 'target-device-2', devModeEnabled: false, isConnected: false)];
|
||||
|
||||
final List<Device>? devices = await targetDevices.findAllTargetDevices();
|
||||
|
||||
expect(logger.statusText, equals('''
|
||||
To use 'target-device-1' for development, enable Developer Mode in Settings → Privacy & Security.
|
||||
To use 'target-device-2' for development, enable Developer Mode in Settings → Privacy & Security.
|
||||
No devices found yet. Checking for wireless devices...
|
||||
|
||||
No supported devices found with name or id matching 'target-device'.
|
||||
'''));
|
||||
expect(devices, isNull);
|
||||
});
|
||||
|
||||
group('when deviceConnectionInterface does not match', () {
|
||||
testUsingContext('filter of wireless', () async {
|
||||
final FakeIOSDevice device1 = FakeIOSDevice.notConnectedWireless(deviceName: 'not-a-match');
|
||||
@ -2691,6 +2730,7 @@ class FakeIOSDevice extends Fake implements IOSDevice {
|
||||
FakeIOSDevice({
|
||||
String? deviceId,
|
||||
String? deviceName,
|
||||
bool? devModeEnabled,
|
||||
bool deviceSupported = true,
|
||||
bool deviceSupportForProject = true,
|
||||
this.ephemeral = true,
|
||||
@ -2699,6 +2739,7 @@ class FakeIOSDevice extends Fake implements IOSDevice {
|
||||
this.connectionInterface = DeviceConnectionInterface.attached,
|
||||
}) : id = deviceId ?? 'xxx',
|
||||
name = deviceName ?? 'test',
|
||||
devModeEnabled = devModeEnabled ?? true,
|
||||
_isSupported = deviceSupported,
|
||||
_isSupportedForProject = deviceSupportForProject;
|
||||
|
||||
@ -2710,6 +2751,7 @@ class FakeIOSDevice extends Fake implements IOSDevice {
|
||||
this.ephemeral = true,
|
||||
this.isConnected = false,
|
||||
this.platformType = PlatformType.ios,
|
||||
this.devModeEnabled = true,
|
||||
this.connectionInterface = DeviceConnectionInterface.wireless,
|
||||
}) : id = deviceId ?? 'xxx',
|
||||
name = deviceName ?? 'test',
|
||||
@ -2723,6 +2765,7 @@ class FakeIOSDevice extends Fake implements IOSDevice {
|
||||
bool deviceSupportForProject = true,
|
||||
this.ephemeral = true,
|
||||
this.isConnected = true,
|
||||
this.devModeEnabled = true,
|
||||
this.platformType = PlatformType.ios,
|
||||
this.connectionInterface = DeviceConnectionInterface.wireless,
|
||||
}) : id = deviceId ?? 'xxx',
|
||||
@ -2739,6 +2782,9 @@ class FakeIOSDevice extends Fake implements IOSDevice {
|
||||
@override
|
||||
final bool ephemeral;
|
||||
|
||||
@override
|
||||
final bool devModeEnabled;
|
||||
|
||||
@override
|
||||
String id;
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user