You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

9.4 KiB

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

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:

project(':timesafari-daily-notification-plugin').projectDir = new File('../../../android/plugin')

AAR File Path:

implementation(name: 'plugin-debug', ext: 'aar')

Capacitor Discovery:

{
  "id": "DailyNotification",
  "name": "DailyNotification",
  "class": "com.timesafari.dailynotification.DailyNotificationPlugin"
}

Solution Approaches

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

# 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

# capacitor.settings.gradle
include ':timesafari-daily-notification-plugin'
project(':timesafari-daily-notification-plugin').projectDir = new File('../../../android/plugin')

Step 3: Add Project Dependency

# capacitor.build.gradle
dependencies {
    implementation project(':timesafari-daily-notification-plugin')
}

Step 4: Remove AAR Dependency

# 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

// assets/capacitor.plugins.json
[
  {
    "id": "DailyNotification",
    "name": "DailyNotification",
    "class": "com.timesafari.dailynotification.DailyNotificationPlugin"
  }
]

Method 2: AAR-Only Resolution

Step 1: Remove Project References

# 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

# 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

# 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

# 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

# Clean build should succeed
./gradlew clean assembleDebug

Success Indicators:

  • Build completes without errors
  • No duplicate class warnings
  • APK generated successfully

3. Runtime Verification

# 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:

# Weekly cache cleanup
./gradlew --stop
rm -rf ~/.gradle/caches

Before Major Changes:

# Clear cache before switching approaches
rm -rf ~/.gradle

3. Project Structure Validation

Verify Paths:

# Check project structure
ls -la ../../../android/plugin/
ls -la libs/

Validate Configuration:

# 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

Community

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.