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:
Matthew Raymer
2025-10-23 10:29:32 +00:00
parent ef37b10503
commit 7185c87e93
13 changed files with 113 additions and 135 deletions

View File

@@ -25,6 +25,10 @@ android {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
debug {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
}
@@ -35,7 +39,7 @@ repositories {
}
dependencies {
implementation fileTree(include: ['*.jar'], dir: 'libs')
implementation fileTree(include: ['*.jar', '*.aar'], dir: 'libs')
implementation "androidx.appcompat:appcompat:$androidxAppCompatVersion"
implementation "androidx.coordinatorlayout:coordinatorlayout:$androidxCoordinatorLayoutVersion"
implementation "androidx.core:core-splashscreen:$coreSplashScreenVersion"
@@ -44,6 +48,11 @@ dependencies {
// Capacitor annotation processor for automatic plugin discovery
annotationProcessor project(':capacitor-android')
// Required dependencies for the plugin
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'
testImplementation "junit:junit:$junitVersion"
androidTestImplementation "androidx.test.ext:junit:$androidxJunitVersion"
androidTestImplementation "androidx.test.espresso:espresso-core:$androidxEspressoCoreVersion"

View File

@@ -7,7 +7,7 @@ buildscript {
mavenCentral()
}
dependencies {
classpath 'com.android.tools.build:gradle:8.7.2'
classpath 'com.android.tools.build:gradle:8.13.0'
classpath 'com.google.gms:google-services:4.4.2'
// NOTE: Do not place your application dependencies here; they belong

View File

@@ -3,4 +3,4 @@ include ':capacitor-android'
project(':capacitor-android').projectDir = new File('../node_modules/@capacitor/android/capacitor')
include ':timesafari-daily-notification-plugin'
project(':timesafari-daily-notification-plugin').projectDir = new File('../node_modules/@timesafari/daily-notification-plugin/android/plugin')
project(':timesafari-daily-notification-plugin').projectDir = new File('../../../android/plugin')

View File

@@ -1,25 +0,0 @@
apply plugin: 'com.android.library'
android {
namespace "com.timesafari.dailynotification"
compileSdkVersion rootProject.ext.compileSdkVersion
defaultConfig {
minSdkVersion rootProject.ext.minSdkVersion
targetSdkVersion rootProject.ext.targetSdkVersion
versionCode 1
versionName "1.0"
}
compileOptions {
sourceCompatibility JavaVersion.VERSION_17
targetCompatibility JavaVersion.VERSION_17
}
}
dependencies {
implementation project(':capacitor-android')
// Capacitor annotation processor for automatic plugin discovery
annotationProcessor project(':capacitor-android')
}

View File

@@ -1,6 +0,0 @@
[
{
"name": "DailyNotification",
"classpath": "com.timesafari.dailynotification.DailyNotificationPlugin"
}
]

View File

@@ -1,43 +0,0 @@
package com.timesafari.dailynotification;
import com.getcapacitor.JSObject;
import com.getcapacitor.Plugin;
import com.getcapacitor.PluginCall;
import com.getcapacitor.PluginMethod;
import com.getcapacitor.annotation.CapacitorPlugin;
@CapacitorPlugin(name = "DailyNotification")
public class DailyNotificationPlugin extends Plugin {
@Override
public void load() {
super.load();
// Log that the plugin has loaded
android.util.Log.d("DailyNotificationPlugin", "Plugin load() method called");
System.out.println("DN|PLUGIN_LOAD_START");
}
@PluginMethod
public void echo(PluginCall call) {
String value = call.getString("value");
JSObject ret = new JSObject();
ret.put("value", value);
call.resolve(ret);
}
@PluginMethod
public void checkStatus(PluginCall call) {
JSObject ret = new JSObject();
ret.put("status", "OK from native plugin");
call.resolve(ret);
}
@PluginMethod
public void scheduleNotification(PluginCall call) {
String title = call.getString("title");
String message = call.getString("message");
JSObject ret = new JSObject();
ret.put("scheduleResult", "Notification '" + title + "' scheduled with message '" + message + "'");
call.resolve(ret);
}
}

View File

@@ -1,6 +1,6 @@
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-8.11.1-all.zip
distributionUrl=https\://services.gradle.org/distributions/gradle-8.13-bin.zip
networkTimeout=10000
validateDistributionUrl=true
zipStoreBase=GRADLE_USER_HOME

View File

@@ -28,6 +28,26 @@ declare global {
}): Promise<void>
cancelNotification(id: string): Promise<void>
requestPermissions(): Promise<boolean>
getNotificationStatus(): Promise<{
isEnabled: boolean
isScheduled: boolean
lastNotificationTime: number
nextNotificationTime: number
pending: number
error?: string
}>
checkPermissions(): Promise<{
notifications: 'granted' | 'denied' | 'prompt'
exactAlarms: 'granted' | 'denied' | 'not_supported'
batteryOptimization: 'granted' | 'denied' | 'not_supported'
overall: 'ready' | 'partial' | 'blocked'
}>
getExactAlarmStatus(): Promise<{
supported: boolean
enabled: boolean
canSchedule: boolean
}>
requestNotificationPermissions(): Promise<void>
}
Capacitor?: {
Plugins?: {
@@ -50,6 +70,26 @@ declare global {
}): Promise<void>
cancelNotification(id: string): Promise<void>
requestPermissions(): Promise<boolean>
getNotificationStatus(): Promise<{
isEnabled: boolean
isScheduled: boolean
lastNotificationTime: number
nextNotificationTime: number
pending: number
error?: string
}>
checkPermissions(): Promise<{
notifications: 'granted' | 'denied' | 'prompt'
exactAlarms: 'granted' | 'denied' | 'not_supported'
batteryOptimization: 'granted' | 'denied' | 'not_supported'
overall: 'ready' | 'partial' | 'blocked'
}>
getExactAlarmStatus(): Promise<{
supported: boolean
enabled: boolean
canSchedule: boolean
}>
requestNotificationPermissions(): Promise<void>
}
Clipboard?: {
write(options: { string: string }): Promise<void>

View File

@@ -239,6 +239,13 @@ const checkSystemStatus = async (): Promise<void> => {
// Log permission status for debugging
if (!mappedStatus.postNotificationsGranted) {
console.warn('⚠️ Notification permissions not granted - user needs to enable in settings')
console.log('🔧 Testing permission request...')
try {
await plugin.requestPermissions()
console.log('✅ Permission request completed')
} catch (permError) {
console.error('❌ Permission request failed:', permError)
}
}
} catch (error) {
console.error('❌ Plugin status check failed:', error)