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.
This commit is contained in:
372
docs/aar-integration-troubleshooting.md
Normal file
372
docs/aar-integration-troubleshooting.md
Normal file
@@ -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.
|
||||
Reference in New Issue
Block a user