Skip to content

Commit 4362100

Browse files
committed
新增支持安装 apks、xapk、apkm 格式的安装包
1 parent 6d7c117 commit 4362100

File tree

1 file changed

+169
-18
lines changed

1 file changed

+169
-18
lines changed

shell/device-tools/InstallApp.sh

Lines changed: 169 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -11,36 +11,44 @@ cd "${scriptDirPath}" || exit 1
1111
source "../common/SystemPlatform.sh" && \
1212
source "../common/FileTools.sh" && \
1313
source "../common/EnvironmentTools.sh" && \
14-
source "../business/DevicesSelector.sh" || exit 1
14+
source "../business/DevicesSelector.sh" && \
15+
source "../business/ResourceManager.sh" || exit 1
1516
cd "${originalDirPath}" || exit 1
1617
unset scriptDirPath
1718
unset originalDirPath
1819

20+
unzipDirPathSuffix="-$(date "+%Y%m%d%H%M%S")"
21+
1922
waitUserInputParameter() {
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+
69194
installMultipleApk() {
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+
109259
main() {
110260
printCurrentSystemType
111261
checkAdbEnvironment
112-
waitUserInputParameter
262+
waitUserInputParameter "$1"
113263
installApkForDevice
264+
clearTempDir
114265
}
115266

116267
clear
117-
main
268+
main "$@"

0 commit comments

Comments
 (0)