Flutter && gradlew 命令 && shell打包腳本

無(wú)論是持續(xù)性編譯還是平時(shí)開發(fā),都離不開命令。Android有g(shù)radlew命令,flutter也有對(duì)應(yīng)的命令,對(duì)于shell腳本命令,我們也經(jīng)常用到。這篇博文只是簡(jiǎn)單整理,方便以后查閱。

對(duì)于部分
Shell(Bash)多命令順序執(zhí)行方法詳解

gradlew命令

我們知道 Android打包使用的是gradlew命令,先來(lái)看一下gradlew命令

gradlew命令都可以使用簡(jiǎn)寫,例如:

./gradlew assembleRelease 簡(jiǎn)寫為:./gradlew aR

gradlew前面加./表示當(dāng)前目錄,具體查看以下博文:路徑中的'.'和'..'還有'./'和'../'都是什么意思,所以這里需要切換到flutter的Android根目錄之下,才能找到gradlew命令

image.png
# 查看所有任務(wù)

./gradlew tasks --all

# 對(duì)某個(gè)module [moduleName] 的某個(gè)任務(wù)[TaskName] 運(yùn)行.

/gradlew:moduleName:taskName

# 查看項(xiàng)目的依賴都依賴了哪些庫(kù)。

gradlew :app:dependencies 

#只編譯清單文件,并查看具體日志,快速定位清單文件報(bào)錯(cuò)

gradlew :app:processDebugManifest --stacktrace:

# 查看構(gòu)建版本

./gradlew -v

# 清除build文件夾

./gradlew clean

# 檢查依賴并編譯打包

./gradlew build

# 編譯并安裝debug包

./gradlew installDebug

# 編譯并打印日志

./gradlew build --info

# 調(diào)試模式構(gòu)建并打印日志

./gradlew build --info --debug --stacktrace

# 強(qiáng)制更新最新依賴,清除構(gòu)建并構(gòu)建

./gradlew clean --refresh-dependencies build

注意build命令把 debug、release環(huán)境的包都打出來(lái)的

如果需要指定構(gòu)建使用如下命令

指定構(gòu)建目標(biāo)命令

# 編譯并打Debug包

./gradlew assembleDebug./gradlew aD

# 編譯并打Release的包

./gradlew assembleRelease./gradlew aR

構(gòu)建并安裝調(diào)試命令

# 編譯并打Debug包

./gradlew assembleDebug

# 編譯app module 并打Debug包

./gradlew install app:assembleDebug

# 編譯并打Release的包(生成的aar包就在`.android/Flutter/build/outputs/aar/`目錄下)

./gradlew assembleRelease

#  Release模式打包并安裝

./gradlew installRelease

# 卸載Release模式包

./gradlew uninstallRelease

多渠道打包

assemble還可以和productFlavors結(jié)合使用,如果出現(xiàn)類似 Task'install'isambiguousinroot project 這種錯(cuò)誤,請(qǐng)查看配置的多個(gè)渠道然后修改命令為./gradlew install[productFlavorsName] app:assembleDebug來(lái)用命令構(gòu)建調(diào)試

# Release模式打包并安裝

./gradlew installRelease

# 卸載Release模式包

./gradlew uninstallRelease

# Release模式全部渠道打包

./gradlew assembleRelease

# Release模式 test 渠道打包

./gradlew assembleTestRelease

# debug release模式全部渠道打包

./gradlew assemble

#查看包依賴

./gradlew dependencies

# 編譯時(shí)的依賴庫(kù)

./gradlew app:dependencies --configuration compile

# 運(yùn)行時(shí)的依賴庫(kù)

./gradlew app:dependencies --configuration runtime

依賴管理
傳遞依賴特性

dependencies {
    transitive true
}

手動(dòng)配置transitive屬性為false,阻止依賴的下載

強(qiáng)制

configurations.all{
// transitive false// 強(qiáng)制指定版本
  resolutionStrategy{
      force'org.hamcrest:hamcrest-core:1.3'// 強(qiáng)制不編譯
      all*.excludegroup:'org.hamcrest',
      module:'hamcrest-core'
  }
}

動(dòng)態(tài)依賴特性

dependencies {
  // 任意一個(gè)版本
  compile group:'b',name:'b',version:'1.+'
  // 最新的版本
  compile group:'a',name:'a',version:'latest.integration'
}

查看詳細(xì)依賴信息

#使用離線模式

./gradlew aDR --offline

#守護(hù)進(jìn)程

./gradle build --daemon

#并行編譯模式

./gradle build --parallel --parallel-threads=N

#按需編譯模式

./gradle build --configure-on-demand

