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.)
This commit is contained in:
parent
ef9c059ef2
commit
199ebaa677
@ -559,7 +559,32 @@ To edit platform code in an IDE see https://flutter.io/developing-packages/#edit
|
|||||||
}
|
}
|
||||||
|
|
||||||
String _createAndroidIdentifier(String organization, String name) {
|
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) {
|
String _createPluginClassName(String name) {
|
||||||
@ -569,10 +594,21 @@ String _createPluginClassName(String name) {
|
|||||||
|
|
||||||
String _createUTIIdentifier(String organization, String name) {
|
String _createUTIIdentifier(String organization, String name) {
|
||||||
// Create a UTI (https://en.wikipedia.org/wiki/Uniform_Type_Identifier) from a base 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]+');
|
final RegExp disallowed = RegExp(r'[^a-zA-Z0-9\-\.\u0080-\uffff]+');
|
||||||
name = camelCase(name).replaceAll(disallowed, '');
|
tmpIdentifier = tmpIdentifier.replaceAll(disallowed, '');
|
||||||
name = name.isEmpty ? 'untitled' : name;
|
|
||||||
return '$organization.$name';
|
// 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>[
|
final Set<String> _packageDependencies = Set<String>.from(<String>[
|
||||||
|
@ -56,7 +56,7 @@ void main() {
|
|||||||
projectDir,
|
projectDir,
|
||||||
<String>[],
|
<String>[],
|
||||||
<String>[
|
<String>[
|
||||||
'android/app/src/main/java/com/example/flutterproject/MainActivity.java',
|
'android/app/src/main/java/com/example/flutter_project/MainActivity.java',
|
||||||
'android/app/src/main/java/io/flutter/plugins/GeneratedPluginRegistrant.java',
|
'android/app/src/main/java/io/flutter/plugins/GeneratedPluginRegistrant.java',
|
||||||
'flutter_project.iml',
|
'flutter_project.iml',
|
||||||
'ios/Flutter/AppFrameworkInfo.plist',
|
'ios/Flutter/AppFrameworkInfo.plist',
|
||||||
@ -74,7 +74,7 @@ void main() {
|
|||||||
projectDir,
|
projectDir,
|
||||||
<String>[],
|
<String>[],
|
||||||
<String>[
|
<String>[
|
||||||
'android/app/src/main/java/com/example/flutterproject/MainActivity.java',
|
'android/app/src/main/java/com/example/flutter_project/MainActivity.java',
|
||||||
'android/app/src/main/java/io/flutter/plugins/GeneratedPluginRegistrant.java',
|
'android/app/src/main/java/io/flutter/plugins/GeneratedPluginRegistrant.java',
|
||||||
'flutter_project.iml',
|
'flutter_project.iml',
|
||||||
'ios/Flutter/AppFrameworkInfo.plist',
|
'ios/Flutter/AppFrameworkInfo.plist',
|
||||||
@ -120,7 +120,7 @@ void main() {
|
|||||||
await projectDir.absolute.childDirectory('blag').create(recursive: true);
|
await projectDir.absolute.childDirectory('blag').create(recursive: true);
|
||||||
await projectDir.absolute.childDirectory('.idea').create(recursive: true);
|
await projectDir.absolute.childDirectory('.idea').create(recursive: true);
|
||||||
await _createAndAnalyzeProject(projectDir, <String>[], <String>[
|
await _createAndAnalyzeProject(projectDir, <String>[], <String>[
|
||||||
'android/app/src/main/java/com/example/flutterproject/MainActivity.java',
|
'android/app/src/main/java/com/example/flutter_project/MainActivity.java',
|
||||||
'android/app/src/main/java/io/flutter/plugins/GeneratedPluginRegistrant.java',
|
'android/app/src/main/java/io/flutter/plugins/GeneratedPluginRegistrant.java',
|
||||||
'flutter_project.iml',
|
'flutter_project.iml',
|
||||||
'ios/Flutter/AppFrameworkInfo.plist',
|
'ios/Flutter/AppFrameworkInfo.plist',
|
||||||
@ -136,7 +136,7 @@ void main() {
|
|||||||
await projectDir.absolute.childDirectory('lib').create(recursive: true);
|
await projectDir.absolute.childDirectory('lib').create(recursive: true);
|
||||||
await projectDir.absolute.childDirectory('ios').create(recursive: true);
|
await projectDir.absolute.childDirectory('ios').create(recursive: true);
|
||||||
await _createAndAnalyzeProject(projectDir, <String>[], <String>[
|
await _createAndAnalyzeProject(projectDir, <String>[], <String>[
|
||||||
'android/app/src/main/java/com/example/flutterproject/MainActivity.java',
|
'android/app/src/main/java/com/example/flutter_project/MainActivity.java',
|
||||||
'android/app/src/main/java/io/flutter/plugins/GeneratedPluginRegistrant.java',
|
'android/app/src/main/java/io/flutter/plugins/GeneratedPluginRegistrant.java',
|
||||||
'flutter_project.iml',
|
'flutter_project.iml',
|
||||||
'ios/Flutter/AppFrameworkInfo.plist',
|
'ios/Flutter/AppFrameworkInfo.plist',
|
||||||
@ -155,8 +155,8 @@ void main() {
|
|||||||
projectDir,
|
projectDir,
|
||||||
<String>[],
|
<String>[],
|
||||||
<String>[
|
<String>[
|
||||||
'android/src/main/java/com/example/flutterproject/FlutterProjectPlugin.java',
|
'android/src/main/java/com/example/flutter_project/FlutterProjectPlugin.java',
|
||||||
'example/android/app/src/main/java/com/example/flutterprojectexample/MainActivity.java',
|
'example/android/app/src/main/java/com/example/flutter_project_example/MainActivity.java',
|
||||||
'example/ios/Runner/AppDelegate.h',
|
'example/ios/Runner/AppDelegate.h',
|
||||||
'example/ios/Runner/AppDelegate.m',
|
'example/ios/Runner/AppDelegate.m',
|
||||||
'example/ios/Runner/main.m',
|
'example/ios/Runner/main.m',
|
||||||
@ -180,9 +180,9 @@ void main() {
|
|||||||
'test/flutter_project_test.dart',
|
'test/flutter_project_test.dart',
|
||||||
],
|
],
|
||||||
unexpectedPaths: <String>[
|
unexpectedPaths: <String>[
|
||||||
'android/app/src/main/java/com/example/flutterproject/MainActivity.java',
|
'android/app/src/main/java/com/example/flutter_project/MainActivity.java',
|
||||||
'android/src/main/java/com/example/flutterproject/FlutterProjectPlugin.java',
|
'android/src/main/java/com/example/flutter_project/FlutterProjectPlugin.java',
|
||||||
'example/android/app/src/main/java/com/example/flutterprojectexample/MainActivity.java',
|
'example/android/app/src/main/java/com/example/flutter_project_example/MainActivity.java',
|
||||||
'example/ios/Runner/AppDelegate.h',
|
'example/ios/Runner/AppDelegate.h',
|
||||||
'example/ios/Runner/AppDelegate.m',
|
'example/ios/Runner/AppDelegate.m',
|
||||||
'example/ios/Runner/main.m',
|
'example/ios/Runner/main.m',
|
||||||
@ -203,14 +203,14 @@ void main() {
|
|||||||
projectDir,
|
projectDir,
|
||||||
<String>['--no-pub', '--template=app', '--android-language=kotlin', '--ios-language=swift'],
|
<String>['--no-pub', '--template=app', '--android-language=kotlin', '--ios-language=swift'],
|
||||||
<String>[
|
<String>[
|
||||||
'android/app/src/main/kotlin/com/example/flutterproject/MainActivity.kt',
|
'android/app/src/main/kotlin/com/example/flutter_project/MainActivity.kt',
|
||||||
'ios/Runner/AppDelegate.swift',
|
'ios/Runner/AppDelegate.swift',
|
||||||
'ios/Runner/Runner-Bridging-Header.h',
|
'ios/Runner/Runner-Bridging-Header.h',
|
||||||
'lib/main.dart',
|
'lib/main.dart',
|
||||||
'.idea/libraries/KotlinJavaRuntime.xml',
|
'.idea/libraries/KotlinJavaRuntime.xml',
|
||||||
],
|
],
|
||||||
unexpectedPaths: <String>[
|
unexpectedPaths: <String>[
|
||||||
'android/app/src/main/java/com/example/flutterproject/MainActivity.java',
|
'android/app/src/main/java/com/example/flutter_project/MainActivity.java',
|
||||||
'ios/Runner/AppDelegate.h',
|
'ios/Runner/AppDelegate.h',
|
||||||
'ios/Runner/AppDelegate.m',
|
'ios/Runner/AppDelegate.m',
|
||||||
'ios/Runner/main.m',
|
'ios/Runner/main.m',
|
||||||
@ -227,9 +227,9 @@ void main() {
|
|||||||
'test/flutter_project_test.dart',
|
'test/flutter_project_test.dart',
|
||||||
],
|
],
|
||||||
unexpectedPaths: <String>[
|
unexpectedPaths: <String>[
|
||||||
'android/app/src/main/java/com/example/flutterproject/MainActivity.java',
|
'android/app/src/main/java/com/example/flutter_project/MainActivity.java',
|
||||||
'android/src/main/java/com/example/flutterproject/FlutterProjectPlugin.java',
|
'android/src/main/java/com/example/flutter_project/FlutterProjectPlugin.java',
|
||||||
'example/android/app/src/main/java/com/example/flutterprojectexample/MainActivity.java',
|
'example/android/app/src/main/java/com/example/flutter_project_example/MainActivity.java',
|
||||||
'example/ios/Runner/AppDelegate.h',
|
'example/ios/Runner/AppDelegate.h',
|
||||||
'example/ios/Runner/AppDelegate.m',
|
'example/ios/Runner/AppDelegate.m',
|
||||||
'example/ios/Runner/main.m',
|
'example/ios/Runner/main.m',
|
||||||
@ -251,8 +251,8 @@ void main() {
|
|||||||
projectDir,
|
projectDir,
|
||||||
<String>['--template=plugin'],
|
<String>['--template=plugin'],
|
||||||
<String>[
|
<String>[
|
||||||
'android/src/main/java/com/example/flutterproject/FlutterProjectPlugin.java',
|
'android/src/main/java/com/example/flutter_project/FlutterProjectPlugin.java',
|
||||||
'example/android/app/src/main/java/com/example/flutterprojectexample/MainActivity.java',
|
'example/android/app/src/main/java/com/example/flutter_project_example/MainActivity.java',
|
||||||
'example/ios/Runner/AppDelegate.h',
|
'example/ios/Runner/AppDelegate.h',
|
||||||
'example/ios/Runner/AppDelegate.m',
|
'example/ios/Runner/AppDelegate.m',
|
||||||
'example/ios/Runner/main.m',
|
'example/ios/Runner/main.m',
|
||||||
@ -271,8 +271,8 @@ void main() {
|
|||||||
projectDir,
|
projectDir,
|
||||||
<String>['--no-pub', '--template=plugin', '-a', 'kotlin', '--ios-language', 'swift'],
|
<String>['--no-pub', '--template=plugin', '-a', 'kotlin', '--ios-language', 'swift'],
|
||||||
<String>[
|
<String>[
|
||||||
'android/src/main/kotlin/com/example/flutterproject/FlutterProjectPlugin.kt',
|
'android/src/main/kotlin/com/example/flutter_project/FlutterProjectPlugin.kt',
|
||||||
'example/android/app/src/main/kotlin/com/example/flutterprojectexample/MainActivity.kt',
|
'example/android/app/src/main/kotlin/com/example/flutter_project_example/MainActivity.kt',
|
||||||
'example/ios/Runner/AppDelegate.swift',
|
'example/ios/Runner/AppDelegate.swift',
|
||||||
'example/ios/Runner/Runner-Bridging-Header.h',
|
'example/ios/Runner/Runner-Bridging-Header.h',
|
||||||
'example/lib/main.dart',
|
'example/lib/main.dart',
|
||||||
@ -282,8 +282,8 @@ void main() {
|
|||||||
'lib/flutter_project.dart',
|
'lib/flutter_project.dart',
|
||||||
],
|
],
|
||||||
unexpectedPaths: <String>[
|
unexpectedPaths: <String>[
|
||||||
'android/src/main/java/com/example/flutterproject/FlutterProjectPlugin.java',
|
'android/src/main/java/com/example/flutter_project/FlutterProjectPlugin.java',
|
||||||
'example/android/app/src/main/java/com/example/flutterprojectexample/MainActivity.java',
|
'example/android/app/src/main/java/com/example/flutter_project_example/MainActivity.java',
|
||||||
'example/ios/Runner/AppDelegate.h',
|
'example/ios/Runner/AppDelegate.h',
|
||||||
'example/ios/Runner/AppDelegate.m',
|
'example/ios/Runner/AppDelegate.m',
|
||||||
'example/ios/Runner/main.m',
|
'example/ios/Runner/main.m',
|
||||||
@ -296,12 +296,12 @@ void main() {
|
|||||||
projectDir,
|
projectDir,
|
||||||
<String>['--no-pub', '--template=plugin', '--org', 'com.bar.foo'],
|
<String>['--no-pub', '--template=plugin', '--org', 'com.bar.foo'],
|
||||||
<String>[
|
<String>[
|
||||||
'android/src/main/java/com/bar/foo/flutterproject/FlutterProjectPlugin.java',
|
'android/src/main/java/com/bar/foo/flutter_project/FlutterProjectPlugin.java',
|
||||||
'example/android/app/src/main/java/com/bar/foo/flutterprojectexample/MainActivity.java',
|
'example/android/app/src/main/java/com/bar/foo/flutter_project_example/MainActivity.java',
|
||||||
],
|
],
|
||||||
unexpectedPaths: <String>[
|
unexpectedPaths: <String>[
|
||||||
'android/src/main/java/com/example/flutterproject/FlutterProjectPlugin.java',
|
'android/src/main/java/com/example/flutter_project/FlutterProjectPlugin.java',
|
||||||
'example/android/app/src/main/java/com/example/flutterprojectexample/MainActivity.java',
|
'example/android/app/src/main/java/com/example/flutter_project_example/MainActivity.java',
|
||||||
],
|
],
|
||||||
);
|
);
|
||||||
}, timeout: allowForCreateFlutterProject);
|
}, timeout: allowForCreateFlutterProject);
|
||||||
@ -312,11 +312,11 @@ void main() {
|
|||||||
<String>['--no-pub', '--template=plugin', '--project-name', 'xyz'],
|
<String>['--no-pub', '--template=plugin', '--project-name', 'xyz'],
|
||||||
<String>[
|
<String>[
|
||||||
'android/src/main/java/com/example/xyz/XyzPlugin.java',
|
'android/src/main/java/com/example/xyz/XyzPlugin.java',
|
||||||
'example/android/app/src/main/java/com/example/xyzexample/MainActivity.java',
|
'example/android/app/src/main/java/com/example/xyz_example/MainActivity.java',
|
||||||
],
|
],
|
||||||
unexpectedPaths: <String>[
|
unexpectedPaths: <String>[
|
||||||
'android/src/main/java/com/example/flutterproject/FlutterProjectPlugin.java',
|
'android/src/main/java/com/example/flutter_project/FlutterProjectPlugin.java',
|
||||||
'example/android/app/src/main/java/com/example/flutterprojectexample/MainActivity.java',
|
'example/android/app/src/main/java/com/example/flutter_project_example/MainActivity.java',
|
||||||
],
|
],
|
||||||
);
|
);
|
||||||
}, timeout: allowForCreateFlutterProject);
|
}, timeout: allowForCreateFlutterProject);
|
||||||
@ -518,6 +518,54 @@ void main() {
|
|||||||
Platform: _kNoColorTerminalPlatform,
|
Platform: _kNoColorTerminalPlatform,
|
||||||
}, timeout: allowForCreateFlutterProject);
|
}, timeout: allowForCreateFlutterProject);
|
||||||
|
|
||||||
|
testUsingContext('has correct application id for android and bundle id for ios', () async {
|
||||||
|
Cache.flutterRoot = '../..';
|
||||||
|
when(mockFlutterVersion.frameworkRevision).thenReturn(frameworkRevision);
|
||||||
|
when(mockFlutterVersion.channel).thenReturn(frameworkChannel);
|
||||||
|
|
||||||
|
final CreateCommand command = CreateCommand();
|
||||||
|
final CommandRunner<void> runner = createTestCommandRunner(command);
|
||||||
|
|
||||||
|
String tmpProjectDir = fs.path.join(tempDir.path, 'hello_flutter');
|
||||||
|
await runner.run(<String>['create', '--template=app', '--no-pub', '--org', 'com.example', tmpProjectDir]);
|
||||||
|
FlutterProject project = await FlutterProject.fromDirectory(fs.directory(tmpProjectDir));
|
||||||
|
expect(
|
||||||
|
project.ios.productBundleIdentifier,
|
||||||
|
'com.example.helloFlutter'
|
||||||
|
);
|
||||||
|
expect(
|
||||||
|
project.android.applicationId,
|
||||||
|
'com.example.hello_flutter'
|
||||||
|
);
|
||||||
|
|
||||||
|
tmpProjectDir = fs.path.join(tempDir.path, 'test_abc');
|
||||||
|
await runner.run(<String>['create', '--template=app', '--no-pub', '--org', 'abc^*.1#@', tmpProjectDir]);
|
||||||
|
project = await FlutterProject.fromDirectory(fs.directory(tmpProjectDir));
|
||||||
|
expect(
|
||||||
|
project.ios.productBundleIdentifier,
|
||||||
|
'abc.1.testAbc'
|
||||||
|
);
|
||||||
|
expect(
|
||||||
|
project.android.applicationId,
|
||||||
|
'abc.u1.test_abc'
|
||||||
|
);
|
||||||
|
|
||||||
|
tmpProjectDir = fs.path.join(tempDir.path, 'flutter_project');
|
||||||
|
await runner.run(<String>['create', '--template=app', '--no-pub', '--org', '#+^%', tmpProjectDir]);
|
||||||
|
project = await FlutterProject.fromDirectory(fs.directory(tmpProjectDir));
|
||||||
|
expect(
|
||||||
|
project.ios.productBundleIdentifier,
|
||||||
|
'flutterProject.untitled'
|
||||||
|
);
|
||||||
|
expect(
|
||||||
|
project.android.applicationId,
|
||||||
|
'flutter_project.untitled'
|
||||||
|
);
|
||||||
|
}, overrides: <Type, Generator>{
|
||||||
|
FlutterVersion: () => mockFlutterVersion,
|
||||||
|
Platform: _kNoColorTerminalPlatform,
|
||||||
|
}, timeout: allowForCreateFlutterProject);
|
||||||
|
|
||||||
testUsingContext('can re-gen default template over existing project', () async {
|
testUsingContext('can re-gen default template over existing project', () async {
|
||||||
Cache.flutterRoot = '../..';
|
Cache.flutterRoot = '../..';
|
||||||
|
|
||||||
@ -616,7 +664,7 @@ void main() {
|
|||||||
projectDir,
|
projectDir,
|
||||||
<String>[],
|
<String>[],
|
||||||
<String>[
|
<String>[
|
||||||
'.android/app/src/main/java/com/bar/foo/flutterproject/host/MainActivity.java',
|
'.android/app/src/main/java/com/bar/foo/flutter_project/host/MainActivity.java',
|
||||||
],
|
],
|
||||||
);
|
);
|
||||||
}, timeout: allowForRemotePubInvocation);
|
}, timeout: allowForRemotePubInvocation);
|
||||||
@ -647,10 +695,10 @@ void main() {
|
|||||||
projectDir,
|
projectDir,
|
||||||
<String>['--no-pub'],
|
<String>['--no-pub'],
|
||||||
<String>[
|
<String>[
|
||||||
'android/app/src/main/java/com/bar/foo/flutterproject/MainActivity.java',
|
'android/app/src/main/java/com/bar/foo/flutter_project/MainActivity.java',
|
||||||
],
|
],
|
||||||
unexpectedPaths: <String>[
|
unexpectedPaths: <String>[
|
||||||
'android/app/src/main/java/com/example/flutterproject/MainActivity.java',
|
'android/app/src/main/java/com/example/flutter_project/MainActivity.java',
|
||||||
],
|
],
|
||||||
);
|
);
|
||||||
}, timeout: allowForCreateFlutterProject);
|
}, timeout: allowForCreateFlutterProject);
|
||||||
@ -682,12 +730,12 @@ void main() {
|
|||||||
projectDir,
|
projectDir,
|
||||||
<String>['--no-pub', '--template=plugin'],
|
<String>['--no-pub', '--template=plugin'],
|
||||||
<String>[
|
<String>[
|
||||||
'example/android/app/src/main/java/com/bar/foo/flutterprojectexample/MainActivity.java',
|
'example/android/app/src/main/java/com/bar/foo/flutter_project_example/MainActivity.java',
|
||||||
'ios/Classes/FlutterProjectPlugin.h',
|
'ios/Classes/FlutterProjectPlugin.h',
|
||||||
],
|
],
|
||||||
unexpectedPaths: <String>[
|
unexpectedPaths: <String>[
|
||||||
'example/android/app/src/main/java/com/example/flutterprojectexample/MainActivity.java',
|
'example/android/app/src/main/java/com/example/flutter_project_example/MainActivity.java',
|
||||||
'android/src/main/java/com/example/flutterproject/FlutterProjectPlugin.java',
|
'android/src/main/java/com/example/flutter_project/FlutterProjectPlugin.java',
|
||||||
],
|
],
|
||||||
);
|
);
|
||||||
final FlutterProject project = await FlutterProject.fromDirectory(projectDir);
|
final FlutterProject project = await FlutterProject.fromDirectory(projectDir);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user