Flutter && gradlew 命令 && shell打包
无论是持续性编译还是平时开发,都离不开命令。Android有gradlew命令,flutter也有对应的命令,对于shell脚本命令,我们也经常用到。这篇博文只是简单整理,方便以后查阅。
gradlew命令
我们知道 Android打包使用的是gradlew命令,先来看一下gradlew命令
gradlew命令都可以使用简写,例如:
./gradlew assembleRelease 简写为:./gradlew aR
gradlew前面加./表示当前目录,具体查看以下博文:路径中的'.'和'..'还有'./'和'../'都是什么意思,所以这里需要切换到flutter的Android根目录之下,才能找到gradlew命令
image.png# 查看所有任务
./gradlew tasks --all
# 对某个module [moduleName] 的某个任务[TaskName] 运行.
/gradlew:moduleName:taskName
# 查看项目的依赖都依赖了哪些库。
gradlew :app:dependencies
#只编译清单文件,并查看具体日志,快速定位清单文件报错
gradlew :app:processDebugManifest --stacktrace:
# 查看构建版本
./gradlew -v
# 清除build文件夹
./gradlew clean
# 检查依赖并编译打包
./gradlew build
# 编译并安装debug包
./gradlew installDebug
# 编译并打印日志
./gradlew build --info
# 调试模式构建并打印日志
./gradlew build --info --debug --stacktrace
# 强制更新最新依赖,清除构建并构建
./gradlew clean --refresh-dependencies build
注意build命令把 debug、release环境的包都打出来的
如果需要指定构建使用如下命令
指定构建目标命令
# 编译并打Debug包
./gradlew assembleDebug./gradlew aD
# 编译并打Release的包
./gradlew assembleRelease./gradlew aR
构建并安装调试命令
# 编译并打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结合使用,如果出现类似 Task'install'isambiguousinroot project 这种错误,请查看配置的多个渠道然后修改命令为./gradlew install[productFlavorsName] app:assembleDebug来用命令构建调试
# Release模式打包并安装
./gradlew installRelease
# 卸载Release模式包
./gradlew uninstallRelease
# Release模式全部渠道打包
./gradlew assembleRelease
# Release模式 test 渠道打包
./gradlew assembleTestRelease
# debug release模式全部渠道打包
./gradlew assemble
#查看包依赖
./gradlew dependencies
# 编译时的依赖库
./gradlew app:dependencies --configuration compile
# 运行时的依赖库
./gradlew app:dependencies --configuration runtime
依赖管理
传递依赖特性
dependencies {
transitive true
}
手动配置transitive属性为false,阻止依赖的下载
强制
configurations.all{
// transitive false// 强制指定版本
resolutionStrategy{
force'org.hamcrest:hamcrest-core:1.3'// 强制不编译
all*.excludegroup:'org.hamcrest',
module:'hamcrest-core'
}
}
动态依赖特性
dependencies {
// 任意一个版本
compile group:'b',name:'b',version:'1.+'
// 最新的版本
compile group:'a',name:'a',version:'latest.integration'
}
查看详细依赖信息
#使用离线模式
./gradlew aDR --offline
#守护进程
./gradle build --daemon
#并行编译模式
./gradle build --parallel --parallel-threads=N
#按需编译模式
./gradle build --configure-on-demand
#不使用snapshot依赖仓库 前提是离线可以使用时
./gradlew clean aDR
通过增加--dwarf_stack_traces,--print-snapshot-sizes,--obfuscate命令压缩体积
./gradlew clean assembleRelease -Pextra-gen-snapshot-options="--dwarf_stack_traces,--print-snapshot-sizes,--obfuscate"
flutter 命令
前面说完gradlew命令,我们回过头来研究flutter。
flutter create
在指定的目录中,创建新的flutter项目,如果没有指定目录,则在当前目录下创建项目
flutter create ~/flutter #在家目录下的flutter目录项目
flutter create . #在当前目录下创建
flutter -v
查看APP所有日志的输出,对于调试是非常有用处,在调试时需要配合run命令使用
flutter -v run
flutter -d
切换在不同设备上运行app,如果没有指定设备,默认将会使用设备列表的第一个设备,这对于计算机连接多个设备时非常有用,可以使用设备名称或者设备id作为参数
flutter run -d NX569J #设备名称
flutter run -d devices_id #设备id
flutter analyze
编辑Flutter代码时,使用分析器检查代码是非常重要,默认是分析整个项目的代码,你也可以通过使用analysis_options.yaml
文件来排除不需要的代码分析
analyzer:
exclude:
- flutter/**
analysis_options.yaml
有时候你可能需要代码分析一直在运行,可以使用--watch选项
flutter analyze --watch
当运行分析命令flutter都执行一次pub get
命令,如果不需要运行,可以执行以下命令
flutter analyze --no-pub
flutter attach
相当于命令flutter run命令,不同之处在很多执行都是自己手动,比如热重载,
flutter bash-completion
在执行该命令时会输出一的配置脚本,脚本可以实现命令行提示的自动完成,可用于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
构建应用程序的apk,appbundle,aot,ios,IOS应用需要在Mac osx上构建
flutter build apk
flutter channel
切换flutter不同的版本,在执行flutter channel会输出不同分支信息,默认使用stable分支
flutter channel # 输出channel
flutter channel dev # 切换到dev channel
flutter clean
删除build/
和.dart_tool/
目录,清除缓存信息,避免之前不同版本代码的影响
flutter config
可以用于指定gradle,android sdk,android studio的目录或者开启,禁用analytics选项,analytics选项用于flutter工具的报告
flutter config --gradle-dir /gradle/
flutter devices
列出已经连接到计算机的设备
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
检查开发工具链是否完整安装,对于安装环境非常有用处,检查andorid licenses需要连接外网,请科学上网
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
快速自动更新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
执行flutter ui测试,该工具类似与web端的Selenium
,WebDriver
,Protractor
.你可以指定不同模式进行测试,可以是debug,profile,release,flavor模式,flavor模式可以指定平台规范,你还可以指定在不同的平台测试,甚至可以指定页面路由
flutter drive --debug --target-platform android-x86
flutter emulators
列出,创建,启动模拟器,默认是列出模拟器
flutter emulators --launch flutter_emulator #启动
flutter emulators # 列出
flutter emulators --create Pixel_API_28 # 创建
flutter format
按照dart代码规范格式项目代码文件,flutter format .
是当前项目所有文件,也可以指定目录或者文件
flutter format dartfile
flutter verion
列出或者切换flutter版本,默认是列出所有版本
flutter version
flutter version v1.5.8
flutter upgrade
更新flutter代码,实质就是git代码更新拉取,下载flutter sdk是git仓库的打包
flutter test
运行flutter单元测试,可以使用--start-paused
模式等待调试器的连接,--concurrency
可以指定并发任务数默认值是6
flutter test --concurrency=8
flutter install
安装app到一个已经连接的设备
flutter install
flutter screenshot
截取当前屏幕,默认是将图片输出到家目录下,使用-o指定输出目录
flutter screenshot -o /home/work
flutter packages
获取,测试,更新依赖包,flutter pub
将会传递剩余参数到dart工具的pub
flutter packages get
首先打开flutter的安装目录,进入flutter_tools-》gradle打开flutter.gradle
image.png
shell打包脚本
Android打包
多渠道
多渠道打包常规方式有两种,Flavor 和 --dart-define,后者是 Flutter1.17新增的命令行可选参数,比Flavor配置更简单,非常适合用于环境配置
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');
}
将渠道传给第三方埋点统计平台,比如友盟和bugly
FlutterUmengPlus.init(androidAppKey:"XXXXXXX", iOSAppKey:"XXXXXX", channel:"${EnvironmentConfig.APP_CHANNEL}",logEnable: false,);
android =》app=〉build.gradle添加以下信息
/// 获取渠道参数使用,这里设置一下默认值
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
// 设置新名称
def newApkName ="app_v${defaultConfig.versionName}_${defaultConfig.versionCode}_channel_${dartEnvironmentVariables.APP_CHANNEL}.apk"
outputFileName = new File(newApkName)
}
}
}
单个市场打包脚本fapk_channel.sh
echo "正在打包$1市场渠道,请耐心等待。。。"
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
进行打包某个渠道的时候只要输入命令即可
fapk_channel.sh HUAWEI 华为
全部市场打包脚本fapk_all_channel.sh
echo "打包全部市场渠道市场渠道,请耐心等待。。。"
fapk_channel.sh MyApp 腾讯应用宝;
fapk_channel.sh 360 360手机助手;
fapk_channel.sh Baidu 百度手机助手;
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 三星应用市场
iOS打包
iOS打包比较复杂一些,需要用到一个打包的脚本,这个脚本在Flutter SDK里,路径为packages/flutter_tools/bin
,有一个叫xcode_backend.sh
的脚本,首先分析这个脚本:
if [[ $# == 0 ]]; then
# Backwards-compatibility: if no args are provided, build.
BuildApp
else
case $1 in
"build")
BuildApp ;;
"thin")
ThinAppFrameworks ;;
"embed")
EmbedFlutterFrameworks ;;
esac
fi
可以看到这个脚本有三个功能,分别是:
- build
- thin
- embed
把这个脚本拷贝到工程的目录,运行
- 第一步
$/bin/sh xcode_backend.sh build
然后你会发现有报错,如下:
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.
这是因为少了一些环境变量,要把这些变量加上:
export FLUTTER_BUILD_MODE="" //有三个值: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要支持的平台
- 第二步
$/bin/sh xcode_backend.sh thin
同样也要加上环境变量:
export SOURCE_ROOT=".../.ios/Flutter" //Flutter iOS代码的目录
export ARCHS="armv7 arm64" //Flutter打包的Framework要支持的平台
export TARGET_BUILD_DIR="${SOURCE_ROOT}" //build生成的路径
export app_path="${TARGET_BUILD_DIR}/Flutter" //Flutter打包的Framework所在的路径
export frameworks_dir="${app_path}" //Flutter打包的Framework所在的路径
综上,要加的环境变量如下:
export FLUTTER_BUILD_MODE="" //有三个值: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要支持的平台
export TARGET_BUILD_DIR="${SOURCE_ROOT}" //build生成的路径
export app_path="${TARGET_BUILD_DIR}/Flutter" //Flutter打包的Framework所在的路径
export frameworks_dir="${app_path}" //Flutter打包的Framework所在的路径
运行的命令如下:
$/bin/sh xcode_backend.sh build
$/bin/sh xcode_backend.sh thin
生成产物在.../.iOS/Flutter
中查看,如果想修改生成产物的路径,修改脚本里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"