#不使用snapshot依賴倉(cāng)庫(kù) 前提是離線可以使用時(shí)

./gradlew clean aDR

通過(guò)增加--dwarf_stack_traces,--print-snapshot-sizes,--obfuscate命令壓縮體積

./gradlew clean assembleRelease -Pextra-gen-snapshot-options="--dwarf_stack_traces,--print-snapshot-sizes,--obfuscate"

flutter 命令

前面說(shuō)完gradlew命令,我們回過(guò)頭來(lái)研究flutter。

flutter create

在指定的目錄中,創(chuàng)建新的flutter項(xiàng)目,如果沒(méi)有指定目錄,則在當(dāng)前目錄下創(chuàng)建項(xiàng)目

flutter create ~/flutter #在家目錄下的flutter目錄項(xiàng)目
flutter create . #在當(dāng)前目錄下創(chuàng)建

flutter -v

查看APP所有日志的輸出,對(duì)于調(diào)試是非常有用處,在調(diào)試時(shí)需要配合run命令使用

flutter -v run

flutter -d

切換在不同設(shè)備上運(yùn)行app,如果沒(méi)有指定設(shè)備,默認(rèn)將會(huì)使用設(shè)備列表的第一個(gè)設(shè)備,這對(duì)于計(jì)算機(jī)連接多個(gè)設(shè)備時(shí)非常有用,可以使用設(shè)備名稱或者設(shè)備id作為參數(shù)

flutter run -d NX569J #設(shè)備名稱
flutter run -d devices_id #設(shè)備id

flutter analyze

編輯Flutter代碼時(shí),使用分析器檢查代碼是非常重要,默認(rèn)是分析整個(gè)項(xiàng)目的代碼,你也可以通過(guò)使用analysis_options.yaml文件來(lái)排除不需要的代碼分析

