# AAR Integration Troubleshooting Guide **Author**: Matthew Raymer **Last Updated**: 2025-01-27 **Version**: 1.0.0 ## Overview This document provides comprehensive troubleshooting guidance for integrating the DailyNotification plugin AAR into Android applications, specifically addressing the common duplicate class issues that occur during plugin integration. ## Table of Contents - [Common Issues](#common-issues) - [Root Cause Analysis](#root-cause-analysis) - [Solution Approaches](#solution-approaches) - [Step-by-Step Resolution](#step-by-step-resolution) - [Verification Steps](#verification-steps) - [Prevention Strategies](#prevention-strategies) - [Best Practices](#best-practices) ## Common Issues ### Duplicate Class Errors **Error Message:** ``` Duplicate class com.timesafari.dailynotification.BootReceiver found in modules: - plugin-debug.aar -> plugin-debug-runtime (:plugin-debug:) - plugin-debug.aar -> plugin-debug-runtime (plugin-debug.aar) ``` **Symptoms:** - Build fails with duplicate class errors - Plugin classes appear twice in dependency tree - Gradle build process hangs or fails - AAR integration appears broken ### Gradle Cache Corruption **Error Message:** ``` Could not read workspace metadata from /home/user/.gradle/caches/8.13/transforms/.../metadata.bin No matching variant of project :timesafari-daily-notification-plugin was found ``` **Symptoms:** - Gradle sync failures - Project reference resolution issues - Inconsistent build behavior - Cache-related build errors ## Root Cause Analysis ### Primary Cause: Dual Inclusion The duplicate class issue occurs when the plugin is included **twice** in the build process: 1. **As Project Reference**: Capacitor's automatic plugin discovery includes the plugin as a project reference 2. **As AAR File**: The AAR file is also included directly in the build dependencies ### Contributing Factors 1. **Capacitor Auto-Discovery**: Capacitor automatically discovers plugins via `capacitor.plugins.json` 2. **Symlinked Dependencies**: Node modules may create symlinks that confuse Gradle 3. **Gradle Cache Issues**: Corrupted cache can cause inconsistent behavior 4. **Path Resolution**: Incorrect project paths can cause module resolution failures ### Technical Details **Project Reference Path:** ```gradle project(':timesafari-daily-notification-plugin').projectDir = new File('../../../android/plugin') ``` **AAR File Path:** ```gradle implementation(name: 'plugin-debug', ext: 'aar') ``` **Capacitor Discovery:** ```json { "id": "DailyNotification", "name": "DailyNotification", "class": "com.timesafari.dailynotification.DailyNotificationPlugin" } ``` ## Solution Approaches ### Approach 1: Project Reference (Recommended) **Advantages:** - ✅ No duplicate class issues - ✅ Better development experience - ✅ Automatic dependency resolution - ✅ Easier debugging and testing **Disadvantages:** - ❌ Requires correct project structure - ❌ More complex initial setup - ❌ Path-dependent configuration ### Approach 2: AAR-Only **Advantages:** - ✅ Simpler dependency management - ✅ Self-contained distribution - ✅ No project structure dependencies **Disadvantages:** - ❌ Prone to duplicate class issues - ❌ Requires manual dependency management - ❌ Harder to debug and test ## Step-by-Step Resolution ### Method 1: Project Reference Resolution #### Step 1: Clear Gradle Cache ```bash # Stop Gradle daemon ./gradlew --stop # Clear all Gradle caches rm -rf ~/.gradle # Clear project build directories rm -rf app/build rm -rf build ``` #### Step 2: Configure Project Reference ```gradle # capacitor.settings.gradle include ':timesafari-daily-notification-plugin' project(':timesafari-daily-notification-plugin').projectDir = new File('../../../android/plugin') ``` #### Step 3: Add Project Dependency ```gradle # capacitor.build.gradle dependencies { implementation project(':timesafari-daily-notification-plugin') } ``` #### Step 4: Remove AAR Dependency ```gradle # app/build.gradle dependencies { // Comment out or remove AAR dependency // implementation(name: 'plugin-debug', ext: 'aar') // Keep required dependencies implementation 'androidx.work:work-runtime:2.9.0' implementation 'androidx.lifecycle:lifecycle-service:2.7.0' implementation 'com.google.code.gson:gson:2.10.1' } ``` #### Step 5: Verify Plugin Discovery ```json // assets/capacitor.plugins.json [ { "id": "DailyNotification", "name": "DailyNotification", "class": "com.timesafari.dailynotification.DailyNotificationPlugin" } ] ``` ### Method 2: AAR-Only Resolution #### Step 1: Remove Project References ```gradle # capacitor.settings.gradle - Comment out project reference // include ':timesafari-daily-notification-plugin' // project(':timesafari-daily-notification-plugin').projectDir = new File('../../../android/plugin') # capacitor.build.gradle - Comment out project dependency // implementation project(':timesafari-daily-notification-plugin') ``` #### Step 2: Ensure AAR-Only Dependency ```gradle # app/build.gradle dependencies { implementation(name: 'plugin-debug', ext: 'aar') implementation 'androidx.work:work-runtime:2.9.0' implementation 'androidx.lifecycle:lifecycle-service:2.7.0' implementation 'com.google.code.gson:gson:2.10.1' } ``` #### Step 3: Remove Duplicate Files ```bash # Remove any duplicate classes.jar files rm -f libs/classes.jar rm -f libs/*.jar # Clean and rebuild ./gradlew clean build ``` ## Verification Steps ### 1. Check Dependency Tree ```bash # Verify plugin is included only once ./gradlew :app:dependencies | grep timesafari ``` **Expected Output:** ``` +--- project :timesafari-daily-notification-plugin ``` **Problematic Output:** ``` +--- project :timesafari-daily-notification-plugin +--- plugin-debug.aar ``` ### 2. Build Verification ```bash # Clean build should succeed ./gradlew clean assembleDebug ``` **Success Indicators:** - ✅ Build completes without errors - ✅ No duplicate class warnings - ✅ APK generated successfully ### 3. Runtime Verification ```bash # Install and test adb install app/build/outputs/apk/debug/app-debug.apk adb logcat | grep DailyNotification ``` **Success Indicators:** - ✅ App launches without crashes - ✅ Plugin detected in logs - ✅ Plugin methods accessible ## Prevention Strategies ### 1. Consistent Approach Selection **Choose One Approach:** - **Development**: Use project reference for better debugging - **Production**: Use AAR for simpler distribution - **Never Mix**: Don't use both approaches simultaneously ### 2. Gradle Cache Management **Regular Maintenance:** ```bash # Weekly cache cleanup ./gradlew --stop rm -rf ~/.gradle/caches ``` **Before Major Changes:** ```bash # Clear cache before switching approaches rm -rf ~/.gradle ``` ### 3. Project Structure Validation **Verify Paths:** ```bash # Check project structure ls -la ../../../android/plugin/ ls -la libs/ ``` **Validate Configuration:** ```bash # Check Gradle configuration ./gradlew :app:dependencies --configuration debugRuntimeClasspath ``` ## Best Practices ### 1. Development Workflow **Initial Setup:** 1. Choose integration approach (project reference recommended) 2. Configure all necessary files 3. Clear Gradle cache 4. Build and test **Ongoing Development:** 1. Avoid switching approaches mid-development 2. Clear cache when making structural changes 3. Test integration after major updates ### 2. Configuration Management **File Organization:** - Keep `capacitor.settings.gradle` minimal - Use `capacitor.build.gradle` for dependencies - Maintain `capacitor.plugins.json` for discovery **Version Consistency:** - Use consistent Android Gradle Plugin versions - Align Gradle wrapper versions - Match dependency versions across modules ### 3. Testing Strategy **Build Testing:** - Test both debug and release builds - Verify on multiple Android versions - Check dependency resolution **Runtime Testing:** - Test plugin functionality - Verify permission handling - Check background task execution ## Troubleshooting Checklist ### Before Starting - [ ] Clear Gradle cache (`rm -rf ~/.gradle`) - [ ] Stop Gradle daemon (`./gradlew --stop`) - [ ] Verify project structure - [ ] Check file permissions ### During Integration - [ ] Use only one integration approach - [ ] Verify all configuration files - [ ] Check dependency tree - [ ] Test build process ### After Integration - [ ] Verify app launches - [ ] Test plugin functionality - [ ] Check logs for errors - [ ] Validate permissions ### Common Mistakes - [ ] Mixing project reference and AAR approaches - [ ] Incorrect project paths - [ ] Forgetting to clear Gradle cache - [ ] Missing required dependencies - [ ] Incorrect plugin discovery configuration ## Support and Resources ### Documentation - [BUILDING.md](../BUILDING.md) - Main build documentation - [INTEGRATION_GUIDE.md](../INTEGRATION_GUIDE.md) - Integration guide - [API.md](../API.md) - Plugin API documentation ### Community - [GitHub Issues](https://github.com/timesafari/daily-notification-plugin/issues) - [Capacitor Community](https://github.com/ionic-team/capacitor/discussions) ### Tools - `./gradlew :app:dependencies` - Dependency analysis - `adb logcat | grep DailyNotification` - Runtime debugging - `./gradlew clean build` - Clean build verification --- **Remember**: The key to successful AAR integration is consistency. Choose one approach, configure it properly, and maintain it throughout development. When in doubt, clear the Gradle cache and start fresh.