Unverified Commit 57171a3f authored by Navaron Bracke's avatar Navaron Bracke Committed by GitHub

[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
parent 06206c2f
......@@ -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,
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment