Refactor ios bundleid/android application process logic. (#27471)
When creating a flutter project,
Make sure: applicationid for android conforms to: https://developer.android.com/studio/build/application-id
Make sure: bundleid for ios conforms to:
https://developer.apple.com/library/archive/documentation/FileManagement/Conceptual/understanding_utis/understand_utis_conc/understand_utis_conc.html
(Not only the name,but also the organization, as it's a check for whole bundleid.)
diff --git a/packages/flutter_tools/lib/src/commands/create.dart b/packages/flutter_tools/lib/src/commands/create.dart
index ec6f616..2a13c4c 100644
--- a/packages/flutter_tools/lib/src/commands/create.dart
+++ b/packages/flutter_tools/lib/src/commands/create.dart
@@ -559,7 +559,32 @@
}
String _createAndroidIdentifier(String organization, String name) {
- return '$organization.$name'.replaceAll('_', '');
+ // Android application ID is specified in: https://developer.android.com/studio/build/application-id
+ // All characters must be alphanumeric or an underscore [a-zA-Z0-9_].
+ String tmpIdentifier = '$organization.$name';
+ final RegExp disallowed = RegExp(r'[^\w\.]');
+ tmpIdentifier = tmpIdentifier.replaceAll(disallowed, '');
+
+ // It must have at least two segments (one or more dots).
+ final List<String> segments = tmpIdentifier
+ .split('.')
+ .where((String segment) => segment.isNotEmpty)
+ .toList();
+ while (segments.length < 2) {
+ segments.add('untitled');
+ }
+
+ // Each segment must start with a letter.
+ final RegExp segmentPatternRegex = RegExp(r'^[a-zA-Z][\w]*$');
+ final List<String> prefixedSegments = segments
+ .map((String segment) {
+ if (!segmentPatternRegex.hasMatch(segment)) {
+ return 'u'+segment;
+ }
+ return segment;
+ })
+ .toList();
+ return prefixedSegments.join('.');
}
String _createPluginClassName(String name) {
@@ -569,10 +594,21 @@
String _createUTIIdentifier(String organization, String name) {
// Create a UTI (https://en.wikipedia.org/wiki/Uniform_Type_Identifier) from a base name
+ name = camelCase(name);
+ String tmpIdentifier = '$organization.$name';
final RegExp disallowed = RegExp(r'[^a-zA-Z0-9\-\.\u0080-\uffff]+');
- name = camelCase(name).replaceAll(disallowed, '');
- name = name.isEmpty ? 'untitled' : name;
- return '$organization.$name';
+ tmpIdentifier = tmpIdentifier.replaceAll(disallowed, '');
+
+ // It must have at least two segments (one or more dots).
+ final List<String> segments = tmpIdentifier
+ .split('.')
+ .where((String segment) => segment.isNotEmpty)
+ .toList();
+ while (segments.length < 2) {
+ segments.add('untitled');
+ }
+
+ return segments.join('.');
}
final Set<String> _packageDependencies = Set<String>.from(<String>[