@@ -11,36 +11,44 @@ cd "${scriptDirPath}" || exit 1
1111source " ../common/SystemPlatform.sh" && \
1212source " ../common/FileTools.sh" && \
1313source " ../common/EnvironmentTools.sh" && \
14- source " ../business/DevicesSelector.sh" || exit 1
14+ source " ../business/DevicesSelector.sh" && \
15+ source " ../business/ResourceManager.sh" || exit 1
1516cd " ${originalDirPath} " || exit 1
1617unset scriptDirPath
1718unset originalDirPath
1819
20+ unzipDirPathSuffix=" -$( date " +%Y%m%d%H%M%S" ) "
21+
1922waitUserInputParameter () {
20- echo " 请输入要安装的 apk 文件或所在目录路径:"
21- read -r sourcePath
22- sourcePath=$( parseComputerFilePath " ${sourcePath} " )
23+ local inputPath
24+ if [[ -n " $1 " ]]; then
25+ inputPath=" $1 "
26+ else
27+ echo " 请输入要安装的 apk/apks/xapk/apkm 文件或所在目录路径:"
28+ read -r inputPath
29+ fi
30+ sourcePath=$( parseComputerFilePath " ${inputPath} " )
2331
2432 if [[ -z " ${sourcePath} " ]]; then
2533 echo " ❌ 路径为空,请检查输入是否正确"
2634 exit 1
2735 fi
2836
29- apkFiles =()
37+ packageFiles =()
3038 if [[ -d " ${sourcePath} " ]]; then
3139 while IFS= read -r -d ' ' file; do
32- apkFiles +=(" ${file} " )
33- done < <( find " ${sourcePath} " -maxdepth 1 -type f -name " *.apk" -print0)
34- if (( ${# apkFiles [@]} == 0 )) ; then
35- echo " ❌ 该目录下没有以 .apk 结尾的文件,安装中止"
40+ packageFiles +=(" ${file} " )
41+ done < <( find " ${sourcePath} " -maxdepth 1 -type f \( -iname " *.apk" -o -iname " *.apks " -o -iname " *.xapk " -o -iname " *.apkm " \) -print0)
42+ if (( ${# packageFiles [@]} == 0 )) ; then
43+ echo " ❌ 该目录下没有以 .apk/.apks/.xapk/.apkm 结尾的文件,安装中止"
3644 exit 1
3745 fi
3846 elif [[ -f " ${sourcePath} " ]]; then
39- if [[ ! " ${sourcePath} " =~ \. (apk)$ ]]; then
40- echo " ❌ 文件错误,只接受文件名后缀为 apk 的文件"
47+ if [[ ! " ${sourcePath} " =~ \. (apk| apks | xapk | apkm )$ ]]; then
48+ echo " ❌ 文件错误,只接受后缀为 apk/apks/xapk/apkm 的文件"
4149 exit 1
4250 fi
43- apkFiles +=(" ${sourcePath} " )
51+ packageFiles +=(" ${sourcePath} " )
4452 else
4553 echo " ❌ 路径不存在,请检查 ${sourcePath} 是否正确"
4654 exit 1
@@ -66,20 +74,150 @@ installSingleApk() {
6674 fi
6775}
6876
77+ installApksWithBundletool () {
78+ local deviceId=$1
79+ local apksFilePath=$2
80+ local baseName
81+ baseName=$( basename " ${apksFilePath} " )
82+ echo " ⏳ [${deviceId} ] 设备正在安装 [${baseName} ]"
83+ local outputPrint
84+ local javaMajorVersionCode=$( getJavaMajorVersionCode)
85+ if (( javaMajorVersionCode <= 11 )) ; then
86+ local tempDirPath=$( unzipFileToTempDir " ${apksFilePath} " )
87+ local -a apkList=()
88+ while IFS= read -r -d ' ' apk; do apkList+=(" ${apk} " ); done < <( findApkPathForDir " ${tempDirPath} " )
89+ outputPrint=$( adb -s " ${deviceId} " install-multiple -r " ${apkList[@]} " < /dev/null 2>&1 )
90+ else
91+ local bundletoolJar
92+ bundletoolJar=" $( getBundletoolJarFilePath) "
93+ outputPrint=$( java -jar " ${bundletoolJar} " install-apks --apks=" ${apksFilePath} " --device-id=" ${deviceId} " < /dev/null 2>&1 )
94+ fi
95+ local exitCode=$?
96+ if (( exitCode == 0 )) ; then
97+ echo " ✅ [${deviceId} ] 设备安装 [${baseName} ] 成功"
98+ return 0
99+ else
100+ echo " ❌ [${deviceId} ] 设备安装 [${baseName} ] 失败,原因如下:"
101+ echo " ${outputPrint} "
102+ return 1
103+ fi
104+ }
105+
106+ installMultipleApkFromDir () {
107+ local deviceId=$1
108+ local unzipApkDirPath=$2
109+ local targetApkFilePath=$3
110+ local -a apkList=()
111+ while IFS= read -r -d ' ' apk; do apkList+=(" ${apk} " ); done < <( findApkPathForDir " ${unzipApkDirPath} " )
112+ local baseName
113+ baseName=$( basename " ${targetApkFilePath} " )
114+ echo " ⏳ [${deviceId} ] 设备正在安装 [${baseName} ]"
115+ local outputPrint=$( adb -s " ${deviceId} " install-multiple -r " ${apkList[@]} " < /dev/null 2>&1 )
116+ local exitCode=$?
117+ if (( exitCode == 0 )) ; then
118+ echo " ✅ [${deviceId} ] 设备安装 [${baseName} ] 成功"
119+ return 0
120+ else
121+ echo " ❌ [${deviceId} ] 设备安装 [${baseName} ] 失败,原因如下:"
122+ echo " ${outputPrint} "
123+ return 1
124+ fi
125+ }
126+
127+ unzipFileToTempDir () {
128+ local archivePath=$1
129+ local tempDirPath
130+ tempDirPath=" ${archivePath% .* }${unzipDirPathSuffix} "
131+ if [[ ! -d " ${tempDirPath} " ]]; then
132+ unzip -q -o " ${archivePath} " -d " ${tempDirPath} " < /dev/null
133+ fi
134+ echo " ${tempDirPath} "
135+ }
136+
137+ maybePushObb () {
138+ local deviceId=$1
139+ local unzipApkDirPath=$2
140+ local obbPath=" ${unzipApkDirPath} /Android/obb"
141+ if [[ -d " ${obbPath} " ]]; then
142+ echo " ⏳ [${deviceId} ] 检测到 OBB,正在推送至 /sdcard/Android/obb"
143+ adb -s " ${deviceId} " shell " mkdir -p /sdcard/Android/obb" < /dev/null > /dev/null 2>&1
144+ adb -s " ${deviceId} " push " ${obbPath} " " /sdcard/Android/obb" < /dev/null
145+ fi
146+ }
147+
148+ getBashApkPath () {
149+ local dir=" $1 "
150+ local manifest=" ${dir} /manifest.json"
151+ local basePath=" "
152+ if [[ -f " ${manifest} " ]]; then
153+ local oneLine
154+ oneLine=$( tr -d ' \n' < " ${manifest} " )
155+ local baseRel
156+ baseRel=$( printf " %s" " $oneLine " | sed -n ' s/.*"id"[[:space:]]*:[[:space:]]*"base"[[:space:]]*,[^{]*"file"[[:space:]]*:[[:space:]]*"\([^"]*\.apk\)".*/\1/p' | head -n1)
157+ if [[ -z " ${baseRel} " ]]; then
158+ baseRel=$( printf " %s" " $oneLine " | sed -n ' s/.*"file"[[:space:]]*:[[:space:]]*"\([^"]*\.apk\)".*"id"[[:space:]]*:[[:space:]]*"base".*/\1/p' | head -n1)
159+ fi
160+ if [[ -n " ${baseRel} " && -f " ${dir} /${baseRel} " ]]; then
161+ basePath=" ${dir} /${baseRel} "
162+ fi
163+ fi
164+ if [[ -z " ${basePath} " ]]; then
165+ local p
166+ while IFS= read -r -d ' ' p; do
167+ if [[ " $( basename " $p " ) " == " base.apk" ]]; then basePath=" $p " ; break ; fi
168+ done < <( find " ${dir} " -type f -name " base.apk" -print0)
169+ fi
170+ if [[ -z " ${basePath} " ]]; then
171+ local p
172+ while IFS= read -r -d ' ' p; do
173+ if [[ " $( basename " $p " ) " == " base-master.apk" ]]; then basePath=" $p " ; break ; fi
174+ done < <( find " ${dir} " -type f -name " base-master.apk" -print0)
175+ fi
176+ echo " ${basePath} "
177+ }
178+
179+ findApkPathForDir () {
180+ local dir=" $1 "
181+ local basePath
182+ basePath=" $( getBashApkPath " ${dir} " ) "
183+ if [[ -n " ${basePath} " ]]; then
184+ printf ' %s\0' " ${basePath} "
185+ fi
186+ while IFS= read -r -d ' ' p; do
187+ if [[ -n " ${basePath} " && " $p " == " ${basePath} " ]]; then
188+ continue
189+ fi
190+ printf ' %s\0' " $p "
191+ done < <( find " ${dir} " -type f -name " *.apk" -print0)
192+ }
193+
69194installMultipleApk () {
70195 local deviceId=$1
71196 local successCount=0
72197 local failCount=0
73- for apkFilePath in " ${apkFiles[@]} " ; do
74- installSingleApk " ${deviceId} " " ${apkFilePath} "
198+ for filePath in " ${packageFiles[@]} " ; do
199+ if [[ " ${filePath} " =~ \. apk$ ]]; then
200+ installSingleApk " ${deviceId} " " ${filePath} "
201+ elif [[ " ${filePath} " =~ \. apks$ ]]; then
202+ installApksWithBundletool " ${deviceId} " " ${filePath} "
203+ elif [[ " ${filePath} " =~ \. (xapk| apkm)$ ]]; then
204+ local tempDirPath=$( unzipFileToTempDir " ${filePath} " )
205+ if [[ " ${filePath} " =~ \. xapk$ ]]; then
206+ maybePushObb " ${deviceId} " " ${tempDirPath} "
207+ fi
208+ installMultipleApkFromDir " ${deviceId} " " ${tempDirPath} " " ${filePath} "
209+ else
210+ echo " 👻 跳过不支持的文件类型:${filePath} "
211+ continue
212+ fi
75213 local exitCode=$?
76214 if (( exitCode == 0 )) ; then
77215 (( successCount++ ))
78216 else
79217 (( failCount++ ))
80218 fi
81219 done
82- if (( ${# apkFiles [@]} > 1 )) ; then
220+ if (( ${# packageFiles [@]} > 1 )) ; then
83221 echo " 📋 [${deviceId} ] 设备安装任务完成,成功 ${successCount} 个,失败 ${failCount} 个"
84222 fi
85223 return 0
@@ -90,7 +228,6 @@ installApkForDevice() {
90228 deviceId=" $( inputMultipleAdbDevice) "
91229 local pids=()
92230 if [[ -n " ${deviceId} " ]]; then
93- echo " ⏳ 正在安装中..."
94231 installMultipleApk " ${deviceId} " &
95232 pids+=($! )
96233 else
@@ -106,12 +243,26 @@ installApkForDevice() {
106243 done
107244}
108245
246+ clearTempDir () {
247+ local packageFilePath
248+ for packageFilePath in " ${packageFiles[@]} " ; do
249+ if [[ -z " ${packageFilePath} " ]]; then
250+ continue
251+ fi
252+ local tempDir=" ${packageFilePath% .* }${unzipDirPathSuffix} "
253+ if [[ -d " ${tempDir} " ]]; then
254+ rm -rf " ${tempDir} "
255+ fi
256+ done
257+ }
258+
109259main () {
110260 printCurrentSystemType
111261 checkAdbEnvironment
112- waitUserInputParameter
262+ waitUserInputParameter " $1 "
113263 installApkForDevice
264+ clearTempDir
114265}
115266
116267clear
117- main
268+ main " $@ "
0 commit comments