From d0878507a6499858635ec3362bbd7007a999d5ef Mon Sep 17 00:00:00 2001 From: Matthew Date: Mon, 2 Feb 2026 02:06:44 -0800 Subject: [PATCH] fix(android): Auto-detect Java/SDK and fix KAPT Java 17+ compatibility - Auto-detect Java from Android Studio (JBR/JRE) or system PATH - Auto-detect Android SDK from common locations or local.properties - Auto-write SDK location to local.properties for Gradle - Add KAPT JVM args to gradle.properties for Java 17+ module access - Fix Java version command quoting for paths with spaces - Comment out DailyNotificationPlugin (Java class not implemented) Eliminates manual JAVA_HOME/ANDROID_HOME setup requirements and fixes KAPT compilation errors when using Java 17+. Author: Matthew Raymer --- android/app/capacitor.build.gradle | 1 + android/app/src/main/AndroidManifest.xml | 6 +- .../src/main/assets/capacitor.plugins.json | 4 + .../java/app/timesafari/MainActivity.java | 3 +- android/build.gradle | 3 + android/capacitor.settings.gradle | 3 + android/gradle.properties | 3 +- package-lock.json | 6 +- scripts/build-android.sh | 152 ++++++++++++++++++ 9 files changed, 173 insertions(+), 8 deletions(-) diff --git a/android/app/capacitor.build.gradle b/android/app/capacitor.build.gradle index f1774d9f..820cd36a 100644 --- a/android/app/capacitor.build.gradle +++ b/android/app/capacitor.build.gradle @@ -18,6 +18,7 @@ dependencies { implementation project(':capacitor-share') implementation project(':capacitor-status-bar') implementation project(':capawesome-capacitor-file-picker') + implementation project(':timesafari-daily-notification-plugin') } diff --git a/android/app/src/main/AndroidManifest.xml b/android/app/src/main/AndroidManifest.xml index cbb419a5..83ff8bee 100644 --- a/android/app/src/main/AndroidManifest.xml +++ b/android/app/src/main/AndroidManifest.xml @@ -56,8 +56,8 @@ - + android:exported="false" + /> - + diff --git a/android/app/src/main/assets/capacitor.plugins.json b/android/app/src/main/assets/capacitor.plugins.json index 438497bf..7e0d8ea0 100644 --- a/android/app/src/main/assets/capacitor.plugins.json +++ b/android/app/src/main/assets/capacitor.plugins.json @@ -35,6 +35,10 @@ "pkg": "@capawesome/capacitor-file-picker", "classpath": "io.capawesome.capacitorjs.plugins.filepicker.FilePickerPlugin" }, + { + "pkg": "@timesafari/daily-notification-plugin", + "classpath": "com.timesafari.dailynotification.DailyNotificationPlugin" + }, { "pkg": "SafeArea", "classpath": "app.timesafari.safearea.SafeAreaPlugin" diff --git a/android/app/src/main/java/app/timesafari/MainActivity.java b/android/app/src/main/java/app/timesafari/MainActivity.java index 2e85dfea..244a803c 100644 --- a/android/app/src/main/java/app/timesafari/MainActivity.java +++ b/android/app/src/main/java/app/timesafari/MainActivity.java @@ -68,7 +68,8 @@ public class MainActivity extends BridgeActivity { registerPlugin(SharedImagePlugin.class); // Register DailyNotification plugin - registerPlugin(com.timesafari.dailynotification.DailyNotificationPlugin.class); + // TODO: Uncomment when DailyNotificationPlugin Java class is implemented + // registerPlugin(com.timesafari.dailynotification.DailyNotificationPlugin.class); // Initialize SQLite //registerPlugin(SQLite.class); diff --git a/android/build.gradle b/android/build.gradle index 4bd6375d..56002bf3 100644 --- a/android/build.gradle +++ b/android/build.gradle @@ -22,6 +22,9 @@ allprojects { google() mavenCentral() } + + // Note: KAPT JVM arguments for Java 17+ compatibility are configured in gradle.properties + // The org.gradle.jvmargs setting includes --add-opens flags needed for KAPT } task clean(type: Delete) { diff --git a/android/capacitor.settings.gradle b/android/capacitor.settings.gradle index 891b5455..0319aa38 100644 --- a/android/capacitor.settings.gradle +++ b/android/capacitor.settings.gradle @@ -28,3 +28,6 @@ project(':capacitor-status-bar').projectDir = new File('../node_modules/@capacit include ':capawesome-capacitor-file-picker' project(':capawesome-capacitor-file-picker').projectDir = new File('../node_modules/@capawesome/capacitor-file-picker/android') + +include ':timesafari-daily-notification-plugin' +project(':timesafari-daily-notification-plugin').projectDir = new File('../node_modules/@timesafari/daily-notification-plugin/android') diff --git a/android/gradle.properties b/android/gradle.properties index 8ea85815..98bddd32 100644 --- a/android/gradle.properties +++ b/android/gradle.properties @@ -9,7 +9,8 @@ # Specifies the JVM arguments used for the daemon process. # The setting is particularly useful for tweaking memory settings. -org.gradle.jvmargs=-Xmx1536m +# Added --add-opens flags for KAPT compatibility with Java 17+ +org.gradle.jvmargs=-Xmx1536m --add-opens=jdk.compiler/com.sun.tools.javac.api=ALL-UNNAMED --add-opens=jdk.compiler/com.sun.tools.javac.code=ALL-UNNAMED --add-opens=jdk.compiler/com.sun.tools.javac.comp=ALL-UNNAMED --add-opens=jdk.compiler/com.sun.tools.javac.file=ALL-UNNAMED --add-opens=jdk.compiler/com.sun.tools.javac.jvm=ALL-UNNAMED --add-opens=jdk.compiler/com.sun.tools.javac.main=ALL-UNNAMED --add-opens=jdk.compiler/com.sun.tools.javac.parser=ALL-UNNAMED --add-opens=jdk.compiler/com.sun.tools.javac.processing=ALL-UNNAMED --add-opens=jdk.compiler/com.sun.tools.javac.tree=ALL-UNNAMED --add-opens=jdk.compiler/com.sun.tools.javac.util=ALL-UNNAMED # When configured, Gradle will run in incubating parallel mode. # This option should only be used with decoupled projects. More details, visit diff --git a/package-lock.json b/package-lock.json index a17d069e..285756a7 100644 --- a/package-lock.json +++ b/package-lock.json @@ -5195,9 +5195,9 @@ } }, "node_modules/@expo/cli": { - "version": "54.0.22", - "resolved": "https://registry.npmjs.org/@expo/cli/-/cli-54.0.22.tgz", - "integrity": "sha512-BTH2FCczhJLfj1cpfcKrzhKnvRLTOztgW4bVloKDqH+G3ZSohWLRFNAIz56XtdjPxBbi2/qWhGBAkl7kBon/Jw==", + "version": "54.0.23", + "resolved": "https://registry.npmjs.org/@expo/cli/-/cli-54.0.23.tgz", + "integrity": "sha512-km0h72SFfQCmVycH/JtPFTVy69w6Lx1cHNDmfLfQqgKFYeeHTjx7LVDP4POHCtNxFP2UeRazrygJhlh4zz498g==", "license": "MIT", "optional": true, "dependencies": { diff --git a/scripts/build-android.sh b/scripts/build-android.sh index 8a29bf9b..4a5fc808 100755 --- a/scripts/build-android.sh +++ b/scripts/build-android.sh @@ -75,6 +75,146 @@ validate_dependencies() { log_success "All critical dependencies validated successfully" } +# Function to detect and set JAVA_HOME for Android builds +setup_java_home() { + log_info "Setting up Java environment..." + + # If JAVA_HOME is already set and valid, use it + if [ -n "$JAVA_HOME" ] && [ -x "$JAVA_HOME/bin/java" ]; then + log_debug "Using existing JAVA_HOME: $JAVA_HOME" + export JAVA_HOME + return 0 + fi + + # Try to find Java in Android Studio's bundled JBR + local android_studio_jbr="/Applications/Android Studio.app/Contents/jbr/Contents/Home" + if [ -d "$android_studio_jbr" ] && [ -x "$android_studio_jbr/bin/java" ]; then + export JAVA_HOME="$android_studio_jbr" + log_info "Found Java in Android Studio: $JAVA_HOME" + if [ -x "$JAVA_HOME/bin/java" ]; then + log_debug "Java version: $(\"$JAVA_HOME/bin/java\" -version 2>&1 | head -1 || echo 'Unable to get version')" + fi + return 0 + fi + + # Try alternative Android Studio location (older versions) + local android_studio_jre="/Applications/Android Studio.app/Contents/jre/Contents/Home" + if [ -d "$android_studio_jre" ] && [ -x "$android_studio_jre/bin/java" ]; then + export JAVA_HOME="$android_studio_jre" + log_info "Found Java in Android Studio (legacy): $JAVA_HOME" + log_debug "Java version: $(\"$JAVA_HOME/bin/java\" -version 2>&1 | head -1)" + return 0 + fi + + # Try to use /usr/libexec/java_home on macOS + if [ "$(uname)" = "Darwin" ] && command -v /usr/libexec/java_home >/dev/null 2>&1; then + local java_home_output=$(/usr/libexec/java_home 2>/dev/null) + if [ -n "$java_home_output" ] && [ -x "$java_home_output/bin/java" ]; then + export JAVA_HOME="$java_home_output" + log_info "Found Java via java_home utility: $JAVA_HOME" + log_debug "Java version: $(\"$JAVA_HOME/bin/java\" -version 2>&1 | head -1)" + return 0 + fi + fi + + # Try to find java in PATH + if command -v java >/dev/null 2>&1; then + local java_path=$(command -v java) + # Resolve symlinks to find actual Java home (portable approach) + local java_real="$java_path" + # Try different methods to resolve symlinks + if [ -L "$java_path" ]; then + if command -v readlink >/dev/null 2>&1; then + java_real=$(readlink "$java_path" 2>/dev/null || echo "$java_path") + elif command -v realpath >/dev/null 2>&1; then + java_real=$(realpath "$java_path" 2>/dev/null || echo "$java_path") + fi + fi + local java_home_candidate=$(dirname "$(dirname "$java_real")") + if [ -d "$java_home_candidate" ] && [ -x "$java_home_candidate/bin/java" ]; then + export JAVA_HOME="$java_home_candidate" + log_info "Found Java in PATH: $JAVA_HOME" + log_debug "Java version: $(\"$JAVA_HOME/bin/java\" -version 2>&1 | head -1)" + return 0 + fi + fi + + # If we get here, Java was not found + log_error "Java Runtime not found!" + log_error "Please ensure one of the following:" + log_error " 1. Android Studio is installed (includes bundled Java)" + log_error " 2. JAVA_HOME is set to a valid Java installation" + log_error " 3. Java is available in your PATH" + log_error "" + log_error "On macOS, Android Studio typically includes Java at:" + log_error " /Applications/Android Studio.app/Contents/jbr/Contents/Home" + return 1 +} + +# Function to detect and set ANDROID_HOME for Android builds +setup_android_home() { + log_info "Setting up Android SDK environment..." + + # If ANDROID_HOME is already set and valid, use it + if [ -n "$ANDROID_HOME" ] && [ -d "$ANDROID_HOME" ]; then + log_debug "Using existing ANDROID_HOME: $ANDROID_HOME" + export ANDROID_HOME + return 0 + fi + + # Check for local.properties file in android directory + local local_props="android/local.properties" + if [ -f "$local_props" ]; then + local sdk_dir=$(grep "^sdk.dir=" "$local_props" 2>/dev/null | cut -d'=' -f2 | sed 's/^[[:space:]]*//;s/[[:space:]]*$//' | sed "s|^file://||") + if [ -n "$sdk_dir" ] && [ -d "$sdk_dir" ]; then + export ANDROID_HOME="$sdk_dir" + log_info "Found Android SDK in local.properties: $ANDROID_HOME" + return 0 + fi + fi + + # Try common macOS locations for Android SDK + local common_locations=( + "$HOME/Library/Android/sdk" + "$HOME/Android/Sdk" + "$HOME/.android/sdk" + ) + + for sdk_path in "${common_locations[@]}"; do + if [ -d "$sdk_path" ] && [ -d "$sdk_path/platform-tools" ]; then + export ANDROID_HOME="$sdk_path" + log_info "Found Android SDK: $ANDROID_HOME" + + # Write to local.properties if it doesn't exist or doesn't have sdk.dir + if [ ! -f "$local_props" ] || ! grep -q "^sdk.dir=" "$local_props" 2>/dev/null; then + log_info "Writing Android SDK location to local.properties" + mkdir -p android + if [ -f "$local_props" ]; then + echo "" >> "$local_props" + echo "sdk.dir=$ANDROID_HOME" >> "$local_props" + else + echo "sdk.dir=$ANDROID_HOME" > "$local_props" + fi + fi + + return 0 + fi + done + + # If we get here, Android SDK was not found + log_error "Android SDK not found!" + log_error "Please ensure one of the following:" + log_error " 1. ANDROID_HOME is set to a valid Android SDK location" + log_error " 2. Android SDK is installed at one of these locations:" + log_error " - $HOME/Library/Android/sdk (macOS default)" + log_error " - $HOME/Android/Sdk" + log_error " 3. android/local.properties contains sdk.dir pointing to SDK" + log_error "" + log_error "You can find your SDK location in Android Studio:" + log_error " Preferences > Appearance & Behavior > System Settings > Android SDK" + return 1 +} + # Function to validate Android assets and resources validate_android_assets() { log_info "Validating Android assets and resources..." @@ -326,6 +466,18 @@ print_header "TimeSafari Android Build Process" # Validate dependencies before proceeding validate_dependencies +# Setup Java environment for Gradle +setup_java_home || { + log_error "Failed to setup Java environment. Cannot proceed with Android build." + exit 1 +} + +# Setup Android SDK environment for Gradle +setup_android_home || { + log_error "Failed to setup Android SDK environment. Cannot proceed with Android build." + exit 1 +} + # Validate Android assets and resources validate_android_assets || { log_error "Android asset validation failed. Please fix the issues above and try again."