把简单的事情,做得出人意料的精彩。 —《态度》
写在前面
过了这么久,2.0终于来了,对比1.0还是有不少改动的,在1.0的前提下继续优化,加入了选项,不仅可以打包apk,也可以打包aar,对脚本中的错误做了处理。没有看过1.0的小可爱赶快去了解下再回来哦。
送你一直穿云箭,《签名脚本》来相见
搭建环境
1.修改build目录
在《签名脚本1.0》中,与Project同级的build目录名称修改为script。
2.修改build.sh
build.sh是一个可执行的脚本文件,它是该环境的核心。
#!/bin/bash
#
# ----------------------------------
# Build Android Project Script.
# ----------------------------------
#
version=2.0
author=junxiang.zhang
install=false
module=app
main() {
init_params $@
}
init_params() {
options=$(getopt -o vha:l: --long version,help,app:,lib:,install: -- $@)
if [ $? -ne 0 ]; then
usage
exit 1
fi
eval set -- $options
while true; do
case $1 in
-v | --version)
version
;;
-h | --help)
usage
exit 0
;;
-a | --app)
format_param $2
shift 2
;;
-l | --lib)
module=lib
format_param $2
shift 2
;;
--install)
install=true
format_param $2
shift 2
;;
--)
shift
break
;;
*)
usage
exit 1
;;
esac
done
}
format_param() {
param=$1
if [ -z param ]; then
usage
exit 1
fi
projectName=${param%/*}
moduleName=${param#*/}
verify_name
}
verify_name() {
if [ -z $projectName ]; then
failed 'THE PROJECT NAME IS EMPTY'
fi
if [ -z $moduleName ]; then
failed 'THE MODULE NAME IS EMPTY'
fi
projectDir=../$projectName
moduleDir=$projectDir/$moduleName
if [ ! -d $projectDir ]; then
failed 'THE PROJECT DOES NOT EXIST'
fi
if [ ! -d $moduleDir ]; then
failed 'THE MODULE DOES NOT EXIST'
fi
verify_output_dir
}
verify_output_dir() {
outputsDir=outputs
if [ ! -d $outputsDir ]; then
mkdir outputs
fi
cd $outputsDir
if [ $module == app ]; then
fileDir=apk
else
if [ $module == lib ]; then
fileDir=lib
fi
fi
if [ ! -d $fileDir ]; then
mkdir $fileDir
fi
cd ../
build
}
build() {
cd $projectDir
if [ $module == app ]; then
./gradlew clean &&
./gradlew :$moduleName:aDebug || result=$?
else
if [ $module == lib ]; then
./gradlew :$moduleName:clean &&
./gradlew :$moduleName:aRelease || result=$?
fi
fi
cd ../script
if [ -z $result ]; then
copy
fi
}
copy() {
if [ $module == app ]; then
inputFile=$moduleDir/build/outputs/apk/debug/$moduleName-debug.apk
else
if [ $module == lib ]; then
inputFile=$moduleDir/build/outputs/aar/$moduleName-release.aar
fi
fi
cp -p $inputFile $outputsDir/$fileDir/ || result=$?
if [ -z $result ]; then
signature
else
exit 1
fi
}
signature() {
if [ $module == app ]; then
inputApk=$outputsDir/$fileDir/$moduleName-debug.apk
outputApk=$outputsDir/$fileDir/$projectName-signed.apk
java -jar signapk/signapk.jar signapk/platform.x509.pem signapk/platform.pk8 $inputApk $outputApk
rm -f $inputApk
install
else
if [ $module == lib ]; then
inputAar=$outputsDir/$fileDir/$moduleName-release.aar
outputAar=$outputsDir/$fileDir/$projectName-release.aar
mv $inputAar $outputAar
successful 'BUILD LIBRARY SUCCESSFUL'
fi
fi
}
install() {
if [ $install == true ]; then
adb install -r -t $outputApk || result=$?
if [ -z $result ]; then
successful 'INSTALL APPLICATION SUCCESSFUL'
fi
else
successful 'BUILD APPLICATION SUCCESSFUL'
fi
}
usage() {
cat <<!EOF!
USAGE:: ./build.sh [option] [param]
options:
-v, -version Print version info.
-h, --help Shows this help message.
-a, --app The project you build is the application.
-l, --lib The project you build is the library.
--install Build and install the application.
param:
project/module
!EOF!
}
version() {
printf "Version = $version\nAuthor = $author\n"
exit 0
}
successful() {
echo -e '\033[32m'$1'\033[0m'
exit 0
}
failed() {
echo -e '\033[31m'$1'\033[0m'
exit 1
}
main $@
脚本讲解
这次把相应的功能都封装成了函数,每个函数单独负责自己的部分。
#!/bin/bash
#
# ----------------------------------
# Build Android Project Script.
# ----------------------------------
#
# 版本号
version=2.0
# 创作者
author=junxiang.zhang
# 该变量只针对application,false代表只构造不安装apk,
# true则代表即构造又安装apk,默认值为false
install=false
# 区分当前构造的模块是application还是library,默认值为application
module=app
# 主函数
main() {
init_params $@
}
# 初始化参数
init_params() {
# 处理选项,-o代表短选项,--long代表长选项,$@代表参数列表
options=$(getopt -o vha:l: --long version,help,app:,lib:,install: -- $@)
# $?代表参数的个数,如果没有参数,则调用usage函数,退出
if [ $? -ne 0 ]; then
usage
exit 1
fi
# 使用while遍历参数
eval set -- $options
while true; do
case $1 in
-v | --version)
version
;;
-h | --help)
usage
exit 0
;;
-a | --app)
format_param $2
shift 2
;;
-l | --lib)
module=lib
format_param $2
shift 2
;;
--install)
install=true
format_param $2
shift 2
;;
--)
shift
break
;;
*)
usage
exit 1
;;
esac
done
}
# 格式化参数
format_param() {
# $1对应格式为MyApplication/app,
# 如果参数是空的,就打印帮助,退出
param=$1
if [ -z param ]; then
usage
exit 1
fi
# 项目名称,对应MyApplication,截取/左边
projectName=${param%/*}
# 工程名称,对应app,截取/右边
moduleName=${param#*/}
# 如果项目名称和工程名称截取成功,就要验证名称的合法性
verify_name
}
# 验证名称
verify_name() {
# 如果项目名称是空的,则失败,退出
if [ -z $projectName ]; then
failed 'THE PROJECT NAME IS EMPTY'
fi
# 如果工程名称是空的,则失败,退出
if [ -z $moduleName ]; then
failed 'THE MODULE NAME IS EMPTY'
fi
# 项目目录,和build目录同级,所以先../回到同级目录
projectDir=../$projectName
# 工程目录,对应MyApplication/app
moduleDir=$projectDir/$moduleName
# 如果项目目录不存在,则失败,退出
if [ ! -d $projectDir ]; then
failed 'THE PROJECT DOES NOT EXIST'
fi
# 如果功工程目录不存在,则失败,退出
if [ ! -d $moduleDir ]; then
failed 'THE MODULE DOES NOT EXIST'
fi
# 如果项目目录和工程目录都存在,就要去验证文件输出目录
verify_output_dir
}
# 验证文件输出目录
verify_output_dir() {
# 文件输出目录的名称为outputs,如果不存在就创建
outputsDir=outputs
if [ ! -d $outputsDir ]; then
mkdir outputs
fi
# 进入outputs目录,判断module是application还是library,
# 从而定义不同的目录名称
cd $outputsDir
if [ $module == app ]; then
fileDir=apk
else
if [ $module == lib ]; then
fileDir=lib
fi
fi
# 如果fileDir目录不存在,就创建
if [ ! -d $fileDir ]; then
mkdir $fileDir
fi
cd ../
# 文件输出目录没问题就开始编译了
build
}
# 构造apk/aar
build() {
# 因为编译需要用到gradlew,所以要进入项目目录,
# result用于接收编译结果
cd $projectDir
if [ $module == app ]; then
./gradlew clean &&
./gradlew :$moduleName:aDebug || result=$?
else
if [ $module == lib ]; then
./gradlew :$moduleName:clean &&
./gradlew :$moduleName:aRelease || result=$?
fi
fi
# 编译结束,无论成功与否,都要回到script目录
cd ../script
# 如果result不为空,说明编译成功了,接下来执行拷贝
if [ -z $result ]; then
copy
fi
}
# 拷贝
copy() {
# 根据module获取相应的文件路径,这里的路径是默认的
if [ $module == app ]; then
inputFile=$moduleDir/build/outputs/apk/debug/$moduleName-debug.apk
else
if [ $module == lib ]; then
inputFile=$moduleDir/build/outputs/aar/$moduleName-release.aar
fi
fi
# 将构造好的文件拷贝到目标目录
cp -p $inputFile $outputsDir/$fileDir/ || result=$?
# 如果拷贝成功就执行签名,否则退出
if [ -z $result ]; then
signature
else
exit 1
fi
}
# 签名
signature() {
# 如果module是application,就区签名
if [ $module == app ]; then
inputApk=$outputsDir/$fileDir/$moduleName-debug.apk
outputApk=$outputsDir/$fileDir/$projectName-signed.apk
java -jar signapk/signapk.jar signapk/platform.x509.pem signapk/platform.pk8 $inputApk $outputApk
rm -f $inputApk
# 签名后,执行安装
install
else
# 如果module是library,就重命名,aar打包结束,退出
if [ $module == lib ]; then
inputAar=$outputsDir/$fileDir/$moduleName-release.aar
outputAar=$outputsDir/$fileDir/$projectName-release.aar
mv $inputAar $outputAar
successful 'BUILD LIBRARY SUCCESSFUL'
fi
fi
}
# 安装
install() {
# 如果需要安装,则执行adb命令进行安装
if [ $install == true ]; then
adb install -r -t $outputApk || result=$?
if [ -z $result ]; then
successful 'INSTALL APPLICATION SUCCESSFUL'
fi
else
successful 'BUILD APPLICATION SUCCESSFUL'
fi
}
# 帮助
usage() {
cat <<!EOF!
USAGE:: ./build.sh [option] [param]
options:
-v, -version Print version info.
-h, --help Shows this help message.
-a, --app The project you build is the application.
-l, --lib The project you build is the library.
--install Build and install the application.
param:
project/module
!EOF!
}
# 版本信息
version() {
printf "Version = $version\nAuthor = $author\n"
exit 0
}
# 成功
successful() {
echo -e '\033[32m'$1'\033[0m'
exit 0
}
# 失败
failed() {
echo -e '\033[31m'$1'\033[0m'
exit 1
}
# 调用main函数
main $@
执行脚本
这次使用Ubuntu系统,再也不用在Windows系统上借助Git了。
1.帮助
2.版本信息
3.打包apk
4.打包aar
写在最后
脚本已经很简单了,其实有很多重复的工作都可以通过脚本封装起来,比如使用repo工具,用过的小可爱肯定都知道到,要先使用Git克隆,然后repo init,最后在repo sync。针对这种总使用到的工作就可以封到脚本里,从几行命令变成一行命令即可。