Consolidate all markdown documentation into organized structure per CONSOLIDATION_DIRECTIVE. All files preserved (canonical, merged, or archived). - docs/integration/ - Integration documentation (7 files) - docs/platform/ios/ - iOS platform docs (12 files) - docs/platform/android/ - Android platform docs (9 files) - docs/testing/ - Testing documentation (15 files) - docs/design/ - Design & research (5 files) - docs/ai/ - AI/ChatGPT artifacts (7 files) - docs/archive/2025-legacy-doc/ - Historical docs (17 files) - Integration: Root INTEGRATION_GUIDE.md → docs/integration/ - Platform: Separated iOS and Android into platform/ subdirectories - Testing: Consolidated all testing docs to docs/testing/ - Legacy: Archived entire doc/ directory to archive/ - AI: Moved all ChatGPT artifacts to docs/ai/ - Added docs/00-INDEX.md - Central navigation hub - Added docs/CONSOLIDATION_SOURCE_MAP.md - Complete audit trail - Added docs/CONSOLIDATION_COMPLETE.md - Consolidation summary - Updated README.md with links to documentation index - All 139 files have destinations (see CONSOLIDATION_SOURCE_MAP.md) - Zero information loss (all files preserved) - Archive preserves original structure - Index provides clear navigation - 87 files moved/created/updated - Root-level docs consolidated - Legacy doc/ directory archived - Test app docs remain with test apps (indexed) Ref: CONSOLIDATION_DIRECTIVE Author: Matthew Raymer
373 lines
9.4 KiB
Markdown
373 lines
9.4 KiB
Markdown
# 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.
|