使用风味使用 MS AppCenter 构建 Flutter android APK 的问题

Posted

技术标签:

【中文标题】使用风味使用 MS AppCenter 构建 Flutter android APK 的问题【英文标题】:Issue building Flutter android APK with MS AppCenter using flavors 【发布时间】:2021-01-10 17:36:36 【问题描述】:

我一直在关注一系列文章,试图在 MS Appcenter 上构建 Flutter 应用,使用各种风格来实现应用环境(即 dev/test/live)。

为了实现这一点,我使用this article 中所示的单独的main-<environment>.dart 入口文件方法,并遵循this article 来配置Appcenter。

我在构建 android apk 时遇到问题,因为缺少 main.dart。我认为将-t 参数传递给构建命令可以处理这个问题?

我将在下面添加构建脚本和日志,但正在执行的颤动命令是这样的:flutter build apk --flavor dev --release -t lib/main_dev_test.dart

flutter build apk 命令似乎可以正常完成,但是在 gradle 任务步骤中构建失败并显示以下错误消息:

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

在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 构建变体 - devRelease(在 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 构建输出:

//---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

【问题讨论】:

我也有同样的问题。我的脚本非常相似。我正在寻找一种方法来设置 gradle 构建的入口点,但没有成功。 【参考方案1】:

我在使用 AppCenter 时遇到了同样的问题,我遇到了这个 answer,表明问题是由 gradle 中的一些构建步骤引起的,建议在您的项目中使用 lib/main.dart

所以我通过使用lib/main.dart 构建生产版本解决了这个问题。唯一要更改的文件是appcenter-post-clone.sh

看看我的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 $_

【讨论】:

以上是关于使用风味使用 MS AppCenter 构建 Flutter android APK 的问题的主要内容,如果未能解决你的问题,请参考以下文章

iOS Build在Xcode中表现不错,但Appcenter.ms失败了

启用 sonarscanner 时 Appcenter iOS 构建失败

MS AppCenter 和 Azure DevOps(前 VSTS)之间的主要区别是啥?

从 Appcenter 创建构建时,FirebaseCrashlytics 崩溃不报告崩溃

UWP 始终在测试文件夹中发布输出

Gradle 在 Android Studio 和 AppCenter 中都找不到 Flutter 构建的 APK