From ef37b10503672b70e35cb3b26fdc7b2a0440638d Mon Sep 17 00:00:00 2001 From: Matthew Raymer Date: Thu, 23 Oct 2025 10:29:13 +0000 Subject: [PATCH] docs: add comprehensive AAR integration troubleshooting guide - Add AAR Duplicate Class Issues section to BUILDING.md with step-by-step solutions - Create dedicated docs/aar-integration-troubleshooting.md with complete troubleshooting guide - Document project reference approach (recommended) vs AAR-only approach - Add verification steps, prevention strategies, and best practices - Update README.md with links to new documentation - Resolve duplicate class issues through proper project reference configuration Fixes AAR integration issues that caused build failures due to plugin being included both as project reference and AAR file simultaneously. --- BUILDING.md | 72 +++++ README.md | 2 + docs/aar-integration-troubleshooting.md | 372 ++++++++++++++++++++++++ 3 files changed, 446 insertions(+) create mode 100644 docs/aar-integration-troubleshooting.md diff --git a/BUILDING.md b/BUILDING.md index 3b37b21..811536a 100644 --- a/BUILDING.md +++ b/BUILDING.md @@ -537,6 +537,45 @@ adb install app/build/outputs/apk/debug/app-debug.apk - Interactive testing interface - Comprehensive logging and debugging +**Plugin Integration Approach:** +The Vue 3 test app uses a **project reference approach** for plugin integration: + +1. **Project Reference Configuration**: + ```gradle + // capacitor.settings.gradle + include ':timesafari-daily-notification-plugin' + project(':timesafari-daily-notification-plugin').projectDir = new File('../../../android/plugin') + + // capacitor.build.gradle + implementation project(':timesafari-daily-notification-plugin') + ``` + +2. **Required Dependencies**: + ```gradle + // app/build.gradle + 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' + ``` + +3. **Plugin Discovery**: + ```json + // assets/capacitor.plugins.json + [ + { + "id": "DailyNotification", + "name": "DailyNotification", + "class": "com.timesafari.dailynotification.DailyNotificationPlugin" + } + ] + ``` + +**Troubleshooting Integration Issues:** +- **Duplicate Classes**: Use project reference instead of AAR to avoid conflicts +- **Gradle Cache**: Clear completely (`rm -rf ~/.gradle`) when switching approaches +- **Path Issues**: Ensure correct project path (`../../../android/plugin`) +- **Dependencies**: Include required WorkManager and Gson dependencies + ### Integration Testing #### 1. Create External Test Capacitor App @@ -857,6 +896,39 @@ npm list @timesafari/daily-notification-plugin npx cap sync android ``` +#### AAR Duplicate Class Issues +```bash +# Problem: Duplicate class errors when integrating plugin AAR +# Error: "Duplicate class com.timesafari.dailynotification.BootReceiver found in modules" +# Root Cause: Plugin being included both as project reference and as AAR file + +# Solution 1: Use Project Reference Approach (Recommended) +# 1. Clear Gradle cache completely +./gradlew --stop +rm -rf ~/.gradle +rm -rf app/build +rm -rf build + +# 2. Configure project reference in capacitor.settings.gradle +include ':timesafari-daily-notification-plugin' +project(':timesafari-daily-notification-plugin').projectDir = new File('../../../android/plugin') + +# 3. Add dependency in capacitor.build.gradle +implementation project(':timesafari-daily-notification-plugin') + +# 4. Remove AAR dependency from app/build.gradle +# Comment out: implementation(name: 'plugin-debug', ext: 'aar') + +# Solution 2: AAR-Only Approach (Alternative) +# 1. Remove project references from capacitor.settings.gradle and capacitor.build.gradle +# 2. Ensure only AAR dependency in app/build.gradle +# 3. Remove any duplicate classes.jar files from libs/ directory +# 4. Clear Gradle cache and rebuild + +# Verification: Check that plugin is included only once +./gradlew :app:dependencies | grep timesafari +``` + ### Debug Commands #### Android Debugging diff --git a/README.md b/README.md index 61b1374..315a2a9 100644 --- a/README.md +++ b/README.md @@ -735,6 +735,8 @@ MIT License - see [LICENSE](LICENSE) file for details. - **API Reference**: Complete TypeScript definitions - **Migration Guide**: [doc/migration-guide.md](doc/migration-guide.md) - **Integration Guide**: [INTEGRATION_GUIDE.md](INTEGRATION_GUIDE.md) - Complete integration instructions +- **Building Guide**: [BUILDING.md](BUILDING.md) - Comprehensive build instructions and troubleshooting +- **AAR Integration Troubleshooting**: [docs/aar-integration-troubleshooting.md](docs/aar-integration-troubleshooting.md) - Resolving duplicate class issues - **Implementation Guide**: [doc/STARRED_PROJECTS_POLLING_IMPLEMENTATION.md](doc/STARRED_PROJECTS_POLLING_IMPLEMENTATION.md) - Generic polling interface - **UI Requirements**: [doc/UI_REQUIREMENTS.md](doc/UI_REQUIREMENTS.md) - Complete UI component requirements - **Host App Examples**: [examples/hello-poll.ts](examples/hello-poll.ts) - Generic polling integration diff --git a/docs/aar-integration-troubleshooting.md b/docs/aar-integration-troubleshooting.md new file mode 100644 index 0000000..c1a2425 --- /dev/null +++ b/docs/aar-integration-troubleshooting.md @@ -0,0 +1,372 @@ +# 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.