vendor/opengapps/build/core/find_apk.sh

247 lines
6.6 KiB
Bash
Raw Permalink Normal View History

2025-08-25 08:12:20 +08:00
#!/bin/bash
getlatestapk() {
# This functions finds the latest available version for the given architeture.
aaptcmd="$3"
sourceapk=""
highversion=""
tempapks=( )
OLDIFS="$IFS"
IFS="
" # We set IFS to newline here so that filenames containing spaces are
# handled correctly in the for-loops below.
local LZ_DECOMPRESS_CMD="false"
local LZ_DECOMPRESS_ARG=""
if command -v lunzip > /dev/null; then
LZ_DECOMPRESS_CMD="lunzip"
elif command -v lzip > /dev/null; then
LZ_DECOMPRESS_CMD="lzip"
LZ_DECOMPRESS_ARG="--decompress"
fi;
# decompress apks
# some apks are lz compressed to work around github file-size limits.
for foundapklz in $(find "$1" -iname '*.apk.lz'); do
$LZ_DECOMPRESS_CMD $LZ_DECOMPRESS_ARG --keep "$foundapklz" || echo "Warning: lz decompress command failed for $foundapklz" >&2
done
# sed copies filename to the beginning, to compare version, and later we remove it with cut
for foundapk in $(find "$1" -iname '*.apk' | sed 's!.*/\(.*\)!\1/&!' | sort -r -t/ -k1,1 -n | cut -d/ -f2-); do
# Get package version name
apkprops="$("$aaptcmd" dump badging "$foundapk" 2> /dev/null)"
apkversion="$(echo "$apkprops" | awk -F="'" '/versionName=/ {print $4}' | sed "s/'.*//g")"
# Get invariant version name.
# We first remove evrything after the first space.
apkversion="$(printf "$apkversion" | cut -d ' ' -f 1)"
# Then, we remove everything after the fourth dot.
apkversionparts=$(echo "$apkversion" | tr '.' '\n')
j=0
apkversion=""
for part in ${apkversionparts[@]}; do
if [ $j -ge 4 ]; then
break;
else
if [ $j -ge 1 ]; then
apkversion+="."
fi
apkversion+="$part"
((j++))
fi
done
if [ -z "$highversion" ]; then
# Take note of the highest version.
highversion="$apkversion"
elif [ "$highversion" != "$apkversion" ]; then
# Skip lower versions.
break;
fi
# Add package to list.
tempapks+=("$foundapk")
done
if [ ${#tempapks[@]} -ge 2 ]; then
# See if there is a package for this dpi or a nodpi package.
for foundapk in ${tempapks[@]}; do
dpipath="$(dirname "$foundapk")"
dpi="$(basename "$dpipath")"
if [[ "$dpi" = "nodpi" || "$dpi" = "$2" ]]; then
sourceapk="$foundapk"
break;
fi
if [ "$2" != "nodpi" ]; then
# Check if the package dpi is a range and if the device falls between that range
lodpi=${dpi%%-*}
hidpi=${dpi##*-}
if [[ "$lodpi" != "$dpi" && "$lodpi" -le "$2" && "$hidpi" -ge "$2" ]]; then
sourceapk="$foundapk"
break;
fi
fi
done
# If the device is set to nodpi, we take the highest dpi available. This should be the first one on the list.
if [[ -z "$sourceapk" && "$2" = "nodpi" ]]; then
sourceapk="$tempapks"
fi
# Take the lowest dpi above the device dpi or the highest dpi under the device dpi.
if [ -z "$sourceapk" ]; then
for foundapk in ${tempapks[@]}; do
dpipath="$(dirname "$foundapk")"
dpi="$(basename "$dpipath")"
# If this is a range, we already know the device is either over or under that range.
# Therefore, we can safely take any value.
dpi=${dpi%%-*}
if [ "$dpi" -ge "$2" ]; then
sourceapk="$foundapk"
else
# If we havn't found a higher dpi, we take the first (highest) lower dpi.
if [ -z "$sourceapk" ]; then
sourceapk="$foundapk"
fi
break;
fi
done
fi
elif [ ${#tempapks[@]} -ge 1 ]; then
# If theres only one apk, take that one.
sourceapk="$tempapks"
fi
IFS="$OLDIFS"
if [ -z "$sourceapk" ]; then
echo "WARNING: No APK found compatible with API level $API for package $PACKAGE_NAME on $ARCH" >&2
return 1 #error
fi
#$sourceapk has the useful return value
return 0 #return that it was a success
}
getconformapk() {
# This functions finds the latest available version for the given architeture and dpi. IF the chosen dpi is not available, nodpi will be selected.
sourceapk=""
OLDIFS="$IFS"
IFS="
" # We set IFS to newline here so that spaces can survive the for loop
# sed copies filename to the beginning, to compare version, and later we remove it with cut
for foundapk in $(find "$1" -iname '*.apk' | sed 's!.*/\(.*\)!\1/&!' | sort -r -t/ -k1,1 -n | cut -d/ -f2-); do
founddpipath="$(dirname "$foundapk")"
dpi="$(basename "$founddpipath")"
lodpi=${dpi%%-*}
hidpi=${dpi##*-}
if [[ "$dpi" = "nodpi" || "$dpi" = "$2"
|| ( "$2" != "nodpi" && "$lodpi" != "$dpi" && "$lodpi" -le "$2" && "$hidpi" -ge "$2" ) ]]; then
sourceapk="$foundapk"
break;
fi
done
IFS="$OLDIFS"
if [ -z "$sourceapk" ]; then
echo "WARNING: No APK found compatible with API level $API for package $PACKAGE_NAME on $ARCH and dpi $2" >&2
return 1 #error
fi
#$sourceapk has the useful return value
return 0 #return that it was a success
}
getapk()
{
if [ "$3" = false ]; then
aaptcmd="$4"
if hash "$aaptcmd" 2> /dev/null; then
getlatestapk "$1" "$2" "$aaptcmd"
else
echo "ERROR: aapt not found. Unable to detect latest package." >&2
return 1
fi
else
getconformapk "$1" "$2"
fi
return $?
}
getappapidir() {
# Check if app directory exists.
if [ ! -d "$1/$2/"*"app/$3" ]; then
return 1 # Package does not exist for this arch.
fi
# Try to find the largest API which is greater or
# equal to what is needed.
api=0
for apidir in "$1/$2/"*"app/$3/"*; do
currentApi="$(basename "$apidir")"
if [ "$currentApi" -le "$4" ] && [ "$currentApi" -ge "$api" ]; then
api="$currentApi"
fi
done
# Have we found anything?
if [ "$api" -gt 0 ]; then
appapidir="$(echo "$1/$2/"*"app/$3/$api")"
return 0
fi
echo "WARNING: No APK found compatible with API level $4 for package $3 on $2" >&2
return 1
}
getdpivalue() {
case "$1" in
"xxxhdpi")
dpivalue="640";
;;
"xxhdpi")
dpivalue="480";
;;
"xhdpi")
dpivalue="320";
;;
"hdpi")
dpivalue="240";
;;
"mdpi")
dpivalue="160";
;;
"ldpi")
dpivalue="120";
;;
*)
return 1;
;;
esac
return 0;
}
SOURCES="$1"
API="$2"
DPI="$3"
PACKAGE_NAME="$4"
ARCH="$5"
FORCE_DPI="$6"
AAPT_CMD="$7"
if ! getappapidir "$SOURCES" "$ARCH" "$PACKAGE_NAME" "$API"; then
exit 1
fi
if getdpivalue "$DPI"; then
if getapk "$appapidir" "$dpivalue" "$FORCE_DPI" "$AAPT_CMD"; then
echo "$sourceapk"
else
exit 1
fi
elif getapk "$appapidir" "nodpi" "$FORCE_DPI" "$AAPT_CMD"; then
echo "$sourceapk"
else
exit 1
fi