[flutter_tools] Add namespace getter in Android project; use namespace as fallback (#121416)
[flutter_tools] Add namespace getter in Android project; use namespace as fallback
This commit is contained in:
parent
06206c2f3a
commit
57171a3fef
@ -171,7 +171,10 @@ class AndroidApk extends ApplicationPackage implements PrebuiltApplicationPackag
|
||||
logger.printError('Please check ${manifest.path} for errors.');
|
||||
return null;
|
||||
}
|
||||
final String? packageId = manifests.first.getAttribute('package');
|
||||
|
||||
// Starting from AGP version 7.3, the `package` attribute in Manifest.xml
|
||||
// can be replaced with the `namespace` attribute under the `android` section in `android/app/build.gradle`.
|
||||
final String? packageId = manifests.first.getAttribute('package') ?? androidProject.namespace;
|
||||
|
||||
String? launchActivity;
|
||||
for (final XmlElement activity in document.findAllElements('activity')) {
|
||||
|
@ -424,6 +424,7 @@ class AndroidProject extends FlutterProjectPlatform {
|
||||
@override
|
||||
String get pluginConfigKey => AndroidPlugin.kConfigKey;
|
||||
|
||||
static final RegExp _androidNamespacePattern = RegExp('android {[\\S\\s]+namespace[\\s]+[\'"](.+)[\'"]');
|
||||
static final RegExp _applicationIdPattern = RegExp('^\\s*applicationId\\s+[\'"](.*)[\'"]\\s*\$');
|
||||
static final RegExp _kotlinPluginPattern = RegExp('^\\s*apply plugin\\:\\s+[\'"]kotlin-android[\'"]\\s*\$');
|
||||
static final RegExp _groupPattern = RegExp('^\\s*group\\s+[\'"](.*)[\'"]\\s*\$');
|
||||
@ -486,9 +487,15 @@ class AndroidProject extends FlutterProjectPlatform {
|
||||
}
|
||||
|
||||
File get appManifestFile {
|
||||
return isUsingGradle
|
||||
? globals.fs.file(globals.fs.path.join(hostAppGradleRoot.path, 'app', 'src', 'main', 'AndroidManifest.xml'))
|
||||
: hostAppGradleRoot.childFile('AndroidManifest.xml');
|
||||
if(isUsingGradle) {
|
||||
return hostAppGradleRoot
|
||||
.childDirectory('app')
|
||||
.childDirectory('src')
|
||||
.childDirectory('main')
|
||||
.childFile('AndroidManifest.xml');
|
||||
}
|
||||
|
||||
return hostAppGradleRoot.childFile('AndroidManifest.xml');
|
||||
}
|
||||
|
||||
File get gradleAppOutV1File => gradleAppOutV1Directory.childFile('app-debug.apk');
|
||||
@ -512,6 +519,19 @@ class AndroidProject extends FlutterProjectPlatform {
|
||||
return firstMatchInFile(gradleFile, _applicationIdPattern)?.group(1);
|
||||
}
|
||||
|
||||
/// Get the namespace for newer Android projects,
|
||||
/// which replaces the `package` attribute in the Manifest.xml.
|
||||
String? get namespace {
|
||||
final File gradleFile = hostAppGradleRoot.childDirectory('app').childFile('build.gradle');
|
||||
|
||||
if (!gradleFile.existsSync()) {
|
||||
return null;
|
||||
}
|
||||
|
||||
// firstMatchInFile() reads per line but `_androidNamespacePattern` matches a multiline pattern.
|
||||
return _androidNamespacePattern.firstMatch(gradleFile.readAsStringSync())?.group(1);
|
||||
}
|
||||
|
||||
String? get group {
|
||||
final File gradleFile = hostAppGradleRoot.childFile('build.gradle');
|
||||
return firstMatchInFile(gradleFile, _groupPattern)?.group(1);
|
||||
|
@ -5,7 +5,9 @@
|
||||
import 'package:archive/archive.dart';
|
||||
import 'package:file/memory.dart';
|
||||
import 'package:file_testing/file_testing.dart';
|
||||
import 'package:flutter_tools/src/android/android_sdk.dart';
|
||||
import 'package:flutter_tools/src/android/android_studio.dart';
|
||||
import 'package:flutter_tools/src/android/application_package.dart';
|
||||
import 'package:flutter_tools/src/android/gradle.dart';
|
||||
import 'package:flutter_tools/src/android/gradle_errors.dart';
|
||||
import 'package:flutter_tools/src/android/gradle_utils.dart';
|
||||
@ -14,6 +16,8 @@ import 'package:flutter_tools/src/base/file_system.dart';
|
||||
import 'package:flutter_tools/src/base/io.dart';
|
||||
import 'package:flutter_tools/src/base/logger.dart';
|
||||
import 'package:flutter_tools/src/base/platform.dart';
|
||||
import 'package:flutter_tools/src/base/process.dart';
|
||||
import 'package:flutter_tools/src/base/user_messages.dart';
|
||||
import 'package:flutter_tools/src/build_info.dart';
|
||||
import 'package:flutter_tools/src/cache.dart';
|
||||
import 'package:flutter_tools/src/project.dart';
|
||||
@ -23,6 +27,7 @@ import 'package:test/fake.dart';
|
||||
import '../../src/common.dart';
|
||||
import '../../src/context.dart';
|
||||
import '../../src/fake_process_manager.dart';
|
||||
import '../../src/fakes.dart';
|
||||
|
||||
void main() {
|
||||
group('gradle build', () {
|
||||
@ -724,6 +729,64 @@ void main() {
|
||||
AndroidStudio: () => FakeAndroidStudio(),
|
||||
});
|
||||
|
||||
testUsingContext('Uses namespace attribute if manifest lacks a package attribute', () async {
|
||||
final FlutterProject project = FlutterProject.fromDirectoryTest(fileSystem.currentDirectory);
|
||||
final AndroidSdk sdk = FakeAndroidSdk();
|
||||
|
||||
fileSystem.directory(project.android.hostAppGradleRoot)
|
||||
.childFile('build.gradle')
|
||||
.createSync(recursive: true);
|
||||
|
||||
fileSystem.directory(project.android.hostAppGradleRoot)
|
||||
.childDirectory('app')
|
||||
.childFile('build.gradle')
|
||||
..createSync(recursive: true)
|
||||
..writeAsStringSync(
|
||||
'''
|
||||
apply from: irrelevant/flutter.gradle
|
||||
|
||||
android {
|
||||
namespace 'com.example.foo'
|
||||
}
|
||||
''');
|
||||
|
||||
fileSystem.directory(project.android.hostAppGradleRoot)
|
||||
.childDirectory('app')
|
||||
.childDirectory('src')
|
||||
.childDirectory('main')
|
||||
.childFile('AndroidManifest.xml')
|
||||
..createSync(recursive: true)
|
||||
..writeAsStringSync(r'''
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<application
|
||||
android:label="namespacetest"
|
||||
android:name="${applicationName}"
|
||||
android:icon="@mipmap/ic_launcher">
|
||||
<activity
|
||||
android:name=".MainActivity">
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.MAIN"/>
|
||||
<category android:name="android.intent.category.LAUNCHER"/>
|
||||
</intent-filter>
|
||||
</activity>
|
||||
</application>
|
||||
</manifest>
|
||||
''');
|
||||
|
||||
final AndroidApk? androidApk = await AndroidApk.fromAndroidProject(
|
||||
project.android,
|
||||
androidSdk: sdk,
|
||||
fileSystem: fileSystem,
|
||||
logger: logger,
|
||||
processManager: processManager,
|
||||
processUtils: ProcessUtils(processManager: processManager, logger: logger),
|
||||
userMessages: UserMessages(),
|
||||
buildInfo: const BuildInfo(BuildMode.debug, null, treeShakeIcons: false),
|
||||
);
|
||||
|
||||
expect(androidApk?.id, 'com.example.foo');
|
||||
});
|
||||
|
||||
testUsingContext("doesn't indicate how to consume an AAR when printHowToConsumeAar is false", () async {
|
||||
final AndroidGradleBuilder builder = AndroidGradleBuilder(
|
||||
logger: logger,
|
||||
|
Loading…
x
Reference in New Issue
Block a user