無(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命令
# 查看所有任務(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
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è)功能,分別是:
- build
- thin
- embed
把這個(gè)腳本拷貝到工程的目錄,運(yùn)行
- 第一步
$/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)
- 第二步
$/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"