mirror of
https://github.com/flutter/flutter
synced 2024-09-17 23:31:55 +00:00
300 lines
8.1 KiB
Dart
300 lines
8.1 KiB
Dart
// Copyright 2014 The Flutter Authors. All rights reserved.
|
|
// Use of this source code is governed by a BSD-style license that can be
|
|
// found in the LICENSE file.
|
|
|
|
import 'dart:io';
|
|
|
|
import 'package:flutter_devicelab/framework/apk_utils.dart';
|
|
import 'package:flutter_devicelab/framework/framework.dart';
|
|
import 'package:flutter_devicelab/framework/task_result.dart';
|
|
import 'package:flutter_devicelab/framework/utils.dart';
|
|
import 'package:path/path.dart' as path;
|
|
|
|
final String gradlew = Platform.isWindows ? 'gradlew.bat' : 'gradlew';
|
|
final String gradlewExecutable = Platform.isWindows ? '.\\$gradlew' : './$gradlew';
|
|
|
|
/// Tests that the Android app containing a Flutter module can be built when
|
|
/// it has custom build types and flavors.
|
|
Future<void> main() async {
|
|
await task(() async {
|
|
|
|
section('Find Java');
|
|
|
|
final String? javaHome = await findJavaHome();
|
|
if (javaHome == null) {
|
|
return TaskResult.failure('Could not find Java');
|
|
}
|
|
|
|
print('\nUsing JAVA_HOME=$javaHome');
|
|
|
|
section('Create Flutter module project');
|
|
|
|
await flutter(
|
|
'precache',
|
|
options: <String>['--android', '--no-ios'],
|
|
);
|
|
|
|
final Directory tempDir = Directory.systemTemp.createTempSync('flutter_module_test.');
|
|
final Directory projectDir = Directory(path.join(tempDir.path, 'hello'));
|
|
try {
|
|
await inDirectory(tempDir, () async {
|
|
await flutter(
|
|
'create',
|
|
options: <String>['--org', 'io.flutter.devicelab', '--template=module', 'hello'],
|
|
);
|
|
});
|
|
|
|
section('Run flutter pub get');
|
|
|
|
await inDirectory(projectDir, () async {
|
|
await flutter(
|
|
'pub',
|
|
options: <String>['get'],
|
|
);
|
|
});
|
|
|
|
section('Add to existing Android app');
|
|
|
|
final Directory hostAppDir = Directory(path.join(tempDir.path, 'hello_host_app_with_custom_build'));
|
|
mkdir(hostAppDir);
|
|
recursiveCopy(
|
|
Directory(
|
|
path.join(
|
|
flutterDirectory.path,
|
|
'dev',
|
|
'integration_tests',
|
|
'module_host_with_custom_build_v2_embedding',
|
|
),
|
|
),
|
|
hostAppDir,
|
|
);
|
|
copy(
|
|
File(path.join(projectDir.path, '.android', gradlew)),
|
|
hostAppDir,
|
|
);
|
|
copy(
|
|
File(path.join(projectDir.path, '.android', 'gradle', 'wrapper', 'gradle-wrapper.jar')),
|
|
Directory(path.join(hostAppDir.path, 'gradle', 'wrapper')),
|
|
);
|
|
|
|
Future<void> clean() async {
|
|
section('Clean');
|
|
await inDirectory(hostAppDir, () async {
|
|
await exec(gradlewExecutable,
|
|
<String>['clean'],
|
|
environment: <String, String>{
|
|
'JAVA_HOME': javaHome,
|
|
},
|
|
);
|
|
});
|
|
}
|
|
|
|
if (!Platform.isWindows) {
|
|
section('Make $gradlewExecutable executable');
|
|
await inDirectory(hostAppDir, () async {
|
|
await exec('chmod', <String>['+x', gradlewExecutable]);
|
|
});
|
|
}
|
|
|
|
section('Build debug APKs');
|
|
|
|
section('Run app:assembleDemoDebug');
|
|
|
|
await inDirectory(hostAppDir, () async {
|
|
await exec(gradlewExecutable,
|
|
<String>['app:assembleDemoDebug'],
|
|
environment: <String, String>{
|
|
'JAVA_HOME': javaHome,
|
|
},
|
|
);
|
|
});
|
|
|
|
final String demoDebugApk = path.join(
|
|
hostAppDir.path,
|
|
'app',
|
|
'build',
|
|
'outputs',
|
|
'apk',
|
|
'demo',
|
|
'debug',
|
|
'app-demo-debug.apk',
|
|
);
|
|
|
|
if (!exists(File(demoDebugApk))) {
|
|
return TaskResult.failure('Failed to build app-demo-debug.apk');
|
|
}
|
|
|
|
section('Verify snapshots in app-demo-debug.apk');
|
|
|
|
checkCollectionContains<String>(<String>[
|
|
...flutterAssets,
|
|
...debugAssets,
|
|
], await getFilesInApk(demoDebugApk));
|
|
|
|
await clean();
|
|
|
|
// Change the order of the task and ensure that flutter_assets are in the APK.
|
|
// https://github.com/flutter/flutter/pull/41333
|
|
section('Run app:assembleDemoDebug - Merge assets before processing manifest');
|
|
|
|
await inDirectory(hostAppDir, () async {
|
|
await exec(gradlewExecutable,
|
|
<String>[
|
|
// Normally, `app:processDemoDebugManifest` runs before `app:mergeDemoDebugAssets`.
|
|
// In this case, we run `app:mergeDemoDebugAssets` first.
|
|
'app:mergeDemoDebugAssets',
|
|
'app:processDemoDebugManifest',
|
|
'app:assembleDemoDebug',
|
|
],
|
|
environment: <String, String>{
|
|
'JAVA_HOME': javaHome,
|
|
},
|
|
);
|
|
});
|
|
|
|
final String demoDebugApk2 = path.join(
|
|
hostAppDir.path,
|
|
'app',
|
|
'build',
|
|
'outputs',
|
|
'apk',
|
|
'demo',
|
|
'debug',
|
|
'app-demo-debug.apk',
|
|
);
|
|
|
|
if (!exists(File(demoDebugApk2))) {
|
|
return TaskResult.failure('Failed to build app-demo-debug.apk');
|
|
}
|
|
|
|
section('Verify snapshots in app-demo-debug.apk');
|
|
|
|
checkCollectionContains<String>(<String>[
|
|
...flutterAssets,
|
|
...debugAssets,
|
|
], await getFilesInApk(demoDebugApk2));
|
|
|
|
await clean();
|
|
|
|
section('Run app:assembleDemoStaging');
|
|
|
|
await inDirectory(hostAppDir, () async {
|
|
await exec(gradlewExecutable,
|
|
<String>['app:assembleDemoStaging'],
|
|
environment: <String, String>{
|
|
'JAVA_HOME': javaHome,
|
|
},
|
|
);
|
|
});
|
|
|
|
final String demoStagingApk = path.join(
|
|
hostAppDir.path,
|
|
'app',
|
|
'build',
|
|
'outputs',
|
|
'apk',
|
|
'demo',
|
|
'staging',
|
|
'app-demo-staging.apk',
|
|
);
|
|
|
|
if (!exists(File(demoStagingApk))) {
|
|
return TaskResult.failure('Failed to build app-demo-staging.apk');
|
|
}
|
|
|
|
section('Verify snapshots in app-demo-staging.apk');
|
|
|
|
checkCollectionContains<String>(<String>[
|
|
...flutterAssets,
|
|
...debugAssets,
|
|
], await getFilesInApk(demoStagingApk));
|
|
|
|
await clean();
|
|
|
|
section('Build release APKs');
|
|
|
|
section('Run app:assembleDemoRelease');
|
|
|
|
await inDirectory(hostAppDir, () async {
|
|
await exec(gradlewExecutable,
|
|
<String>['app:assembleDemoRelease'],
|
|
environment: <String, String>{
|
|
'JAVA_HOME': javaHome,
|
|
},
|
|
);
|
|
});
|
|
|
|
final String demoReleaseApk = path.join(
|
|
hostAppDir.path,
|
|
'app',
|
|
'build',
|
|
'outputs',
|
|
'apk',
|
|
'demo',
|
|
'release',
|
|
'app-demo-release-unsigned.apk',
|
|
);
|
|
|
|
if (!exists(File(demoReleaseApk))) {
|
|
return TaskResult.failure('Failed to build app-demo-release-unsigned.apk');
|
|
}
|
|
|
|
section('Verify AOT ELF in app-demo-release-unsigned.apk');
|
|
|
|
checkCollectionContains<String>(<String>[
|
|
...flutterAssets,
|
|
'lib/arm64-v8a/libflutter.so',
|
|
'lib/arm64-v8a/libapp.so',
|
|
'lib/armeabi-v7a/libflutter.so',
|
|
'lib/armeabi-v7a/libapp.so',
|
|
], await getFilesInApk(demoReleaseApk));
|
|
|
|
await clean();
|
|
|
|
section('Run app:assembleDemoProd');
|
|
|
|
await inDirectory(hostAppDir, () async {
|
|
await exec(gradlewExecutable,
|
|
<String>['app:assembleDemoProd'],
|
|
environment: <String, String>{
|
|
'JAVA_HOME': javaHome,
|
|
},
|
|
);
|
|
});
|
|
|
|
final String demoProdApk = path.join(
|
|
hostAppDir.path,
|
|
'app',
|
|
'build',
|
|
'outputs',
|
|
'apk',
|
|
'demo',
|
|
'prod',
|
|
'app-demo-prod-unsigned.apk',
|
|
);
|
|
|
|
if (!exists(File(demoProdApk))) {
|
|
return TaskResult.failure('Failed to build app-demo-prod-unsigned.apk');
|
|
}
|
|
|
|
section('Verify AOT ELF in app-demo-prod-unsigned.apk');
|
|
|
|
checkCollectionContains<String>(<String>[
|
|
...flutterAssets,
|
|
'lib/arm64-v8a/libapp.so',
|
|
'lib/arm64-v8a/libflutter.so',
|
|
'lib/armeabi-v7a/libapp.so',
|
|
'lib/armeabi-v7a/libflutter.so',
|
|
], await getFilesInApk(demoProdApk));
|
|
|
|
return TaskResult.success(null);
|
|
} on TaskResult catch (taskResult) {
|
|
return taskResult;
|
|
} catch (e) {
|
|
return TaskResult.failure(e.toString());
|
|
} finally {
|
|
rmTree(tempDir);
|
|
}
|
|
});
|
|
}
|