File size: 9,278 Bytes
1ac6b7e df87679 1ac6b7e 8854bb1 1ac6b7e df87679 7f17202 1ac6b7e 7f17202 1ac6b7e 7f17202 1ac6b7e df87679 1ac6b7e b2167f3 1ac6b7e 8854bb1 b2167f3 1ac6b7e b2167f3 1ac6b7e 376857e b6111ab 376857e 1ac6b7e 376857e 1ac6b7e b6111ab 1ac6b7e 376857e b6111ab 1ac6b7e 3bb2b11 1ac6b7e | 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 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 | #!/bin/bash
# build_java_apk.sh <work_dir> <app_name> <pkg_name> <keystore>
# Java kodunu Android APK'ya derler
set -e
WORK_DIR="$1"
APP_NAME="$2"
PKG_NAME="$3"
KEYSTORE="$4"
ANDROID_SDK=/opt/android-sdk
BUILD_TOOLS=$ANDROID_SDK/build-tools/33.0.0
PLATFORM=$ANDROID_SDK/platforms/android-33
echo "[HtStudio Java APK] Başlıyor: $APP_NAME ($PKG_NAME)"
# Klasör yapısı
mkdir -p "$WORK_DIR/src/$( echo $PKG_NAME | tr '.' '/' )"
mkdir -p "$WORK_DIR/res/layout"
mkdir -p "$WORK_DIR/res/values"
mkdir -p "$WORK_DIR/res/mipmap-mdpi" "$WORK_DIR/res/mipmap-hdpi" "$WORK_DIR/res/mipmap-xhdpi" "$WORK_DIR/res/mipmap-xxhdpi" "$WORK_DIR/res/mipmap-xxxhdpi"
mkdir -p "$WORK_DIR/bin"
mkdir -p "$WORK_DIR/obj"
mkdir -p "$WORK_DIR/gen"
mkdir -p "$WORK_DIR/assets"
# İkon: kullanıcının logosu varsa onu kullan (process_logo tarafından
# $WORK_DIR/icons/mipmap-*/ic_launcher.png içine kaydedilmiş olur), yoksa
# varsayılan ikonu kullan. Bu adım eskiden hiç yapılmıyordu, o yüzden Java
# APK'lar her zaman sistem varsayılan (Android robotu) ikonuyla çıkıyordu.
if [ -f "$WORK_DIR/has_logo" ]; then
echo "[HtStudio Java APK] Kullanıcı logosu kullanılıyor"
cp "$WORK_DIR/icons/mipmap-mdpi/ic_launcher.png" "$WORK_DIR/res/mipmap-mdpi/ic_launcher.png"
cp "$WORK_DIR/icons/mipmap-hdpi/ic_launcher.png" "$WORK_DIR/res/mipmap-hdpi/ic_launcher.png"
cp "$WORK_DIR/icons/mipmap-xhdpi/ic_launcher.png" "$WORK_DIR/res/mipmap-xhdpi/ic_launcher.png"
cp "$WORK_DIR/icons/mipmap-xxhdpi/ic_launcher.png" "$WORK_DIR/res/mipmap-xxhdpi/ic_launcher.png"
cp "$WORK_DIR/icons/mipmap-xxxhdpi/ic_launcher.png" "$WORK_DIR/res/mipmap-xxxhdpi/ic_launcher.png"
else
echo "[HtStudio Java APK] Varsayılan ikon kullanılıyor"
cp /opt/default_icons/mdpi/ic_launcher.png "$WORK_DIR/res/mipmap-mdpi/ic_launcher.png"
cp /opt/default_icons/hdpi/ic_launcher.png "$WORK_DIR/res/mipmap-hdpi/ic_launcher.png"
cp /opt/default_icons/xhdpi/ic_launcher.png "$WORK_DIR/res/mipmap-xhdpi/ic_launcher.png"
cp /opt/default_icons/xxhdpi/ic_launcher.png "$WORK_DIR/res/mipmap-xxhdpi/ic_launcher.png"
cp /opt/default_icons/xxxhdpi/ic_launcher.png "$WORK_DIR/res/mipmap-xxxhdpi/ic_launcher.png"
fi
# Kullanıcının Java kodunu yerleştir.
# İki mod var:
# 1) "Tam Activity modu" - kullanıcı kendi MainActivity/View/onDraw vs. kodunu
# yazmışsa (gerçek Android UI), kodunu direkt MainActivity.java olarak
# kullanıyoruz, hiçbir wrapper üretmiyoruz (aksi halde "duplicate class"
# hatası alınır çünkü iki MainActivity çakışır).
# 2) "Konsol modu" - kullanıcı basit `class Main { main(...) }` yazmışsa,
# eskisi gibi çıktısını TextView'da gösteren bir wrapper MainActivity
# otomatik üretilir.
SRC_DIR="$WORK_DIR/src/$( echo $PKG_NAME | tr '.' '/' )"
# Kullanıcının kodundaki `package ...;` satırı proje ayarındaki gerçek paket
# adından farklıysa derleme patlar (paket/klasör uyuşmazlığı). Otomatik
# eşitliyoruz ki kullanıcı hangi paket adını yazdıysa yazsın çalışsın.
if grep -q "^package " "$WORK_DIR/Main.java"; then
sed -i "s/^package .*/package ${PKG_NAME};/" "$WORK_DIR/Main.java"
else
sed -i "1i package ${PKG_NAME};" "$WORK_DIR/Main.java"
fi
if grep -qE "class[[:space:]]+MainActivity\b" "$WORK_DIR/Main.java"; then
echo "[HtStudio Java APK] Tam Activity modu (kullanıcı kendi MainActivity'sini yazmış)"
cp "$WORK_DIR/Main.java" "$SRC_DIR/MainActivity.java"
else
echo "[HtStudio Java APK] Konsol modu (Main.main() çıktısı sarmalanıyor)"
cp "$WORK_DIR/Main.java" "$SRC_DIR/Main.java"
cat > "$SRC_DIR/MainActivity.java" << JAVA
package $PKG_NAME;
import android.app.Activity;
import android.os.Bundle;
import android.widget.ScrollView;
import android.widget.TextView;
import java.io.ByteArrayOutputStream;
import java.io.PrintStream;
public class MainActivity extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
ScrollView sv = new ScrollView(this);
TextView tv = new TextView(this);
tv.setPadding(32, 32, 32, 32);
tv.setTextSize(14f);
tv.setTextColor(0xFFCDD6F4);
tv.setBackgroundColor(0xFF1E1E2E);
tv.setTypeface(android.graphics.Typeface.MONOSPACE);
sv.addView(tv);
setContentView(sv);
sv.setBackgroundColor(0xFF1E1E2E);
// Kullanıcının main metodunu çalıştır, stdout'u yakala
ByteArrayOutputStream baos = new ByteArrayOutputStream();
PrintStream ps = new PrintStream(baos);
PrintStream old = System.out;
System.setOut(ps);
try {
Main.main(new String[]{});
} catch (Exception e) {
System.out.println("Hata: " + e.getMessage());
} finally {
System.out.flush();
System.setOut(old);
}
tv.setText(baos.toString());
}
}
JAVA
fi
# AndroidManifest.xml
cat > "$WORK_DIR/AndroidManifest.xml" << XML
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="$PKG_NAME"
android:versionCode="1"
android:versionName="1.0">
<uses-sdk android:minSdkVersion="21" android:targetSdkVersion="33"/>
<application android:label="$APP_NAME" android:icon="@mipmap/ic_launcher" android:allowBackup="true">
<activity android:name=".MainActivity" android:exported="true"
android:theme="@android:style/Theme.NoTitleBar.Fullscreen">
<intent-filter>
<action android:name="android.intent.action.MAIN"/>
<category android:name="android.intent.category.LAUNCHER"/>
</intent-filter>
</activity>
</application>
</manifest>
XML
# R.java oluştur (aapt2)
$BUILD_TOOLS/aapt2 compile --dir "$WORK_DIR/res" -o "$WORK_DIR/res_compiled.zip" 2>&1
$BUILD_TOOLS/aapt2 link \
--manifest "$WORK_DIR/AndroidManifest.xml" \
-I "$PLATFORM/android.jar" \
--java "$WORK_DIR/gen" \
-A "$WORK_DIR/assets" \
-o "$WORK_DIR/resources.apk" \
"$WORK_DIR/res_compiled.zip" \
--auto-add-overlay 2>&1
echo "[HtStudio Java APK] javac ile derleniyor..."
# Java kaynaklarını derle
find "$WORK_DIR/src" -name "*.java" > "$WORK_DIR/sources.txt"
find "$WORK_DIR/gen" -name "*.java" >> "$WORK_DIR/sources.txt" 2>/dev/null || true
# Projeye eklenen kütüphaneler (process_libraries() tarafından $WORK_DIR/libs/
# altına konuluyor). İki formatta gelebilir:
# - .jar -> direkt kullanılır
# - .aar -> Android Archive, içinde classes.jar + kaynaklar var. Burada
# sadece classes.jar'ı çıkarıp kullanıyoruz (kaynak/manifest
# birleştirme yapmıyoruz - çoğu kod kütüphanesi için yeterli,
# ama kütüphane kendi layout/drawable gibi Android
# kaynaklarına ihtiyaç duyuyorsa bu basit çıkarma yetmez).
mkdir -p "$WORK_DIR/libs_extracted"
for AAR in "$WORK_DIR"/libs/*.aar; do
[ -e "$AAR" ] || continue
AAR_NAME=$(basename "$AAR" .aar)
echo "[HtStudio Java APK] AAR açılıyor: $AAR_NAME"
TMP_EXTRACT="$WORK_DIR/libs_extracted/${AAR_NAME}_tmp"
mkdir -p "$TMP_EXTRACT"
unzip -o -q "$AAR" classes.jar -d "$TMP_EXTRACT" 2>&1 || true
if [ -f "$TMP_EXTRACT/classes.jar" ]; then
mv "$TMP_EXTRACT/classes.jar" "$WORK_DIR/libs_extracted/${AAR_NAME}.jar"
else
echo "[UYARI] $AAR_NAME.aar içinde classes.jar bulunamadı, atlanıyor"
fi
rm -rf "$TMP_EXTRACT"
done
LIB_JARS=$(find "$WORK_DIR/libs" "$WORK_DIR/libs_extracted" -name "*.jar" 2>/dev/null | tr '\n' ':')
if [ -n "$LIB_JARS" ]; then
echo "[HtStudio Java APK] Kütüphaneler classpath'e ekleniyor: $LIB_JARS"
CLASSPATH="$PLATFORM/android.jar:${LIB_JARS}"
else
CLASSPATH="$PLATFORM/android.jar"
fi
javac -source 8 -target 8 \
-cp "$CLASSPATH" \
-d "$WORK_DIR/obj" \
@"$WORK_DIR/sources.txt" 2>&1
echo "[HtStudio Java APK] d8 ile dex oluşturuluyor..."
# NOT: Kütüphane jar'ları (aar'dan çıkarılanlar dahil) burada da d8'e
# veriliyor - sadece derleme classpath'inde olmaları yeterli değil,
# kütüphanenin kendi bytecode'unun da dex'lenip APK'ya gömülmesi lazım,
# yoksa runtime'da ClassNotFoundException alınır.
$BUILD_TOOLS/d8 \
--lib "$PLATFORM/android.jar" \
--output "$WORK_DIR/bin" \
$(find "$WORK_DIR/obj" -name "*.class") \
$(find "$WORK_DIR/libs" "$WORK_DIR/libs_extracted" -name "*.jar" 2>/dev/null) 2>&1
echo "[HtStudio Java APK] APK paketleniyor..."
cd "$WORK_DIR"
cp resources.apk unsigned.apk 2>/dev/null || $BUILD_TOOLS/aapt package -f \
-M AndroidManifest.xml \
-I "$PLATFORM/android.jar" \
-F unsigned.apk 2>&1
# classes.dex ekle
zip -j unsigned.apk bin/classes.dex 2>&1
echo "[HtStudio Java APK] Hizalanıyor (zipalign)..."
$BUILD_TOOLS/zipalign -f -p 4 unsigned.apk aligned.apk 2>&1
mv aligned.apk unsigned.apk
echo "[HtStudio Java APK] İmzalanıyor..."
$BUILD_TOOLS/apksigner sign \
--ks "$KEYSTORE" \
--ks-pass pass:android \
--key-pass pass:android \
--ks-key-alias androiddebugkey \
--out output.apk \
unsigned.apk 2>&1
echo "[HtStudio Java APK] Başarılı: $WORK_DIR/output.apk"
|