analyzer:
  exclude:
    - flutter/**

analysis_options.yaml

有時(shí)候你可能需要代碼分析一直在運(yùn)行,可以使用--watch選項(xiàng)

flutter analyze --watch

當(dāng)運(yùn)行分析命令flutter都執(zhí)行一次pub get命令,如果不需要運(yùn)行,可以執(zhí)行以下命令

flutter analyze --no-pub 

flutter attach

相當(dāng)于命令flutter run命令,不同之處在很多執(zhí)行都是自己手動(dòng),比如熱重載,

flutter bash-completion

在執(zhí)行該命令時(shí)會(huì)輸出一的配置腳本,腳本可以實(shí)現(xiàn)命令行提示的自動(dòng)完成,可用于zsh,bash的配置,將腳本添加到~/.bashrc或者~/.zshrc

if type complete &>/dev/null; then
  __flutter_completion() {
    local si="$IFS"
    IFS=$'\n' COMPREPLY=($(COMP_CWORD="$COMP_CWORD" \
                           COMP_LINE="$COMP_LINE" \
                           COMP_POINT="$COMP_POINT" \
                           flutter completion -- "${COMP_WORDS[@]}" \
                           2>/dev/null)) || return $?
    IFS="$si"
  }
  complete -F __flutter_completion flutter
elif type compdef &>/dev/null; then
  __flutter_completion() {
    si=$IFS
    compadd -- $(COMP_CWORD=$((CURRENT-1)) \
                 COMP_LINE=$BUFFER \
                 COMP_POINT=0 \
                 flutter completion -- "${words[@]}" \
                 2>/dev/null)
    IFS=$si
  }
  compdef __flutter_completion flutter
elif type compctl &>/dev/null; then
  __flutter_completion() {
    local cword line point words si
    read -Ac words
    read -cn cword
    let cword-=1
    read -l line
    read -ln point
    si="$IFS"
    IFS=$'\n' reply=($(COMP_CWORD="$cword" \
                       COMP_LINE="$line" \
                       COMP_POINT="$point" \
                       flutter completion -- "${words[@]}" \
                       2>/dev/null)) || return $?
    IFS="$si"
  }
  compctl -K __flutter_completion flutter
fi

flutter build

構(gòu)建應(yīng)用程序的apk,appbundle,aot,ios,IOS應(yīng)用需要在Mac osx上構(gòu)建

flutter build apk

flutter channel

切換flutter不同的版本,在執(zhí)行flutter channel會(huì)輸出不同分支信息,默認(rèn)使用stable分支

flutter channel # 輸出channel
flutter channel dev # 切換到dev channel

flutter clean

刪除build/.dart_tool/目錄,清除緩存信息,避免之前不同版本代碼的影響

flutter config

可以用于指定gradle,android sdk,android studio的目錄或者開啟,禁用analytics選項(xiàng),analytics選項(xiàng)用于flutter工具的報(bào)告

flutter config --gradle-dir /gradle/

flutter devices

列出已經(jīng)連接到計(jì)算機(jī)的設(shè)備

flutter devices
NX569J                    ? 192.168.43.1:5555 ? android-arm64 ? Android 7.1.2 (API 25)
Android SDK built for x86 ? emulator-5554     ? android-x86   ? Android 9 (API 28) (emulator)

flutter doctor

檢查開發(fā)工具鏈?zhǔn)欠裢暾惭b,對(duì)于安裝環(huán)境非常有用處,檢查andorid licenses需要連接外網(wǎng),請(qǐng)科學(xué)上網(wǎng)

flutter doctor

Doctor summary (to see all details, run flutter doctor -v):
[?] Flutter (Channel stable, v1.2.1, on Linux, locale en_US.UTF-8)
[?] Android toolchain - develop for Android devices (Android SDK version 28.0.3)
[?] Android Studio (version 3.3)
[?] VS Code (version 1.33.1)
[?] Connected device (2 available)

? No issues found!

flutter pub outdated

查詢展示依賴包可更新的版本信息

Showing outdated packages.
[*] indicates versions that are not the latest available.

Package Name     Current     Upgradable  Resolvable  Latest   

direct dependencies:
cupertino_icons  *0.1.3      *0.1.3      1.0.3       1.0.3    
fixnum           *0.10.11    *0.10.11    1.0.0       1.0.0    
package_info     *0.3.2+1    *0.3.2+1    2.0.2       2.0.2    
protobuf         *0.13.16+1  *0.13.16+1  2.0.0       2.0.0    

transitive dependencies:
meta             *1.3.0      *1.3.0      *1.3.0      1.7.0    

transitive dev_dependencies:
async            *2.6.1      *2.6.1      *2.6.1      2.8.2    
charcode         *1.2.0      *1.2.0      *1.2.0      1.3.1    
matcher          *0.12.10    *0.12.10    *0.12.10    0.12.11  
test_api         *0.3.0      *0.3.0      *0.3.0      0.4.3    

4  dependencies are constrained to versions that are older than a resolvable version.

flutter pub upgrade --major-versions

快速自動(dòng)更新app依賴

Resolving dependencies...
  async 2.6.1 (2.8.2 available)
  boolean_selector 2.1.0
  characters 1.1.0
  charcode 1.2.0 (1.3.1 available)
  clock 1.1.0
  collection 1.15.0
> cupertino_icons 1.0.3 (was 0.1.3)
  fake_async 1.2.0
> fixnum 1.0.0 (was 0.10.11)
  flutter 0.0.0 from sdk flutter
  flutter_test 0.0.0 from sdk flutter
  matcher 0.12.10 (0.12.11 available)
  meta 1.3.0 (1.7.0 available)
> package_info 2.0.2 (was 0.3.2+1)
  path 1.8.0
> protobuf 2.0.0 (was 0.13.16+1)
  sky_engine 0.0.99 from sdk flutter
  source_span 1.8.1
  stack_trace 1.10.0
  stream_channel 2.1.0
  string_scanner 1.1.0
  term_glyph 1.2.0
  test_api 0.3.0 (0.4.3 available)
  typed_data 1.3.0
  vector_math 2.1.0
Downloading protobuf 2.0.0...
Changed 4 dependencies!
5 packages have newer versions incompatible with dependency constraints.
Try `flutter pub outdated` for more information.

Changed 4 constraints in pubspec.yaml:
  package_info: ^0.3.2+1 -> ^2.0.2
  fixnum: ^0.10.9 -> ^1.0.0
  protobuf: ^0.13.4 -> ^2.0.0
  cupertino_icons: ^0.1.2 -> ^1.0.3

flutter drive

執(zhí)行flutter ui測(cè)試,該工具類似與web端的Selenium,WebDriver,Protractor.你可以指定不同模式進(jìn)行測(cè)試,可以是debug,profile,release,flavor模式,flavor模式可以指定平臺(tái)規(guī)范,你還可以指定在不同的平臺(tái)測(cè)試,甚至可以指定頁(yè)面路由

flutter drive --debug --target-platform android-x86

flutter emulators

列出,創(chuàng)建,啟動(dòng)模擬器,默認(rèn)是列出模擬器

flutter emulators --launch flutter_emulator #啟動(dòng)
flutter emulators # 列出
flutter emulators --create Pixel_API_28 # 創(chuàng)建

flutter format

按照dart代碼規(guī)范格式項(xiàng)目代碼文件,flutter format .是當(dāng)前項(xiàng)目所有文件,也可以指定目錄或者文件

flutter format dartfile

flutter verion

列出或者切換flutter版本,默認(rèn)是列出所有版本

flutter version
flutter version v1.5.8

flutter upgrade

更新flutter代碼,實(shí)質(zhì)就是git代碼更新拉取,下載flutter sdk是git倉(cāng)庫(kù)的打包

flutter test

運(yùn)行flutter單元測(cè)試,可以使用--start-paused模式等待調(diào)試器的連接,--concurrency可以指定并發(fā)任務(wù)數(shù)默認(rèn)值是6

flutter test --concurrency=8

flutter install

安裝app到一個(gè)已經(jīng)連接的設(shè)備

flutter install

flutter screenshot

截取當(dāng)前屏幕,默認(rèn)是將圖片輸出到家目錄下,使用-o指定輸出目錄

flutter screenshot -o /home/work

flutter packages

獲取,測(cè)試,更新依賴包,flutter pub 將會(huì)傳遞剩余參數(shù)到dart工具的pub

flutter packages get

首先打開flutter的安裝目錄,進(jìn)入flutter_tools-》gradle打開flutter.gradle


image.png

shell打包腳本

Android打包

多渠道

多渠道打包常規(guī)方式有兩種,F(xiàn)lavor 和 --dart-define,后者是 Flutter1.17新增的命令行可選參數(shù),比Flavor配置更簡(jiǎn)單,非常適合用于環(huán)境配置

channel_dev.dart

class EnvironmentConfig{
  static const APP_CHANNEL = String.fromEnvironment('APP_CHANNEL',defaultValue:"default");
  static const APP_STORE_NAME = String.fromEnvironment('APP_STORE_NAME');
}

將渠道傳給第三方埋點(diǎn)統(tǒng)計(jì)平臺(tái),比如友盟和bugly

FlutterUmengPlus.init(androidAppKey:"XXXXXXX", iOSAppKey:"XXXXXX", channel:"${EnvironmentConfig.APP_CHANNEL}",logEnable: false,);

android =》app=〉build.gradle添加以下信息

/// 獲取渠道參數(shù)使用,這里設(shè)置一下默認(rèn)值
def dartEnvironmentVariables = [
        APP_CHANNEL: 'default',
        APP_STORE_NAM: 'yatsar',
        APP_STORE_URL:''
]
///攔截dart-defines 獲取外部輸入值,添加到dartEnvironmentVariables
if (project.hasProperty('dart-defines')) {
    dartEnvironmentVariables = dartEnvironmentVariables + project.property('dart-defines')
            .split(',')
            .collectEntries { entry ->
                def pair = URLDecoder.decode(entry, "utf-8").split('=')
                [(pair.first()): pair.last()]
            }
}

android{}下更改apk名字

 // 重命名 apk
    applicationVariants.all { variant ->
        variant.outputs.all { output ->
            if(variant.buildType.name == "release"){
                // 獲取版本
                def versionName = variant.versionName
                def versionCode = variant.versionName
                // 設(shè)置新名稱
                def newApkName ="app_v${defaultConfig.versionName}_${defaultConfig.versionCode}_channel_${dartEnvironmentVariables.APP_CHANNEL}.apk"
                outputFileName = new File(newApkName)
            }
        }
    }
單個(gè)市場(chǎng)打包腳本fapk_channel.sh
echo "正在打包$1市場(chǎng)渠道,請(qǐng)耐心等待。。。"
cd C:/Users/Administrator/StudioProjects/flutter_beauty/
flutter clean
echo "flutter clean end: $?"
if [$? -ne 0];then
    echo "clean faild"
else
    echo "clean success"
fi

flutter build apk  --dart-define=APP_CHANNEL=$1  --dart-define=APP_STORE_NAME=$2
cd build/app/outputs/flutter-apk/

date_time=$(date "+%Y%m%d")

build_dir=C:/myApp/output/$date_time/$1

if [ ! -d "$build_dir" ];then
     mkdir -p $build_dir
fi

time=$(date "+%Y%m%d%H%M%S")

cp -R *release.apk  $build_dir/$1_$time.apk

進(jìn)行打包某個(gè)渠道的時(shí)候只要輸入命令即可

fapk_channel.sh HUAWEI  華為
全部市場(chǎng)打包腳本fapk_all_channel.sh
echo "打包全部市場(chǎng)渠道市場(chǎng)渠道,請(qǐng)耐心等待。。。"

fapk_channel.sh MyApp 騰訊應(yīng)用寶;
fapk_channel.sh 360  360手機(jī)助手;
fapk_channel.sh Baidu 百度手機(jī)助手;
fapk_channel.sh Yatsar Yatsar
fapk_channel.sh HUAWEI  華為;
fapk_channel.sh OPPO OPPO;
fapk_channel.sh VIVO VIVO;
fapk_channel.sh Mi 小米;
fapk_channel.sh SamSung 三星應(yīng)用市場(chǎng)

iOS打包

iOS打包比較復(fù)雜一些,需要用到一個(gè)打包的腳本,這個(gè)腳本在Flutter SDK里,路徑為packages/flutter_tools/bin,有一個(gè)叫xcode_backend.sh的腳本,首先分析這個(gè)腳本:

if [[ $# == 0 ]]; then
  # Backwards-compatibility: if no args are provided, build.
  BuildApp
else
  case $1 in
    "build")
      BuildApp ;;
    "thin")
      ThinAppFrameworks ;;
    "embed")
      EmbedFlutterFrameworks ;;
  esac
fi

可以看到這個(gè)腳本有三個(gè)功能,分別是:

  1. build
  2. thin
  3. embed

把這個(gè)腳本拷貝到工程的目錄,運(yùn)行

  1. 第一步
$/bin/sh xcode_backend.sh build

然后你會(huì)發(fā)現(xiàn)有報(bào)錯(cuò),如下:

ERROR: Unknown FLUTTER_BUILD_MODE: .
Valid values are 'Debug', 'Profile', or 'Release' (case insensitive).
This is controlled by the FLUTTER_BUILD_MODE environment varaible.
If that is not set, the CONFIGURATION environment variable is used.

這是因?yàn)樯倭艘恍┉h(huán)境變量,要把這些變量加上:

export FLUTTER_BUILD_MODE="" //有三個(gè)值:Debug  Profile   Release
export FLUTTER_ROOT="" //Flutter SDK的目錄
export FLUTTER_APPLICATION_PATH=""  //工程目錄
export SOURCE_ROOT="${FLUTTER_APPLICATION_PATH}/.ios/Flutter"  //Flutter iOS代碼的目錄
export FLUTTER_TARGET="lib/main.dart"  //dart代碼
export FLUTTER_BUILD_DIR="build" //build生成的路徑
export ARCHS="armv7 arm64" //Flutter打包的Framework要支持的平臺(tái)
  1. 第二步
$/bin/sh xcode_backend.sh thin

同樣也要加上環(huán)境變量:

export SOURCE_ROOT=".../.ios/Flutter" //Flutter iOS代碼的目錄
export ARCHS="armv7 arm64" //Flutter打包的Framework要支持的平臺(tái)
export TARGET_BUILD_DIR="${SOURCE_ROOT}" //build生成的路徑
export app_path="${TARGET_BUILD_DIR}/Flutter" //Flutter打包的Framework所在的路徑
export frameworks_dir="${app_path}"  //Flutter打包的Framework所在的路徑

綜上,要加的環(huán)境變量如下:

export FLUTTER_BUILD_MODE="" //有三個(gè)值:Debug  Profile   Release
export FLUTTER_ROOT="" //Flutter SDK的目錄
export FLUTTER_APPLICATION_PATH=""  //工程目錄
export SOURCE_ROOT="${FLUTTER_APPLICATION_PATH}/.ios/Flutter"  //Flutter iOS代碼的目錄
export FLUTTER_TARGET="lib/main.dart"  //dart代碼
export FLUTTER_BUILD_DIR="build" //build生成的路徑
export ARCHS="armv7 arm64" //Flutter打包的Framework要支持的平臺(tái)
export TARGET_BUILD_DIR="${SOURCE_ROOT}" //build生成的路徑
export app_path="${TARGET_BUILD_DIR}/Flutter" //Flutter打包的Framework所在的路徑
export frameworks_dir="${app_path}"  //Flutter打包的Framework所在的路徑

運(yùn)行的命令如下:

$/bin/sh xcode_backend.sh build
$/bin/sh xcode_backend.sh thin

生成產(chǎn)物在.../.iOS/Flutter中查看,如果想修改生成產(chǎn)物的路徑,修改腳本里derived_dir的值,如下:

  local derived_dir="${SOURCE_ROOT}/Flutter/Flutter"
  if [[ -e "${project_path}/.ios" ]]; then
    derived_dir="${project_path}/.ios/Flutter/Flutter"
  fi
flutter --suppress-analytics build aot --output-dir=build/aot --target-platform=ios --target=lib/main.dart --release --ios-arch=arm64 --extra-gen-snapshot-options="--dwarf_stack_traces,--print-snapshot-sizes,--print_instructions_sizes_to=build/aot.json"
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

推薦閱讀更多精彩內(nèi)容