migration start
Some checks failed
CI - Multi-Platform Native / Build iOS (RSSuper) (push) Has been cancelled
CI - Multi-Platform Native / Build macOS (push) Has been cancelled
CI - Multi-Platform Native / Build Android (push) Has been cancelled
CI - Multi-Platform Native / Build Linux (push) Has been cancelled
CI - Multi-Platform Native / Build Summary (push) Has been cancelled

This commit is contained in:
2026-03-29 14:12:17 -04:00
parent af87f9f571
commit d346b527e6
51 changed files with 4476 additions and 69 deletions

422
scripts/build-android.sh Executable file
View File

@@ -0,0 +1,422 @@
#!/bin/bash
# RSSuper Android Build Script
# Native Android build using Gradle
set -e
# Configuration
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
PROJECT_ROOT="$(dirname "$SCRIPT_DIR")"
ANDROID_PROJECT_DIR="$PROJECT_ROOT/native-route/android"
# Default values
VARIANT="${1:-debug}"
ACTION="${2:-assemble}"
# Show help
show_help() {
echo "RSSuper Android Build Script"
echo ""
echo "Usage: $0 [VARIANT] [ACTION]"
echo ""
echo "Arguments:"
echo " VARIANT Build variant (debug|release) [Default: debug]"
echo " ACTION Gradle action (assemble|build|test|clean) [Default: assemble]"
echo ""
echo "Examples:"
echo " $0 # Assemble debug APK"
echo " $0 release # Assemble release APK"
echo " $0 debug test # Run tests"
echo " $0 clean # Clean build"
}
# Check prerequisites
check_prerequisites() {
if [ ! -d "$ANDROID_PROJECT_DIR" ]; then
echo "Error: Android project directory not found: $ANDROID_PROJECT_DIR"
echo "Creating basic Android project structure..."
create_android_project
return 0
fi
if [ ! -f "$ANDROID_PROJECT_DIR/build.gradle.kts" ] && [ ! -f "$ANDROID_PROJECT_DIR/build.gradle" ]; then
echo "Warning: No build.gradle found. Creating basic Android project..."
create_android_project
fi
# Check for Java/JDK
if ! command -v java &> /dev/null; then
echo "Error: Java not found. Please install JDK 17."
exit 1
fi
echo "Java version:"
java -version
}
# Create basic Android project structure
create_android_project() {
echo "Creating Android project structure..."
mkdir -p "$ANDROID_PROJECT_DIR/app/src/main/java/com/mikefreno/rssuper"
mkdir -p "$ANDROID_PROJECT_DIR/app/src/main/res/values"
mkdir -p "$ANDROID_PROJECT_DIR/app/src/main/res/mipmap-hdpi"
mkdir -p "$ANDROID_PROJECT_DIR/gradle/wrapper"
# Root build.gradle.kts
cat > "$ANDROID_PROJECT_DIR/build.gradle.kts" << 'EOF'
// Top-level build file where you can add configuration options common to all sub-projects/modules.
plugins {
id("com.android.application") version "8.2.0" apply false
id("org.jetbrains.kotlin.android") version "1.9.0" apply false
}
allprojects {
repositories {
google()
mavenCentral()
}
}
task<Delete>("clean") {
delete(rootProject.buildDir)
}
EOF
# settings.gradle.kts
cat > "$ANDROID_PROJECT_DIR/settings.gradle.kts" << 'EOF'
pluginManagement {
repositories {
google()
mavenCentral()
gradlePluginPortal()
}
}
dependencyResolutionManagement {
repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS)
repositories {
google()
mavenCentral()
}
}
rootProject.name = "RSSuper"
include(":app")
EOF
# app/build.gradle.kts
cat > "$ANDROID_PROJECT_DIR/app/build.gradle.kts" << 'EOF'
plugins {
id("com.android.application")
id("org.jetbrains.kotlin.android")
}
android {
namespace = "com.mikefreno.rssuper"
compileSdk = 34
defaultConfig {
applicationId = "com.mikefreno.rssuper"
minSdk = 24
targetSdk = 34
versionCode = 1
versionName = "1.0"
testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
}
buildTypes {
release {
isMinifyEnabled = false
proguardFiles(getDefaultProguardFile("proguard-android-optimize.txt"), "proguard-rules.pro")
}
}
compileOptions {
sourceCompatibility = JavaVersion.VERSION_17
targetCompatibility = JavaVersion.VERSION_17
}
kotlinOptions {
jvmTarget = "17"
}
}
dependencies {
implementation("androidx.core:core-ktx:1.12.0")
implementation("androidx.appcompat:appcompat:1.6.1")
implementation("com.google.android.material:material:1.11.0")
implementation("androidx.constraintlayout:constraintlayout:2.1.4")
// Navigation
implementation("androidx.navigation:navigation-fragment-ktx:2.7.6")
implementation("androidx.navigation:navigation-ui-ktx:2.7.6")
// Lifecycle
implementation("androidx.lifecycle:lifecycle-viewmodel-ktx:2.7.0")
implementation("androidx.lifecycle:lifecycle-runtime-ktx:2.7.0")
// Coroutines
implementation("org.jetbrains.kotlinx:kotlinx-coroutines-android:1.7.3")
// Networking
implementation("com.squareup.retrofit2:retrofit:2.9.0")
implementation("com.squareup.retrofit2:converter-gson:2.9.0")
implementation("com.squareup.okhttp3:okhttp:4.12.0")
// Room Database
implementation("androidx.room:room-runtime:2.6.1")
implementation("androidx.room:room-ktx:2.6.1")
testImplementation("junit:junit:4.13.2")
androidTestImplementation("androidx.test.ext:junit:1.1.5")
androidTestImplementation("androidx.test.espresso:espresso-core:3.5.1")
}
EOF
# gradle.properties
cat > "$ANDROID_PROJECT_DIR/gradle.properties" << 'EOF'
org.gradle.jvmargs=-Xmx2048m -Dfile.encoding=UTF-8
android.useAndroidX=true
kotlin.code.style=official
android.nonTransitiveRClass=true
EOF
# gradle wrapper properties
cat > "$ANDROID_PROJECT_DIR/gradle/wrapper/gradle-wrapper.properties" << 'EOF'
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-8.2-bin.zip
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
EOF
# Main Activity
cat > "$ANDROID_PROJECT_DIR/app/src/main/java/com/mikefreno/rssuper/MainActivity.kt" << 'EOF'
package com.mikefreno.rssuper
import android.os.Bundle
import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Surface
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.tooling.preview.Preview
import com.mikefreno.rssuper.ui.theme.RSSuperTheme
class MainActivity : ComponentActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContent {
RSSuperTheme {
Surface(
modifier = Modifier.fillMaxSize(),
color = MaterialTheme.colorScheme.background
) {
Greeting("Android")
}
}
}
}
}
@Composable
fun Greeting(name: String, modifier: Modifier = Modifier) {
Text(
text = "RSSuper - $name",
modifier = modifier
)
}
@Preview(showBackground = true)
@Composable
fun GreetingPreview() {
RSSuperTheme {
Greeting("Android")
}
}
EOF
# Theme
mkdir -p "$ANDROID_PROJECT_DIR/app/src/main/java/com/mikefreno/rssuper/ui/theme"
cat > "$ANDROID_PROJECT_DIR/app/src/main/java/com/mikefreno/rssuper/ui/theme/Theme.kt" << 'EOF'
package com.mikefreno.rssuper.ui.theme
import android.app.Activity
import android.os.Build
import androidx.compose.foundation.isSystemInDarkTheme
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.darkColorScheme
import androidx.compose.material3.dynamicDarkColorScheme
import androidx.compose.material3.dynamicLightColorScheme
import androidx.compose.material3.lightColorScheme
import androidx.compose.runtime.Composable
import androidx.compose.runtime.SideEffect
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.toArgb
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.platform.LocalView
import androidx.core.view.WindowCompat
private val DarkColorScheme = darkColorScheme(
primary = Color(0xFF90CAF9),
secondary = Color(0xFF81D4FA),
tertiary = Color(0xFFA5D6A7)
)
private val LightColorScheme = lightColorScheme(
primary = Color(0xFF1976D2),
secondary = Color(0xFF03A9F4),
tertiary = Color(0xFF4CAF50)
)
@Composable
fun RSSuperTheme(
darkTheme: Boolean = isSystemInDarkTheme(),
dynamicColor: Boolean = true,
content: @Composable () -> Unit
) {
val colorScheme = when {
dynamicColor && Build.VERSION.SDK_INT >= Build.VERSION_CODES.S -> {
val context = LocalContext.current
if (darkTheme) dynamicDarkColorScheme(context) else dynamicLightColorScheme(context)
}
darkTheme -> DarkColorScheme
else -> LightColorScheme
}
val view = LocalView.current
if (!view.isInEditMode) {
SideEffect {
val window = (view.context as Activity).window
window.statusBarColor = colorScheme.primary.toArgb()
WindowCompat.getInsetsController(window, view).isAppearanceLightStatusBars = darkTheme
}
}
MaterialTheme(
colorScheme = colorScheme,
content = content
)
}
EOF
# AndroidManifest.xml
cat > "$ANDROID_PROJECT_DIR/app/src/main/AndroidManifest.xml" << 'EOF'
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="RSSuper"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/Theme.RSSuper">
<activity
android:name=".MainActivity"
android:exported="true"
android:theme="@style/Theme.RSSuper">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>
EOF
# styles.xml
cat > "$ANDROID_PROJECT_DIR/app/src/main/res/values/styles.xml" << 'EOF'
<?xml version="1.0" encoding="utf-8"?>
<resources>
<style name="Theme.RSSuper" parent="android:Theme.Material.Light.NoActionBar">
<item name="android:statusBarColor">@android:color/transparent</item>
</style>
</resources>
EOF
# proguard-rules.pro
cat > "$ANDROID_PROJECT_DIR/app/proguard-rules.pro" << 'EOF'
# Add project specific ProGuard rules here.
-keepattributes Signature
-keepattributes *Annotation*
-keepattributes RuntimeVisibleAnnotations
-keepattributes RuntimeInvisibleAnnotations
EOF
# gradlew script
cat > "$ANDROID_PROJECT_DIR/gradlew" << 'EOF'
#!/bin/bash
# Gradle wrapper placeholder
# In a real project, this would be generated by gradle wrapper
# For now, we'll use system gradle if available
if command -v gradle &> /dev/null; then
exec gradle "$@"
else
echo "Error: Gradle not found. Please install Gradle or use ./gradlew"
exit 1
fi
EOF
chmod +x "$ANDROID_PROJECT_DIR/gradlew"
echo "Android project structure created!"
}
# Build the project
build_project() {
echo "Building Android $VARIANT..."
cd "$ANDROID_PROJECT_DIR"
# Determine gradle task based on variant
local TASK="${ACTION}${VARIANT}""
if [ "$VARIANT" = "release" ]; then
TASK="${ACTION}Release"
fi
echo "Running: ./gradlew $TASK"
./gradlew $TASK
}
# Run tests
run_tests() {
echo "Running Android tests..."
cd "$ANDROID_PROJECT_DIR"
./gradlew test
}
# Clean build
clean_build() {
echo "Cleaning Android build..."
cd "$ANDROID_PROJECT_DIR"
./gradlew clean
}
# Main
case "$ACTION" in
clean)
check_prerequisites
clean_build
;;
test)
check_prerequisites
run_tests
;;
assemble|build|*)
check_prerequisites
build_project
;;
esac