Updates BUILDING.md to reflect recent changes in build-native.sh, especially
the Xcode Command Line Tools prerequisite check and the clean-build script.
Problem:
- BUILDING.md didn't mention Xcode Command Line Tools prerequisite
(recently added to build-native.sh)
- clean-build.sh script exists but wasn't documented
- iOS build troubleshooting lacked Command Line Tools guidance
Changes:
- Add Xcode Command Line Tools to Prerequisites section
- Document installation command (xcode-select --install)
- Include verification steps (xcode-select -p, xcodebuild -version)
- Note that build script automatically checks for these tools
- Explain that sqlite3 is part of Command Line Tools
- Document clean-build.sh script in Build Scripts section
- Basic usage: ./scripts/clean-build.sh
- All options: --all, --clean-gradle-cache, --clean-derived-data,
--reinstall-node
- Explain when to use clean builds
- Enhance iOS Native Build Process section
- Add prerequisite note about Command Line Tools
- Include troubleshooting commands for pod install issues
- Reference prerequisites section for details
- Add comprehensive troubleshooting sections
- Clean Build section at start of Troubleshooting
- Recommends clean-build as first step for many issues
- Lists when to use clean builds
- iOS Build Issues section
- Command Line Tools configuration errors
- SQLite/linker issues and pkgx conflicts
- CocoaPods installation problems
- All with clear solutions and commands
The documentation now accurately reflects:
- Xcode Command Line Tools as required iOS prerequisite
- clean-build.sh as available build tool
- Complete iOS troubleshooting workflow
Files modified:
- BUILDING.md
36 KiB
Building the DailyNotification Plugin
Author: Matthew Raymer
Last Updated: 2025-10-21 09:03:53 UTC
Version: 1.0.0
Overview
This document provides comprehensive instructions for building the DailyNotification Capacitor plugin using various methods, including Android Studio, command line, and integration testing.
Table of Contents
- Quick Start
- Prerequisites
- Build Methods
- Android Studio Setup
- Command Line Building
- Testing Strategies
- Development Workflow
- Troubleshooting
- Project Structure
Quick Start
For Plugin Development
# Build plugin source code
./scripts/build-native.sh --platform android
# Test in Capacitor app
cd /path/to/test-capacitor-app
npx cap sync android
npx cap run android
For Android Studio
# 1. Open Android Studio
# 2. File → Open → /path/to/daily-notification-plugin/android
# 3. Wait for Gradle sync
# 4. Build → Make Project (Ctrl+F9)
Prerequisites
Required Software
- Android Studio (latest stable version) - for Android development
- Java 11+ (for Kotlin compilation)
- Android SDK with API level 21+
- Xcode (latest stable version) - for iOS development (macOS only)
- Xcode Command Line Tools - required for iOS builds (includes
xcodebuild,sqlite3, etc.) - Node.js 16+ (for TypeScript compilation)
- npm or yarn (for dependency management)
Required Tools
- Gradle Wrapper (included in project)
- Kotlin (configured in build.gradle)
- TypeScript (for plugin interface)
- CocoaPods - for iOS dependency management
iOS-Specific Prerequisites
Xcode Command Line Tools are required for iOS builds. The build script will verify these are installed:
# Install Xcode Command Line Tools (if not already installed)
xcode-select --install
Verification:
# Check if Command Line Tools are configured
xcode-select -p
# Verify xcodebuild is available
xcodebuild -version
# Verify sqlite3 is available (part of Command Line Tools)
sqlite3 --version
Note: The build script automatically checks for Command Line Tools and will fail with clear error messages if they're missing.
System Requirements
- RAM: 4GB minimum, 8GB recommended
- Storage: 2GB free space
- OS: Windows 10+, macOS 10.14+, or Linux (iOS development requires macOS)
Build Methods
Method 1: Automated Build Script (Recommended)
The project includes an automated build script that handles both TypeScript and native compilation:
# Build all platforms
./scripts/build-native.sh
# Build specific platform
./scripts/build-native.sh --platform android
./scripts/build-native.sh --platform ios
# Build with verbose output
./scripts/build-native.sh --verbose
What it does:
- Compiles TypeScript to JavaScript
- Bundles plugin code with Rollup
- Builds native Android/iOS code
- Handles plugin development project detection
- Provides helpful warnings and guidance
Method 2: Manual Command Line
TypeScript Compilation
# Clean previous builds
npm run clean
# Build TypeScript and bundle
npm run build
# Watch mode for development
npm run build:watch
Android Native Build
# Navigate to Android directory
cd android
# Build plugin library (recommended for plugin development)
./gradlew :plugin:assembleRelease
# Build test app (requires proper Capacitor integration)
./gradlew :app:assembleRelease
# Build all modules
./gradlew build
# Run tests
./gradlew test
iOS Native Build
# Navigate to iOS directory
cd ios
# Install CocoaPods dependencies
pod install
# Build using Xcode (command line)
xcodebuild -workspace DailyNotificationPlugin.xcworkspace -scheme DailyNotificationPlugin -configuration Release
Method 3: Android Studio
See Android Studio Setup for detailed instructions.
Android Studio Setup
Opening the Project
Important: Open the Correct Directory
# ✅ CORRECT: Open the android/ folder
File → Open → /path/to/daily-notification-plugin/android
# ❌ WRONG: Don't open the root project folder
# This will cause Gradle sync issues
Initial Configuration
1. Gradle Sync
- Android Studio will prompt to sync Gradle
- Click "Sync Now" or use the sync button in the toolbar
- Wait for sync to complete (may take a few minutes)
2. SDK Configuration
File → Project Structure → SDK Location
- Android SDK: /path/to/Android/Sdk
- JDK Location: /path/to/jdk-11
3. Gradle Settings
File → Settings → Build → Gradle
- Use Gradle from: 'gradle-wrapper.properties' file
- Gradle JVM: Project SDK (Java 11)
4. Kotlin Configuration
File → Settings → Languages & Frameworks → Kotlin
- Target JVM version: 1.8
- Language version: 1.5
Building in Android Studio
Build Commands
# Build the project
Build → Make Project (Ctrl+F9)
# Clean and rebuild
Build → Clean Project
Build → Rebuild Project
# Generate signed APK/AAR
Build → Generate Signed Bundle / APK
Build Output
The built plugin AAR will be located at:
android/build/outputs/aar/android-release.aar
Project Structure in Android Studio
When opened correctly, you'll see:
android/
├── app/ # Main Android test app
│ ├── build.gradle # App build configuration
│ ├── src/main/java/ # MainActivity.java
│ ├── src/main/assets/ # Capacitor assets (HTML/JS)
│ └── build/outputs/apk/ # Built APK files
├── plugin/ # Plugin library module
│ ├── build.gradle # Plugin build configuration
│ ├── src/main/java/
│ │ └── com/timesafari/dailynotification/
│ │ ├── DailyNotificationPlugin.java
│ │ ├── DailyNotificationWorker.java
│ │ ├── DailyNotificationScheduler.java
│ │ └── ...
│ └── build/outputs/aar/
│ └── plugin-release.aar # Built plugin AAR
├── build.gradle # Root build file
├── settings.gradle # Project settings
├── gradle.properties # Gradle properties
└── gradle/wrapper/ # Gradle wrapper files
Note: There's also a separate Vue 3 test app at test-apps/daily-notification-test/android/ with its own Android module.
Important Distinctions
Standard Capacitor Plugin Structure
The plugin now follows the standard Capacitor Android structure:
- Plugin Code:
android/src/main/java/... - Plugin Build:
android/build.gradle - Test App:
test-apps/android-test-app/app/(separate from plugin)
This structure is compatible with Capacitor's auto-generated files and requires no path fixes.
❌ Test plugin without host app (needs Capacitor runtime)
Command Line Building
TypeScript Build Process
1. Clean Previous Builds
npm run clean
# Removes: dist/, build/, out/
2. Compile TypeScript
npm run build
# Compiles: src/ → dist/
# Bundles: dist/plugin.js, dist/esm/index.js
3. Watch Mode (Development)
npm run build:watch
# Automatically rebuilds on file changes
Android Native Build Process
1. Navigate to Android Directory
cd android
2. Build Commands
# Build all variants
./gradlew build
# Build debug variant
./gradlew assembleDebug
# Build release variant
./gradlew assembleRelease
# Clean build
./gradlew clean build
# Run tests
./gradlew test
3. Build Outputs
# Plugin AAR files
android/build/outputs/aar/
├── android-debug.aar
└── android-release.aar
# Test results
android/build/reports/tests/test/index.html
iOS Native Build Process
Prerequisites: Ensure Xcode Command Line Tools are installed (see Prerequisites section). The build script will verify this automatically.
1. Navigate to iOS Directory
cd ios
2. Install Dependencies
pod install
Note: If you encounter issues with pod install, ensure Xcode Command Line Tools are properly configured:
xcode-select --install # Install if missing
xcode-select -p # Verify installation path
3. Build Commands
# Build using Xcode command line
xcodebuild -workspace DailyNotificationPlugin.xcworkspace \
-scheme DailyNotificationPlugin \
-configuration Release \
-destination generic/platform=iOS
# Build for simulator
xcodebuild -workspace DailyNotificationPlugin.xcworkspace \
-scheme DailyNotificationPlugin \
-configuration Debug \
-destination 'platform=iOS Simulator,name=iPhone 14'
Testing Strategies
Unit Testing
Android Unit Tests
# Run all tests
./gradlew test
# Run specific test class
./gradlew test --tests "DailyNotificationPluginTest"
# Run tests with coverage
./gradlew test jacocoTestReport
iOS Unit Tests
# Run tests using Xcode
xcodebuild test -workspace DailyNotificationPlugin.xcworkspace \
-scheme DailyNotificationPlugin \
-destination 'platform=iOS Simulator,name=iPhone 14'
Test Apps Within Project
Vue 3 Test Application
The project includes a comprehensive Vue 3 test app for interactive plugin testing:
# Navigate to Vue 3 test app
cd test-apps/daily-notification-test
# Install dependencies
npm install
# Build Vue 3 app
npm run build
# Add Capacitor platforms
npm install @capacitor/android @capacitor/ios
# Sync with Capacitor
npx cap sync android
# For iOS: Use the npm script (handles Podfile fixes automatically)
npm run cap:sync:ios
# This runs: cap copy ios + fix Podfile + pod install
# Run on Android device/emulator
npx cap run android
# Run on iOS device/simulator
npx cap run ios
iOS Setup (Vue 3 Test App)
The iOS setup requires additional steps to configure the plugin correctly:
1. Install Dependencies
cd test-apps/daily-notification-test
npm install
2. Build Vue App
npm run build
3. Add iOS Platform (if not already added)
npx cap add ios
4. Fix Podfile Configuration
Critical: Capacitor's npx cap sync ios regenerates the Podfile with incorrect plugin references (TimesafariDailyNotificationPlugin instead of DailyNotificationPlugin).
Solution: Use the npm script npm run cap:sync:ios which:
- Copies assets without running pod install (
npx cap copy ios) - Automatically fixes the Podfile
- Then runs
pod installwith the corrected Podfile
# Use the npm script (recommended)
npm run cap:sync:ios
# Or manually fix after copy
npx cap copy ios
node scripts/fix-capacitor-plugins.js
cd ios/App && pod install && cd ../..
The fix script will:
- Change
TimesafariDailyNotificationPlugin→DailyNotificationPlugin - Fix the path from
'../../../..'→'../../node_modules/@timesafari/daily-notification-plugin/ios'
5. Install CocoaPods Dependencies
After the Podfile is fixed, install the iOS dependencies:
cd ios/App
pod install
cd ../..
Expected Podfile Configuration:
The Podfile should reference the plugin like this:
def capacitor_pods
pod 'Capacitor', :path => '../../node_modules/@capacitor/ios'
pod 'CapacitorCordova', :path => '../../node_modules/@capacitor/ios'
pod 'DailyNotificationPlugin', :path => '../../node_modules/@timesafari/daily-notification-plugin/ios'
end
Important Notes:
- The pod name must be
DailyNotificationPlugin(notTimesafariDailyNotificationPlugin) - The path must point to
../../node_modules/@timesafari/daily-notification-plugin/ios - The plugin must be installed in
node_modulesvianpm install(it's installed as a local file dependency)
6. Sync and Build
Important: npx cap sync ios tries to run pod install automatically, but it will fail because the Podfile has incorrect plugin references. Use the npm script instead:
# Option 1: Use the npm script (recommended - handles everything)
npm run cap:sync:ios
# This script:
# 1. Copies web assets (npx cap copy ios)
# 2. Fixes the Podfile (node scripts/fix-capacitor-plugins.js)
# 3. Installs pods (cd ios/App && pod install)
# Option 2: Manual steps (if you need more control)
npx cap copy ios # Copy assets without pod install
node scripts/fix-capacitor-plugins.js # Fix Podfile
cd ios/App && pod install && cd ../.. # Install pods
# Open in Xcode
npx cap open ios
Why this approach?
npx cap sync iosregenerates the Podfile with wrong references, then tries to runpod installwhich failsnpx cap copy iosonly copies files, allowing us to fix the Podfile beforepod install- The npm script automates the entire workflow correctly
Troubleshooting iOS Setup:
Error: [!] No podspec found for 'TimesafariDailyNotificationPlugin'
This means the Podfile has the wrong pod name or path. Solutions:
-
Run the fix script:
node scripts/fix-capacitor-plugins.js -
Manually fix the Podfile:
- Open
ios/App/Podfile - Change
TimesafariDailyNotificationPlugintoDailyNotificationPlugin - Change path from
'../../../..'to'../../node_modules/@timesafari/daily-notification-plugin/ios'
- Open
-
Verify plugin is installed:
ls -la node_modules/@timesafari/daily-notification-plugin/ios/DailyNotificationPlugin.podspec -
Reinstall dependencies if needed:
rm -rf node_modules package-lock.json npm install
Error: pod install fails
-
Update CocoaPods:
sudo gem install cocoapods -
Clean CocoaPods cache:
cd ios/App rm -rf Pods Podfile.lock pod install --repo-update -
Verify Xcode Command Line Tools:
xcode-select --install
Test App Features:
- Interactive plugin testing interface
- Plugin diagnostics and status checking
- Notification scheduling and management
- Permission testing and management
- Comprehensive logging and debugging
Test App Structure:
test-apps/daily-notification-test/
├── src/ # Vue 3 source code
│ ├── views/ # Test interface views
│ ├── components/ # Reusable UI components
│ └── stores/ # Pinia state management
├── android/ # Android Capacitor app
├── ios/ # iOS Capacitor app
│ └── App/
│ ├── Podfile # CocoaPods dependencies
│ └── App.xcworkspace # Xcode workspace
├── docs/ # Test app documentation
└── scripts/ # Test app build scripts
│ └── fix-capacitor-plugins.js # Auto-fixes Podfile
Android Test Apps
The project includes two separate Android test applications:
1. Main Android Test App (test-apps/android-test-app/app)
A Capacitor-based Android test app with full plugin integration:
# Build main Android test app
cd test-apps/android-test-app
./gradlew :app:assembleDebug
# Install on device
adb install app/build/outputs/apk/debug/app-debug.apk
# Run tests
./gradlew :app:test
# Run in Android Studio
# File → Open → /path/to/daily-notification-plugin/test-apps/android-test-app
# Select 'app' module and run
Test App Structure:
test-apps/android-test-app/
├── app/
│ ├── src/
│ │ ├── main/
│ │ │ ├── AndroidManifest.xml # App manifest with permissions
│ │ │ ├── assets/ # Capacitor web assets
│ │ │ │ ├── capacitor.config.json # Capacitor configuration
│ │ │ │ ├── capacitor.plugins.json # Plugin registry
│ │ │ │ └── public/ # Web app files
│ │ │ ├── java/
│ │ │ │ └── com/timesafari/dailynotification/
│ │ │ │ └── MainActivity.java # Capacitor BridgeActivity
│ │ │ └── res/ # Android resources
│ │ ├── androidTest/ # Instrumented tests
│ │ └── test/ # Unit tests
│ ├── build.gradle # App build configuration
│ ├── capacitor.build.gradle # Auto-generated Capacitor config
│ └── proguard-rules.pro # Code obfuscation rules
Key Files Explained:
MainActivity.java - Entry point extending Capacitor's BridgeActivity:
public class MainActivity extends BridgeActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
}
AndroidManifest.xml - App permissions and configuration:
- Notification permissions
- Background execution permissions
- Exact alarm permissions
- Capacitor plugin declarations
assets/public/index.html - Main test interface:
- Interactive plugin testing buttons
- Plugin diagnostics and status checking
- Notification scheduling interface
- Permission management UI
capacitor.plugins.json - Plugin registry:
{
"plugins": {
"DailyNotification": {
"class": "com.timesafari.dailynotification.DailyNotificationPlugin"
}
}
}
Build Process:
- Web Assets: Capacitor copies
assets/public/to APK - Java Compilation: Compiles
MainActivity.javaand dependencies - Resource Processing: Processes Android resources and assets
- APK Generation: Packages everything into installable APK
- Plugin Integration: Links with plugin from
node_modules/@timesafari/daily-notification-plugin/android
Editing Guidelines:
- HTML/JS: Edit
assets/public/index.htmlfor UI changes - Java: Edit
src/main/java/for native Android code - Resources: Edit
src/main/res/for icons, strings, layouts - Configuration: Edit
AndroidManifest.xmlfor permissions - Build: Modify
build.gradlefor dependencies and build settings
Features:
- Full Capacitor integration
- Plugin testing interface (HTML/JS)
- Native Android testing capabilities
- Complete app lifecycle testing
2. Vue 3 Test App Android Module (/test-apps/daily-notification-test/android)
Android module within the Vue 3 test application:
# Build Vue 3 test app Android module
cd test-apps/daily-notification-test/android
./gradlew assembleDebug
# Install on device
adb install app/build/outputs/apk/debug/app-debug.apk
# Run tests
./gradlew test
Features:
- Integrated with Vue 3 frontend
- Plugin diagnostics and management
- Interactive testing interface
- Comprehensive logging and debugging
Plugin Integration Approach: The Vue 3 test app uses a project reference approach for plugin integration:
-
Project Reference Configuration:
// capacitor.settings.gradle include ':timesafari-daily-notification-plugin' project(':timesafari-daily-notification-plugin').projectDir = new File('../../../android') // capacitor.build.gradle implementation project(':timesafari-daily-notification-plugin') -
Required Dependencies:
// app/build.gradle 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' -
Plugin Discovery:
// assets/capacitor.plugins.json [ { "id": "DailyNotification", "name": "DailyNotification", "class": "com.timesafari.dailynotification.DailyNotificationPlugin" } ]
Troubleshooting Integration Issues:
- Duplicate Classes: Use project reference instead of AAR to avoid conflicts
- Gradle Cache: Clear completely (
rm -rf ~/.gradle) when switching approaches - Path Issues: Ensure correct project path (
../../../android) - Dependencies: Include required WorkManager and Gson dependencies
Integration Testing
1. Create External Test Capacitor App
# Create new Capacitor app
npx @capacitor/create-app@latest TestApp
cd TestApp
# Install your plugin
npm install /path/to/daily-notification-plugin
# Add platforms
npx cap add android
npx cap add ios
# Sync with Capacitor
npx cap sync android
npx cap sync ios
2. Test in Android Studio
# Open test app in Android Studio
File → Open → TestApp/android
# Now you can:
# - Run the app
# - Test notifications
# - Debug full integration
# - Test background tasks
3. Test on Device
# Run on Android device
npx cap run android
# Run on iOS device
npx cap run ios
Manual Testing Checklist
Basic Functionality
- Plugin loads without errors
- DailyNotification.configure() works
- Background fetching works
- Notifications appear
- Settings are persisted
Integration Testing
- ActiveDid change handling
- Settings synchronization
- Request pattern matching
- Error handling
- Network failure recovery
Edge Cases
- Network failures
- ActiveDid changes during fetch
- App backgrounding/foregrounding
- Battery optimization settings
- Low storage conditions
Build Scripts and Automation
Available Build Scripts
The project includes several automated build scripts in the scripts/ directory:
Core Build Scripts
# Main build script (handles TypeScript + native)
./scripts/build-native.sh --platform android
./scripts/build-native.sh --platform ios
./scripts/build-native.sh --verbose
# Clean build (removes all build artifacts and caches)
./scripts/clean-build.sh
./scripts/clean-build.sh --all # Also cleans caches and reinstalls dependencies
./scripts/clean-build.sh --clean-gradle-cache # Clean Gradle cache
./scripts/clean-build.sh --clean-derived-data # Clean Xcode DerivedData
./scripts/clean-build.sh --reinstall-node # Reinstall node_modules
# TimeSafari-specific builds
node scripts/build-timesafari.js
# Comprehensive testing
./scripts/comprehensive-test-v2.sh
# Capacitor build fixes
./scripts/fix-capacitor-build.sh
Setup and Configuration Scripts
# Gradle setup automation
./scripts/setup-gradle.sh
# Native environment setup
node scripts/setup-native.js
# Environment checking
node scripts/check-environment.js
Testing and Validation Scripts
# Chaos testing for reliability
node scripts/chaos-test.js
# API changes detection
node scripts/check-api-changes.js
# Bundle size monitoring
node scripts/check-bundle-size.js
# Daily notification testing
./scripts/daily-notification-test.sh
node scripts/daily-notification-test.py
Release and Deployment Scripts
# Release notes generation
node scripts/update-release-notes.js
# Type checksum generation
node scripts/generate-types-checksum.js
Deployment to External Projects
1. Publishing to npm Registry
# Build the plugin
npm run build
# Run tests
npm test
# Update version
npm version patch # or minor, major
# Publish to npm
npm publish
# Verify publication
npm view @timesafari/daily-notification-plugin
2. Installing in External Capacitor Projects
# Install from npm
npm install @timesafari/daily-notification-plugin
# Install from local development
npm install /path/to/daily-notification-plugin
# Install from git repository
npm install git+https://github.com/timesafari/daily-notification-plugin.git
3. Integration in Host Applications
# Add to Capacitor project
npx cap add android
npx cap add ios
# Sync with Capacitor
npx cap sync android
npx cap sync ios
# Build and run
npx cap run android
npx cap run ios
4. Version Management
# Check current version
npm list @timesafari/daily-notification-plugin
# Update to latest version
npm update @timesafari/daily-notification-plugin
# Install specific version
npm install @timesafari/daily-notification-plugin@1.2.3
For Plugin Development
1. Edit Plugin Code
# Edit TypeScript interface
vim src/definitions.ts
# Edit Android native code
vim android/src/main/java/com/timesafari/dailynotification/DailyNotificationPlugin.kt
# Edit iOS native code
vim ios/Plugin/DailyNotificationPlugin.swift
2. Build and Test
# Build plugin
./scripts/build-native.sh --platform android
# Test in Capacitor app
cd /path/to/test-capacitor-app
npx cap sync android
npx cap run android
3. Iterate
# Make changes
# Build again
# Test again
# Repeat until working
For Production Testing
1. Test in TimeSafari PWA
# Install plugin in TimeSafari PWA
npm install @timesafari/daily-notification-plugin
# Sync with Capacitor
npx cap sync android
npx cap sync ios
# Test on real devices
npx cap run android
npx cap run ios
2. Monitor and Debug
# Check logs
adb logcat | grep DailyNotification
# Check plugin metrics
# Use observability dashboards
Troubleshooting
Clean Build (First Step for Many Issues)
If you encounter persistent build issues, try a clean build first:
# Clean all build artifacts (recommended first step)
./scripts/clean-build.sh
# Clean everything including caches (for stubborn issues)
./scripts/clean-build.sh --all
# Then rebuild
./scripts/build-native.sh --platform all
When to use clean-build:
- Build errors that don't make sense
- Dependency conflicts
- Stale build artifacts
- After switching branches
- After updating dependencies
Common Issues
Gradle Sync Failures
# Problem: Gradle sync fails
# Solution: Check Java version
java -version # Should be 11+
# Solution: Clear Gradle cache
./gradlew clean
rm -rf ~/.gradle/caches ~/.gradle/daemon
Build Failures
# Problem: Build fails with "Could not read script"
# Solution: This is a plugin development project
# The build script handles this automatically
./scripts/build-native.sh --platform android
# Problem: Build fails with "Could not resolve project :capacitor-cordova-android-plugins"
# Solution: Build the plugin module instead of the test app
./gradlew :plugin:assembleRelease
# Problem: Build fails with "Cannot locate tasks that match ':android:assembleRelease'"
# Solution: Use correct project name - available projects are:
# - :app (test app, may have Capacitor issues)
# - :plugin (plugin library, recommended)
# - :capacitor-android
# - :capacitor-cordova-android-plugins
./gradlew :plugin:assembleRelease
# Problem: Build fails with "Plugin with id 'kotlin-android' not found"
# Solution: The plugin module doesn't need Kotlin plugin for Java/Kotlin code
# Check the plugin/build.gradle file
Capacitor Integration Warnings
# ⚠️ WARNING: capacitor.build.gradle is auto-generated!
# Any manual fixes will be lost when running:
# - npx cap sync
# - npx cap update
# - npx cap add android
# ⚠️ NOTE: npx cap sync will fail in plugin development projects!
# This is expected - plugin projects don't have www/ directory
# Error: "Could not find the web assets directory: ./www"
# This is normal for plugin development projects
# To fix after Capacitor operations:
./scripts/fix-capacitor-build.sh
# Or use the build script (applies fix automatically):
./scripts/build-native.sh --platform android
Capacitor Settings Path Fix (Test App)
Note: The plugin now uses standard Capacitor structure, so no path fixes are needed for consuming apps. The test app at test-apps/android-test-app/ references the plugin correctly.
Android Studio Issues
# Problem: Android Studio can't find SDK
# Solution: Configure SDK location
File → Project Structure → SDK Location
# Problem: Kotlin compilation errors
# Solution: Check Kotlin version in build.gradle
iOS Build Issues
# Problem: "Xcode Command Line Tools not configured"
# Error: xcode-select -p fails or xcodebuild not found
# Solution: Install Command Line Tools
xcode-select --install
# Verify installation
xcode-select -p
xcodebuild -version
sqlite3 --version
# Problem: "sqlite3 not found" or linker errors with SQLite
# Solution: Ensure Command Line Tools are properly installed
# The build script checks for this automatically, but if you see linker errors:
xcode-select --install
# Problem: pkgx SQLite conflicts with iOS builds
# Error: Linker errors about libsqlite3.dylib
# Solution: The build script automatically handles this by unsetting problematic
# environment variables. If issues persist:
unset PKGX_DIR DYLD_LIBRARY_PATH LD_LIBRARY_PATH
./scripts/build-native.sh --platform ios
# Problem: "pod install" fails
# Solution: Ensure Command Line Tools are installed
xcode-select --install
# Then reinstall CocoaPods dependencies
cd ios
pod deintegrate
pod install
Capacitor Integration Issues
# Problem: Plugin not found in Capacitor app
# Solution: Check plugin installation
npm list @timesafari/daily-notification-plugin
# Solution: Re-sync Capacitor
npx cap sync android
AAR Duplicate Class Issues
# Problem: Duplicate class errors when integrating plugin AAR
# Error: "Duplicate class com.timesafari.dailynotification.BootReceiver found in modules"
# Root Cause: Plugin being included both as project reference and as AAR file
# Solution 1: Use Project Reference Approach (Recommended)
# 1. Clear Gradle cache completely
./gradlew --stop
rm -rf ~/.gradle
rm -rf app/build
rm -rf build
# 2. Configure project reference in capacitor.settings.gradle
include ':timesafari-daily-notification-plugin'
project(':timesafari-daily-notification-plugin').projectDir = new File('../../../android/plugin')
# 3. Add dependency in capacitor.build.gradle
implementation project(':timesafari-daily-notification-plugin')
# 4. Remove AAR dependency from app/build.gradle
# Comment out: implementation(name: 'plugin-debug', ext: 'aar')
# Solution 2: AAR-Only Approach (Alternative)
# 1. Remove project references from capacitor.settings.gradle and capacitor.build.gradle
# 2. Ensure only AAR dependency in app/build.gradle
# 3. Remove any duplicate classes.jar files from libs/ directory
# 4. Clear Gradle cache and rebuild
# Verification: Check that plugin is included only once
./gradlew :app:dependencies | grep timesafari
Debug Commands
Android Debugging
# View Android logs
adb logcat | grep DailyNotification
# Check plugin installation
adb shell pm list packages | grep timesafari
# Test background tasks
adb shell am start -n com.capacitorjs.app/.MainActivity
iOS Debugging
# View iOS logs
xcrun simctl spawn booted log stream --predicate 'subsystem contains "DailyNotification"'
# Check plugin installation
# Use Xcode Organizer or Device Manager
Performance Issues
Build Performance
# Enable Gradle daemon
echo "org.gradle.daemon=true" >> ~/.gradle/gradle.properties
# Increase memory
echo "org.gradle.jvmargs=-Xmx4g" >> ~/.gradle/gradle.properties
# Enable parallel builds
echo "org.gradle.parallel=true" >> ~/.gradle/gradle.properties
Android Studio Performance
# Increase Android Studio memory
# Help → Edit Custom VM Options
-Xmx4g
-XX:ReservedCodeCacheSize=1g
Project Structure
Root Directory
daily-notification-plugin/
├── android/ # Android native code
├── ios/ # iOS native code
├── src/ # TypeScript plugin interface
├── dist/ # Built plugin files
├── scripts/ # Build scripts and automation
├── test-apps/ # Test applications
│ └── daily-notification-test/ # Vue 3 test app
├── docs/ # Documentation
├── examples/ # Usage examples
├── tests/ # Test files
├── package.json # Node.js dependencies
├── tsconfig.json # TypeScript configuration
├── rollup.config.js # Bundler configuration
└── BUILDING.md # This file
Android Structure
android/
├── src/main/java/ # Plugin source code
├── build.gradle # Plugin build configuration
└── variables.gradle # Gradle variables
iOS Structure
ios/
├── Plugin/ # Swift plugin code
├── DailyNotificationPlugin.xcodeproj/ # Xcode project
├── DailyNotificationPlugin.xcworkspace/ # Xcode workspace
├── Podfile # CocoaPods dependencies
└── Tests/ # iOS unit tests
Test Apps Structure
test-apps/
└── daily-notification-test/ # Vue 3 test application
├── src/ # Vue 3 source code
│ ├── views/ # Test interface views
│ ├── components/ # Reusable UI components
│ ├── stores/ # Pinia state management
│ └── router/ # Vue Router configuration
├── android/ # Android Capacitor app
│ ├── app/ # Android app module
│ ├── dailynotification/ # Plugin module
│ └── build.gradle # Android build config
├── docs/ # Test app documentation
├── scripts/ # Test app build scripts
├── package.json # Vue 3 dependencies
└── vite.config.ts # Vite build configuration
Scripts Structure
scripts/
├── build-native.sh # Main build script
├── build-timesafari.js # TimeSafari-specific builds
├── comprehensive-test-v2.sh # Full test suite
├── fix-capacitor-build.sh # Capacitor build fixes
├── setup-gradle.sh # Gradle setup automation
├── setup-native.js # Native environment setup
├── check-environment.js # Environment validation
├── chaos-test.js # Reliability testing
├── check-api-changes.js # API change detection
├── check-bundle-size.js # Bundle size monitoring
├── daily-notification-test.sh # Notification testing
├── daily-notification-test.py # Python test runner
├── update-release-notes.js # Release notes generation
└── generate-types-checksum.js # Type checksum generation
Best Practices
Code Organization
- Keep plugin code modular and testable
- Use consistent naming conventions
- Document all public APIs
- Follow platform-specific coding standards
Build Optimization
- Use incremental builds when possible
- Cache build artifacts
- Parallelize builds where supported
- Monitor build times and optimize
Testing Strategy
- Write unit tests for all plugin logic
- Test on real devices, not just simulators
- Test edge cases and error conditions
- Monitor performance and memory usage
Documentation
- Keep BUILDING.md updated
- Document all build requirements
- Provide troubleshooting guides
- Include examples and best practices
Support
Getting Help
- Check the troubleshooting section
- Review GitHub issues
- Consult Capacitor documentation
- Ask in Capacitor community
Contributing
- Follow the contributing guidelines
- Test all changes thoroughly
- Update documentation as needed
- Submit pull requests with clear descriptions
Remember: This is a Capacitor plugin development project. For full functionality testing, use it in a Capacitor host application, not as a standalone Android/iOS app.