blob: 3040ee002126d11538cac31edbfe10b0ecfe477b (
plain) (
blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
|
#!/bin/sh
# Build a signed release APK.
#
# Required environment:
# KEYSTORE_PATH absolute path to a JKS / PKCS12 keystore
# KEYSTORE_PASS password for the keystore
# KEY_ALIAS alias of the signing key inside the keystore
# KEY_PASS password for that key (often the same as KEYSTORE_PASS)
#
# Required tooling:
# Android build-tools 35.0.0 under ANDROID_SDK_ROOT or on PATH.
#
# Usage:
# scripts/build-apk
#
# Output: prints the absolute path of the signed APK and its sha256.
# The signed APK lives at app/build/outputs/apk/release/app-release.apk.
#
# This script does NOT generate a keystore. Generate one once with:
# keytool -genkey -v -keystore release.jks -alias scrcpy-android \
# -keyalg RSA -keysize 2048 -validity 10000
# and keep it outside the repo (it must never be committed).
set -eu
ROOT="$(cd "$(dirname "$0")/.." && pwd)"
APK="$ROOT/app/build/outputs/apk/release/app-release.apk"
require() {
name="$1"
val="$2"
if [ -z "$val" ]; then
echo "build-apk: \$$name is not set" >&2
echo " see the header of $0 for the required environment" >&2
exit 1
fi
}
require KEYSTORE_PATH "${KEYSTORE_PATH:-}"
require KEYSTORE_PASS "${KEYSTORE_PASS:-}"
require KEY_ALIAS "${KEY_ALIAS:-}"
require KEY_PASS "${KEY_PASS:-}"
if [ ! -f "$KEYSTORE_PATH" ]; then
echo "build-apk: keystore not found at $KEYSTORE_PATH" >&2
exit 1
fi
"$ROOT/scripts/check-wrapper"
"$ROOT/scripts/check-server"
echo "build-apk: gradle :app:assembleRelease"
cd "$ROOT"
./gradlew --no-daemon :app:assembleRelease
if [ ! -f "$APK" ]; then
echo "build-apk: gradle finished but $APK does not exist" >&2
exit 1
fi
SUM=$(sha256sum "$APK" | awk '{print $1}')
APKSIGNER=""
AAPT2=""
ZIPALIGN=""
SDK_ROOT="${ANDROID_SDK_ROOT:-${ANDROID_HOME:-}}"
if [ -n "$SDK_ROOT" ]; then
APKSIGNER="$SDK_ROOT/build-tools/35.0.0/apksigner"
AAPT2="$SDK_ROOT/build-tools/35.0.0/aapt2"
ZIPALIGN="$SDK_ROOT/build-tools/35.0.0/zipalign"
[ -x "$APKSIGNER" ] || APKSIGNER=""
[ -x "$AAPT2" ] || AAPT2=""
[ -x "$ZIPALIGN" ] || ZIPALIGN=""
fi
if [ -z "$APKSIGNER" ] && command -v apksigner >/dev/null 2>&1; then
APKSIGNER=$(command -v apksigner)
fi
if [ -z "$AAPT2" ] && command -v aapt2 >/dev/null 2>&1; then
AAPT2=$(command -v aapt2)
fi
if [ -z "$ZIPALIGN" ] && command -v zipalign >/dev/null 2>&1; then
ZIPALIGN=$(command -v zipalign)
fi
if [ -z "$APKSIGNER" ] || [ -z "$AAPT2" ] || [ -z "$ZIPALIGN" ]; then
echo "build-apk: build-tools 35.0.0 are required" >&2
echo " set ANDROID_SDK_ROOT or put apksigner, aapt2, and zipalign on PATH" >&2
exit 1
fi
# Capture rather than pipe: POSIX sh has no pipefail, so
# `apksigner verify | sed` reports sed's status and a rejected APK would
# sail past set -e and be announced below as if it were signed.
echo "build-apk: apksigner verify"
if ! verify_out=$("$APKSIGNER" verify --verbose --print-certs "$APK" 2>&1); then
printf '%s\n' "$verify_out" >&2
echo "build-apk: apksigner rejected $APK" >&2
exit 1
fi
printf '%s\n' "$verify_out" | sed 's/^/ /'
"$ZIPALIGN" -c -P 16 4 "$APK"
expected_permissions=$(cat <<EOF
package: invalid.lena.scrcpy
uses-permission: name='android.permission.INTERNET'
uses-permission: name='android.permission.FOREGROUND_SERVICE'
uses-permission: name='android.permission.FOREGROUND_SERVICE_MEDIA_PLAYBACK'
uses-permission: name='android.permission.POST_NOTIFICATIONS'
EOF
)
actual_permissions=$("$AAPT2" dump permissions "$APK")
if [ "$actual_permissions" != "$expected_permissions" ]; then
echo "build-apk: unexpected release permissions:" >&2
printf '%s\n' "$actual_permissions" >&2
exit 1
fi
expected_sdk=$(cat <<EOF
minSdkVersion:'31'
targetSdkVersion:'36'
EOF
)
actual_sdk=$("$AAPT2" dump badging "$APK" \
| sed -n '/^minSdkVersion:/p; /^targetSdkVersion:/p')
if [ "$actual_sdk" != "$expected_sdk" ]; then
echo "build-apk: unexpected release SDK levels:" >&2
printf '%s\n' "$actual_sdk" >&2
exit 1
fi
expected_abis="native-code: 'arm64-v8a' 'x86_64'"
actual_abis=$("$AAPT2" dump badging "$APK" | sed -n '/^native-code:/p')
if [ "$actual_abis" != "$expected_abis" ]; then
echo "build-apk: unexpected release ABIs: $actual_abis" >&2
exit 1
fi
echo "build-apk: $APK"
echo "build-apk: sha256 $SUM"
|