-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathbuild+install.sh
More file actions
executable file
·184 lines (159 loc) · 6.11 KB
/
build+install.sh
File metadata and controls
executable file
·184 lines (159 loc) · 6.11 KB
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
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
#!/usr/bin/env bash
set -euo pipefail
# ============================================================================
APP_PKG="uk.simlink.lpa"
APKTOOL_TREE="eazyeuicc"
ORIG_APK="eazyeuicc.apk"
DEP_JAR="eazyeuicc.jar"
JAVA_PKG="im.angry.openeuicc.bridge"
SRC_DIR="src"
OUT_DIR="out"
DEPS_DIR="deps"
BAKSMALI_JAR="tools/baksmali.jar"
# ============================================================================
pick_smali_bucket() {
local base="$APKTOOL_TREE"
local n=2
[[ -d "$base/smali" ]] && echo "$base/smali" && return 0
while [[ -d "$base/smali_classes$n" ]]; do n=$((n+1)); done
echo "$base/smali_classes$n"
}
# Derived paths/names
SMALI_PKG_DIR="${JAVA_PKG//.//}"
SRC_PKG_DIR="${SRC_DIR}/${SMALI_PKG_DIR}"
TARGET_SMALI_ROOT="$(pick_smali_bucket)"
TARGET_SMALI_DIR="${TARGET_SMALI_ROOT}/${SMALI_PKG_DIR}"
# SDK paths
ANDROID_SDK="$HOME/Library/Android/sdk"
ANDROID_JAR="$ANDROID_SDK/platforms/android-33/android.jar"
BT="$ANDROID_SDK/build-tools/$(ls "$ANDROID_SDK/build-tools" | sort -V | tail -1)"
# Sanity: tools present
command -v apktool >/dev/null || { echo "ERROR: apktool not found"; exit 1; }
command -v adb >/dev/null || { echo "ERROR: adb not found"; exit 1; }
command -v java >/dev/null || { echo "ERROR: java not found"; exit 1; }
command -v javac >/dev/null || { echo "ERROR: javac not found"; exit 1; }
# command -v keytool >/dev/null || { echo "ERROR: keytool not found"; exit 1; }
# Sanity: files/dirs
[[ -f "$ANDROID_JAR" ]] || { echo "ERROR: android.jar not found: $ANDROID_JAR"; exit 1; }
[[ -x "$BT/d8" ]] || { echo "ERROR: d8 not found: $BT/d8"; exit 1; }
[[ -x "$BT/zipalign" ]] || { echo "ERROR: zipalign not found: $BT/zipalign"; exit 1; }
[[ -x "$BT/apksigner" ]] || { echo "ERROR: apksigner not found: $BT/apksigner"; exit 1; }
[[ -f "$BAKSMALI_JAR" ]] || { echo "ERROR: baksmali jar missing: $BAKSMALI_JAR"; exit 1; }
[[ -d "$APKTOOL_TREE" ]] || { echo "ERROR: apktool tree missing: $APKTOOL_TREE"; exit 1; }
[[ -d "$SRC_PKG_DIR" ]] || { echo "ERROR: source package dir missing: $SRC_PKG_DIR"; exit 1; }
mkdir -p "$DEPS_DIR"
# Ensure we have a complete classpath jar containing ALL dexes (kotlin, coroutines, lpac_jni, etc.)
rebuild_cp_jar() {
local apk="$1"
local dexdir="$DEPS_DIR/_dex"
local mergedir="$DEPS_DIR/_merge"
local jar_out="$DEPS_DIR/$DEP_JAR"
rm -rf "$dexdir" "$mergedir"
mkdir -p "$dexdir" "$mergedir"
echo "[dex] extracting classes*.dex from $apk"
unzip -q -j "$apk" 'classes*.dex' -d "$dexdir"
local any=0
for d in "$dexdir"/classes*.dex; do
[[ -f "$d" ]] || continue
any=1
local j="${d%.dex}.jar"
echo "[dex2jar] $d -> $j"
d2j-dex2jar "$d" -o "$j" >/dev/null
unzip -q -o "$j" -d "$mergedir"
done
[[ $any -eq 1 ]] || { echo "ERROR: no classes*.dex found in $apk"; exit 1; }
(cd "$mergedir" && jar cf "../$DEP_JAR" .)
rm -rf "$dexdir" "$mergedir"
}
# (Re)build deps jar if missing or incomplete
APP_JAR="$DEPS_DIR/$DEP_JAR"
need_rebuild=0
if [[ ! -f "$APP_JAR" ]]; then
need_rebuild=1
else
jar tf "$APP_JAR" | grep -q '^kotlin/' || need_rebuild=1
jar tf "$APP_JAR" | grep -q '^kotlinx/coroutines/' || need_rebuild=1
jar tf "$APP_JAR" | grep -q '^net/typeblog/lpac_jni/' || need_rebuild=1
fi
if [[ $need_rebuild -eq 1 ]]; then
[[ -f "$ORIG_APK" ]] || { echo "ERROR: ORIG_APK not found: $ORIG_APK"; exit 1; }
rebuild_cp_jar "$ORIG_APK"
fi
# Verify again (fail fast with helpful messages)
jar tf "$APP_JAR" | grep -q '^kotlin/' || { echo "ERROR: Kotlin stdlib missing in $APP_JAR"; exit 1; }
jar tf "$APP_JAR" | grep -q '^kotlinx/coroutines/' || { echo "ERROR: kotlinx coroutines missing in $APP_JAR"; exit 1; }
jar tf "$APP_JAR" | grep -q '^net/typeblog/lpac_jni/' || { echo "ERROR: net.typeblog.lpac_jni missing in $APP_JAR"; exit 1; }
# Gather sources
JAVA_SOURCES=()
while IFS= read -r -d '' f; do
JAVA_SOURCES+=("$f")
done < <(find "$SRC_PKG_DIR" -type f -name '*.java' -print0)
[[ ${#JAVA_SOURCES[@]} -gt 0 ]] || { echo "ERROR: no .java files found under $SRC_PKG_DIR"; exit 1; }
# Clean + mkdirs
rm -rf "$APKTOOL_TREE/build"
rm -rf "$OUT_DIR"
mkdir -p "$OUT_DIR"/{classes,dex,smali}
# Build classpath from all jars in deps
CP="$ANDROID_JAR:$(find "$DEPS_DIR" -maxdepth 1 -type f -name '*.jar' | paste -sd: -)"
# Compile
javac \
-source 23 -target 23 \
-classpath "$CP" \
-Xlint:-options \
-encoding UTF-8 \
-d "$OUT_DIR/classes" \
"${JAVA_SOURCES[@]}"
# DEX
D8_CLASSPATH_ARGS=()
IFS=':' read -ra CP_ENTRIES <<< "$CP"
for entry in "${CP_ENTRIES[@]}"; do
D8_CLASSPATH_ARGS+=(--classpath "$entry")
done
"$BT/d8" \
--lib "$ANDROID_JAR" \
"${D8_CLASSPATH_ARGS[@]}" \
--output "$OUT_DIR/dex" \
$(find "$OUT_DIR/classes" -type f -name '*.class')
# Smali
found_dex=0
for dex in "$OUT_DIR"/dex/*.dex; do
[[ -f "$dex" ]] || continue
found_dex=1
java -jar "$BAKSMALI_JAR" d "$dex" -o "$OUT_DIR/smali"
done
[[ $found_dex -eq 1 ]] || { echo "ERROR: no dex files produced"; exit 1; }
mkdir -p "$TARGET_SMALI_DIR"
if [[ -d "$OUT_DIR/smali/$SMALI_PKG_DIR" ]]; then
rm -rf "$TARGET_SMALI_DIR"
mkdir -p "$TARGET_SMALI_DIR"
cp -R "$OUT_DIR/smali/$SMALI_PKG_DIR/." "$TARGET_SMALI_DIR/"
else
echo "ERROR: expected smali package dir not found: $OUT_DIR/smali/$SMALI_PKG_DIR"
exit 1
fi
# Rebuild
apktool b "$APKTOOL_TREE" -o "$OUT_DIR/build-unsigned.apk"
# Align
"$BT/zipalign" -p -f 4 "$OUT_DIR/build-unsigned.apk" "$OUT_DIR/build-aligned.apk"
# Ensure keystore
# if [ ! -f "$HOME/.android/debug.keystore" ]; then
# mkdir -p "$HOME/.android"
# keytool -genkeypair \
# -keystore "$HOME/.android/debug.keystore" \
# -storepass android -keypass android \
# -alias androiddebugkey \
# -keyalg RSA -keysize 2048 -validity 10000 \
# -dname "CN=Android Debug,O=Android,C=US"
# fi
# https://github.com/9esim/9eSIMCommunityKey
COMMUNITY_KEY_JKS="./9eSIMCommunityKey.jks"
COMMUNITY_KEY_PASS="147258369"
# Sign APK using 9eSIM Community Key
java --enable-native-access=ALL-UNNAMED \
-jar "$BT/lib/apksigner.jar" sign \
--ks "$COMMUNITY_KEY_JKS" \
--ks-pass pass:"$COMMUNITY_KEY_PASS" \
--out "$OUT_DIR/build-signed.apk" \
"$OUT_DIR/build-aligned.apk"
# Install
adb install -r "$OUT_DIR/build-signed.apk"