Issue building Flutter android APK with MS AppCenter using flavors
I had the same issue while using AppCenter, and I came across this answer that show the problem is caused by some build steps in gradle and that it is recommended to have a lib/main.dart
in your project.
So I solved the problem by using the lib/main.dart
to build the production version. The only file to change is the appcenter-post-clone.sh
Here's a look at my appcenter-post-clone.sh
:
#!/usr/bin/env bash
# place this script in project/android/app/
cd ..
# fail if any command fails
set -e
# debug log
set -x
cd ..
# choose a different release channel if you want - https://github.com/flutter/flutter/wiki/Flutter-build-release-channels
# stable - recommended for production
git clone -b stable https://github.com/flutter/flutter.git
export PATH=`pwd`/flutter/bin:$PATH
echo "Building with flavor $FLAVOR"
target="lib/main.dart"
if [ "$FLAVOR" == "qa" ]; then
target="lib/main_qa.dart";
elif [ "$FLAVOR" == "prod" ]; then
target="lib/main.dart";
fi
echo "using entrypoint: $target"
flutter channel stable
flutter doctor
flutter pub get
flutter pub run build_runner build
flutter build apk --release --dart-define=API_KEY=$API_KEY --dart-define=FLAVOR=$FLAVOR --flavor $FLAVOR -t $target
# change apk file name
mv build/app/outputs/flutter-apk/app-$FLAVOR-release.apk build/app/outputs/flutter-apk/wfm.apk
# copy the APK where AppCenter will find it
mkdir -p android/app/build/outputs/apk/; mv build/app/outputs/flutter-apk/wfm.apk $_
cmpbedes
Updated on December 24, 2022Comments
-
cmpbedes over 1 year
I've been following a combination of articles to attempt to build Flutter apps on MS Appcenter using flavors to achieve app environments (i.e. dev/test/live).
To achieve this, i'm using the separate
main-<environment>.dart
entry file approach as shown in this article and followed this article for configuring Appcenter.I'm having issues with the build of the android apk because the
main.dart
is missing. I thought that passing the-t
parameter to the build command would handle this?I'll add the build scripts and logs below but the flutter command being executed is this:
flutter build apk --flavor dev --release -t lib/main_dev_test.dart
The
flutter build apk
command seems to complete fine, however the build fails at the gradle task step with this error message:Task :app:compileFlutterBuildDevRelease FAILED 12 actionable tasks: 2 executed, 10 up-to-date Error: Error when reading 'lib/main.dart': No such file or directory package:hello_world/main.dart: Error: No 'main' method found. Try adding a method named 'main' to your program. FAILURE: Build failed with an exception. * Where: Script '/Users/runner/work/1/s/flutter/packages/flutter_tools/gradle/flutter.gradle' line: 904 * What went wrong: Execution failed for task ':app:compileFlutterBuildDevRelease'. > Process 'command '/Users/runner/work/1/s/flutter/bin/flutter'' finished with non-zero exit value 1
output when running locally on windows:
flutter build apk --flavor dev --release -t lib/main_dev_test.dart You are building a fat APK that includes binaries for android-arm, android-arm64, android-x64. If you are deploying the app to the Play Store, it's recommended to use app bundles or split the APK to reduce the APK size. To generate an app bundle, run: flutter build appbundle --target-platform android-arm,android-arm64,android-x64 Learn more on: https://developer.android.com/guide/app-bundle To split the APKs per ABI, run: flutter build apk --target-platform android-arm,android-arm64,android-x64 --split-per-abi Learn more on: https://developer.android.com/studio/build/configure-apk-splits#configure-abi-split Running Gradle task 'assembleDevRelease'... Note: Some input files use unchecked or unsafe operations. Note: Recompile with -Xlint:unchecked for details. Calling mockable JAR artifact transform to create file: C:\Users\_USERFOLDER_\.gradle\caches\transforms-2\files-2.1\5760bf626ba5c024071f2e9f16ccfcc3\android.jar with input C:\Users\_USERFOLDER_\AppData\Local\Android\Sdk\platforms\android-28\android.jar Calling mockable JAR artifact transform to create file: C:\Users\_USERFOLDER_\.gradle\caches\transforms-2\files-2.1\08efdfe0d8cf00cccc6a03622959e0ad\android.jar with input C:\Users\_USERFOLDER_\AppData\Local\Android\Sdk\platforms\android-28\android.jar Calling mockable JAR artifact transform to create file: C:\Users\_USERFOLDER_\.gradle\caches\transforms-2\files-2.1\1a859f032ea56da6fdcf4706b3d23efa\android.jar with input C:\Users\_USERFOLDER_\AppData\Local\Android\Sdk\platforms\android-29\android.jar Removed unused resources: Binary resource data reduced from 759KB to 728KB: Removed 4% Running Gradle task 'assembleDevRelease'... Running Gradle task 'assembleDevRelease'... Done 270.2s (!) √ Built build\app\outputs\flutter-apk\app-dev-release.apk (21.0MB).
AppCenter Build Variant - devRelease (specified on the webUI)
appcenter-post-clone.sh:
#!/usr/bin/env bash # place this script in project/android/app/ cd .. # fail if any command fails set -e # debug log set -x #print appcenter's output folder echo "!~! Appcenter output: $APPCENTER_OUTPUT_DIRECTORY" #print app flavour specified echo "Building app for $APP_ENV flavour" entrypoint="placeholder_to_replace.dart" #set target main<>.dart file if [ "$APP_ENV" == "dev" ]; then entrypoint="main_dev_test.dart"; elif [ "$APP_ENV" == "beta" ]; then entrypoint="main_beta.dart"; elif [ "$APP_ENV" == "prod" ]; then entrypoint="main_release.dart"; fi echo "using entrypoint: $entrypoint" cd .. # choose a different release channel if you want - https://github.com/flutter/flutter/wiki/Flutter-build-release-channels # stable - recommended for production git clone -b stable https://github.com/flutter/flutter.git export PATH=`pwd`/flutter/bin:$PATH flutter channel beta flutter upgrade flutter doctor flutter build apk --release --flavor dev -t lib/$entrypoint # copy the APK where AppCenter will find it mkdir -p android/app/build/outputs/apk/; mv build/app/outputs/flutter-apk/app-$APP_ENV-release.apk $_
android/app/build.gradle:
def localProperties = new Properties() def localPropertiesFile = rootProject.file('local.properties') if (localPropertiesFile.exists()) { localPropertiesFile.withReader('UTF-8') { reader -> localProperties.load(reader) } } def flutterRoot = localProperties.getProperty('flutter.sdk') if (flutterRoot == null) { throw new GradleException("Flutter SDK not found. Define location with flutter.sdk in the local.properties file.") } def flutterVersionCode = localProperties.getProperty('flutter.versionCode') if (flutterVersionCode == null) { flutterVersionCode = '1' } def flutterVersionName = localProperties.getProperty('flutter.versionName') if (flutterVersionName == null) { flutterVersionName = '1.0' } apply plugin: 'com.android.application' apply plugin: 'kotlin-android' apply from: "$flutterRoot/packages/flutter_tools/gradle/flutter.gradle" android { compileSdkVersion 28 sourceSets { main.java.srcDirs += 'src/main/kotlin' } lintOptions { disable 'InvalidPackage' } defaultConfig { // TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html). applicationId "com.example.hello_world" minSdkVersion 21 targetSdkVersion 28 versionCode flutterVersionCode.toInteger() versionName flutterVersionName } signingConfigs { release { storeFile rootProject.file("app/android.keystore") storePassword System.getenv("APPCENTER_KEYSTORE_PASSWORD") keyAlias System.getenv("APPCENTER_KEY_ALIAS") keyPassword System.getenv("APPCENTER_KEY_PASSWORD") } } buildTypes { release { // TODO: Add your own signing config for the release build. // Signing with the debug keys for now, so `flutter run --release` works. signingConfig signingConfigs.release } } flavorDimensions "default" productFlavors { local { dimension "default" applicationIdSuffix ".dev" } dev { dimension "default" applicationIdSuffix ".dev" } beta { dimension "default" applicationIdSuffix ".beta" } prod { dimension "default" } } } flutter { source '../..' } dependencies { implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version" }
AppCenter build output:
//---OMITTED TOOLING CLONING--- Building flutter tool... Flutter is already up to date on channel beta Flutter 1.22.0-12.1.pre • channel beta • https://github.com/flutter/flutter.git Framework • revision 8b3760638a (8 days ago) • 2020-09-15 17:47:13 -0700 Engine • revision 4654fc6cf6 Tools • Dart 2.10.0 (build 2.10.0-110.3.beta) + flutter doctor Downloading Material fonts... 0.5s Downloading package sky_engine... 0.2s Downloading flutter_patched_sdk tools... 0.7s Downloading flutter_patched_sdk_product tools... 0.6s Downloading darwin-x64 tools... 1.6s Downloading libimobiledevice... 0.0s Downloading usbmuxd... 0.0s Downloading darwin-x64/font-subset tools... 0.3s Downloading android-arm-profile/darwin-x64 tools... 0.3s Downloading android-arm-release/darwin-x64 tools... 0.2s Downloading android-arm64-profile/darwin-x64 tools... 0.3s Downloading android-arm64-release/darwin-x64 tools... 0.3s Downloading android-x64-profile/darwin-x64 tools... 0.3s Downloading android-x64-release/darwin-x64 tools... 0.3s Doctor summary (to see all details, run flutter doctor -v): [✓] Flutter (Channel beta, 1.22.0-12.1.pre, on Mac OS X 10.14.6 18G6020, locale en) [!] Android toolchain - develop for Android devices (Android SDK version 30.0.2) ! Some Android licenses not accepted. To resolve this, run: flutter doctor --android-licenses [✓] Xcode - develop for iOS and macOS (Xcode 11.3.1) [!] Android Studio (not installed) [!] Connected device ! No devices available ! Doctor found issues in 3 categories. + flutter build apk --flavor dev --release -t lib/main_dev_test.dart Running "flutter pub get" in s... 6.9s You are building a fat APK that includes binaries for android-arm, android-arm64, android-x64. If you are deploying the app to the Play Store, it's recommended to use app bundles or split the APK to reduce the APK size. To generate an app bundle, run: flutter build appbundle --target-platform android-arm,android-arm64,android-x64 Learn more on: https://developer.android.com/guide/app-bundle To split the APKs per ABI, run: flutter build apk --target-platform android-arm,android-arm64,android-x64 --split-per-abi Learn more on: https://developer.android.com/studio/build/configure-apk-splits#configure-abi-split Running Gradle task 'assembleDevRelease'... Gradle 5.6.2 //---OMMITTED PACKAGE RESOLVE LINES--- > Task :clean > Task :app:clean UP-TO-DATE > Task :barcode_scan:clean UP-TO-DATE > Task :camera:clean UP-TO-DATE > Task :device_info:clean UP-TO-DATE > Task :flutter_secure_storage:clean UP-TO-DATE > Task :package_info:clean UP-TO-DATE > Task :path_provider:clean UP-TO-DATE > Task :permission_handler:clean UP-TO-DATE > Task :shared_preferences:clean UP-TO-DATE > Task :sqflite:clean UP-TO-DATE > Task :app:compileFlutterBuildDevRelease FAILED Error: Error when reading 'lib/main.dart': No such file or directory package:hello_world/main.dart: Error: No 'main' method found. Try adding a method named 'main' to your program. FAILURE: Build failed with an exception. * Where: Script '/Users/runner/work/1/s/flutter/packages/flutter_tools/gradle/flutter.gradle' line: 904 * What went wrong: Execution failed for task ':app:compileFlutterBuildDevRelease'. > Process 'command '/Users/runner/work/1/s/flutter/bin/flutter'' finished with non-zero exit value 1 * Try: 12 actionable tasks: 2 executed, 10 up-to-date Run with --stacktrace option to get the stack trace. Run with --info or --debug option to get more log output. Run with --scan to get full insights. * Get more help at https://help.gradle.org BUILD FAILED in 6s Error: /Users/runner/work/1/s/android/gradlew failed with return code: 1 at ChildProcess.<anonymous> (/Users/runner/work/_tasks/Gradle_8d8eebd8-2b94-4c97-85af-839254cc6da4/1.128.0/node_modules/vsts-task-lib/toolrunner.js:569:30) at emitTwo (events.js:106:13) at ChildProcess.emit (events.js:191:7) at maybeClose (internal/child_process.js:920:16) at Socket.<anonymous> (internal/child_process.js:351:11) at emitOne (events.js:96:13) at Socket.emit (events.js:188:7) at Pipe._handle.close [as _onclose] (net.js:509:12) ##[error]Error: /Users/runner/work/1/s/android/gradlew failed with return code: 1 ##[section]Finishing: Gradle Task ##[section]Starting: Checkout YardAppFlutter@feature/switchable_build_configurations to s ============================================================================== Task : Get sources Description : Get sources from a repository. Supports Git, TfsVC, and SVN repositories. Version : 1.0.0 Author : Microsoft Help : [More Information](https://go.microsoft.com/fwlink/?LinkId=798199) ============================================================================== Cleaning any cached credential from repository: YardAppFlutter (ExternalGit) ##[section]Finishing: Checkout YardAppFlutter@feature/switchable_build_configurations to s ##[section]Starting: Finalize Job Cleaning up task key Start cleaning up orphan processes. Terminate orphan process: pid (1609) (java) Terminate orphan process: pid (1550) (java) Terminate orphan process: pid (1428) (adb) ##[section]Finishing: Finalize Job ##[section]Finishing: Build
-
Phil Ives -Rain Everywhere over 3 yearsI have the same issue. My script is quite similar. I'm looking for a way to set the entry point to the gradle build with no success.
-