Browse Source
- 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.master
3 changed files with 446 additions and 0 deletions
@ -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. |
|||
Loading…
Reference in new issue