Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
129 changes: 129 additions & 0 deletions CLAUDE.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,129 @@
# CLAUDE.md - Iterable Android SDK

## Project Overview

The Iterable Android SDK integrates Android apps with [Iterable](https://www.iterable.com), a growth marketing platform. The SDK provides push notifications (FCM), in-app messaging, embedded messaging, mobile inbox, event tracking, deep linking, and user management.

**Min SDK:** 21 (Android 5.0+) | **Language:** Java (75%) + Kotlin (25%)

## Quick Reference

### Build & Test

```bash
# Build (incremental, fast)
./build.sh

# Build (clean)
./build.sh --clean

# Run all unit tests
./test.sh

# Run a specific test class
./test.sh IterableApiTest

# Run a specific test method
./test.sh "IterableApiTest.testSetEmail"

# List all available test classes
./test.sh --list
```

The wrapper scripts (`build.sh`, `test.sh`) provide formatted output and error summaries. You can also use Gradle directly:

```bash
./gradlew build -x test # build
./gradlew :iterableapi:testDebugUnitTest --tests "*IterableApiTest*" # test
```

### Requirements

- JDK 17+
- Android SDK with compileSdk 34
- Gradle 8.0+ (use the wrapper: `./gradlew`)

## Project Structure

```
iterableapi/ # Core SDK module (main deliverable)
iterableapi-ui/ # UI components module (inbox, embedded views)
app/ # Internal test application for SDK integration testing
sample-apps/ # Example apps demonstrating SDK usage (inbox-customization)
integration-tests/ # End-to-end integration tests (requires emulator)
tools/ # CI/CD utilities (emulator wait script)
```

## Module Details

### iterableapi (core SDK)
- **Source:** `iterableapi/src/main/java/com/iterable/iterableapi/`
- **Tests:** `iterableapi/src/test/java/com/iterable/iterableapi/`
- ~94 source files, ~48 test files
- Mostly Java with Kotlin for newer features (embedded messaging, encryption, keychain)

### iterableapi-ui (UI components)
- **Source:** `iterableapi-ui/src/main/java/com/iterable/iterableapi/ui/`
- Inbox UI (Java) and Embedded views (Kotlin)
- No unit tests in this module

## Key Classes

| Class | Purpose |
|-------|---------|
| `IterableApi.java` | Main SDK interface (singleton entry point) |
| `IterableConfig.java` | SDK configuration builder |
| `IterableApiClient.java` | Network communication / API calls |
| `IterableAuthManager.java` | JWT authentication management |
| `IterableKeychain.kt` | Secure token/credential storage |
| `IterableInAppManager.java` | In-app message lifecycle management |
| `IterableEmbeddedManager.kt` | Embedded message management |
| `IterableConstants.java` | API endpoint paths and constants |
| `IterableRequestTask.java` | Network request execution |
| `IterableFirebaseMessagingService.java` | FCM push notification handling |
| `IterableDeeplinkManager.java` | Deep link resolution |
| `IterableNotificationHelper.java` | Push notification display |

## Common Development Tasks

### Adding a new API endpoint
1. Add endpoint path constant to `IterableConstants.java`
2. Add request method to `IterableApiClient.java`
3. Add public-facing method to `IterableApi.java`
4. Add tests in `iterableapi/src/test/java/`

### Modifying authentication
- Auth flow: `IterableAuthManager.java`
- Token storage: `IterableKeychain.kt`
- Auth failure handling: `AuthFailure.java`, `AuthFailureReason.java`

### Adding a new model class
- Create in `iterableapi/src/main/java/com/iterable/iterableapi/`
- Implement `Parcelable` if passed between components
- Add JSON serialization for network transport

## Code Style

- Checkstyle enforced (see `checkstyle.xml`)
- No star imports
- Max method length: 200 lines
- Standard Java naming conventions (camelCase methods/vars, PascalCase types)
- New features tend to use Kotlin; existing Java code stays Java unless refactored

## CI/CD

GitHub Actions workflows in `.github/workflows/`:
- `build.yml` - Main build and test
- `integration-tests.yml` - Full integration test suite
- `inapp-e2e-tests.yml` - E2E tests for in-app messaging
- `codeql.yml` - Code quality analysis
- `prepare-release.yml` / `validate-release.yml` / `publish.yml` - Release pipeline

## Testing Notes

- Unit tests use Robolectric for Android framework simulation
- Network tests use OkHttp MockWebServer
- Mocking via Mockito (core + inline)
- JSON assertions via JSONAssert
- Test base class: `BaseTest.java`
- Test utilities: `IterableTestUtils.java`, `InAppTestUtils.java`, `EmbeddedTestUtils.java`
81 changes: 81 additions & 0 deletions build.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
#!/bin/bash

# This script is to be used by LLMs and AI agents to build the Iterable Android SDK.
# It uses Gradle to build the project and shows errors in a clean format.
# It also checks if the build is successful and exits with the correct status.
#
# Usage: ./build.sh [--clean]
# --clean: Force a clean build (slower, but ensures clean state)

# Note: Not using set -e because we need to handle build failures gracefully

echo "Building Iterable Android SDK..."

# Create a temporary file for the build output
TEMP_OUTPUT=$(mktemp)

# Function to clean up temp file on exit
cleanup() {
rm -f "$TEMP_OUTPUT"
}
trap cleanup EXIT

# Check if we have Android SDK
if [ -z "$ANDROID_HOME" ] && [ -z "$ANDROID_SDK_ROOT" ]; then
echo "⚠️ Warning: ANDROID_HOME or ANDROID_SDK_ROOT not set. Build may fail if Android SDK is not in PATH."
fi

# Parse command line arguments for clean build option
CLEAN_BUILD=false
if [[ "$1" == "--clean" ]]; then
CLEAN_BUILD=true
echo "🧹 Clean build requested"
fi

# Run the build and capture all output
if [ "$CLEAN_BUILD" = true ]; then
echo "🔨 Clean building all modules..."
./gradlew clean build -x test --no-daemon --console=plain > "$TEMP_OUTPUT" 2>&1
BUILD_STATUS=$?
else
echo "🔨 Building all modules (incremental)..."
./gradlew build -x test --no-daemon --console=plain > "$TEMP_OUTPUT" 2>&1
BUILD_STATUS=$?
fi

# Show appropriate output based on build result
if [ $BUILD_STATUS -eq 0 ]; then
echo "✅ Iterable Android SDK build succeeded!"
echo ""
echo "📦 Built modules:"
echo " • iterableapi (core SDK)"
echo " • iterableapi-ui (UI components)"
echo " • app (sample app)"
else
echo "❌ Iterable Android SDK build failed with status $BUILD_STATUS"
echo ""
echo "🔍 Build errors:"

# Extract and show compilation errors with file paths and line numbers
grep -E "\.java:[0-9]+: error:|\.kt:[0-9]+: error:|error:|Error:|FAILURE:|Failed|Exception:" "$TEMP_OUTPUT" | head -20

echo ""
echo "⚠️ Build warnings:"
grep -E "\.java:[0-9]+: warning:|\.kt:[0-9]+: warning:|warning:|Warning:" "$TEMP_OUTPUT" | head -10

# If no specific errors found, show the failure section
if ! grep -q -E "\.java:[0-9]+: error:|\.kt:[0-9]+: error:|error:" "$TEMP_OUTPUT"; then
echo ""
echo "📋 Build failure details:"
grep -A 10 -B 2 "FAILURE\|BUILD FAILED" "$TEMP_OUTPUT" | head -15
fi

echo ""
echo "💡 Common solutions:"
echo " • Check Java version (JDK 17+ required)"
echo " • Verify ANDROID_HOME is set correctly"
echo " • Run './gradlew --stop' to kill daemon processes"
echo " • Check dependencies in build.gradle files"
fi

exit $BUILD_STATUS
Loading
Loading