# JanusSDK for Android

This directory contains the source code for the JanusSDK Android library, tests, and examples.

## Repository Structure

* **sdk/src/main/java/com/ethyca/janussdk/android** - Core SDK source code
* **sdk/src/test/java/com/ethyca/janussdk/android** - Unit tests
* **janus-sdk-android/Example** - Example implementation of the SDK

## Architecture Overview

The Android SDK follows a modular architecture with clear separation of concerns:

```
com.ethyca.janussdk.android/
├── Janus.kt             # Main entry point (public API)
├── JanusConfiguration.kt # Configuration class (public API)
├── JanusError.kt        # Error types (public API)
├── JanusEvent.kt        # Event system classes (public API)
├── core/                # Internal implementation details
│   ├── JanusInterface.kt  # Core interface definition
│   ├── JanusImplementation.kt # Actual implementation
│   └── JanusProvider.kt   # Dependency injection
├── api/                 # API communication and data models
├── consent/             # Consent management and storage
├── webview/             # WebView integration and JavaScript bridge
├── ui/                  # UI components
│   ├── view/            # Traditional Android Views
│   └── compose/         # Optional Jetpack Compose components
└── utils/               # Utility classes
```

### Key Implementation Components

- **JanusSDK.kt** - Static facade class (entry point)
- **JanusProvider.kt** - Factory for implementation instance
- **JanusProtocol.kt** - Interface defining SDK capabilities
- **JanusImplementation.kt** - Core implementation of the protocol
- **JanusConfiguration.kt** - SDK configuration
- **JanusError.kt** - Error types
- **JanusEvent.kt** - Event system

## Development Workflow

### Setting up JDK 17

The SDK and Example app require JDK 17. If you don't have it installed:

#### macOS
```bash
# Install with Homebrew
brew install openjdk@17

# Add Java environment variables to your shell profile (for persistence)
echo 'export JAVA_HOME=/opt/homebrew/opt/openjdk@17/libexec/openjdk.jdk/Contents/Home' >> ~/.zshrc
echo 'export PATH="/opt/homebrew/opt/openjdk@17/bin:$PATH"' >> ~/.zshrc

# Apply the changes
source ~/.zshrc
```

### Opening and Testing in Android Studio

1. Open the `Android` directory in Android Studio
2. Build the SDK using Gradle: Build > Make Project
3. Run tests: View > Tool Windows > Run > Run All Tests

### Running Tests from Command Line

```bash
# Run all unit tests (debug and release)
./gradlew runTests

# Run only debug unit tests
./gradlew :sdk:testDebugUnitTest

# Run only release unit tests
./gradlew :sdk:testReleaseUnitTest

# Run tests with code coverage
./gradlew runTestsWithCoverage
```

Test results are available in:
```
sdk/build/reports/tests/testDebugUnitTest/  # Debug unit tests
sdk/build/reports/tests/testReleaseUnitTest/  # Release unit tests
```

### Code Coverage

To generate code coverage reports:

```bash
# Run tests with coverage
./gradlew runTestsWithCoverage
```

This will:
1. Run all unit tests
2. Generate JaCoCo coverage reports

Coverage reports are available in:
```
sdk/build/reports/jacoco/jacocoTestReport/html/index.html  # HTML report
sdk/build/reports/jacoco/jacocoTestReport/xml/report.xml   # XML report (for CI integration)
```

To view the HTML report, open the index.html file in your browser:
```bash
open sdk/build/reports/jacoco/jacocoTestReport/html/index.html  # macOS
xdg-open sdk/build/reports/jacoco/jacocoTestReport/html/index.html  # Linux
```

### Building the SDK AAR / Running the Example to Manually Test/Debug the SDK

```bash
# Build release version
./gradlew buildSdk
```

Then run build and run the example app in Android Studio. The release version of the SDK should be used when testing to atest the actual production code

For debugging/stepping through the SDK, its helpful to build the SDK in debug mode:

```bash
# Build debug version
./gradlew buildDebugSdk
```

Both of these build steps will copy the result AAR file to the example directory.

## Using Logdy for Local Log Monitoring

The example app includes an optional HTTPLogger that can send logs to a local [logdy](https://logdy.dev) instance for real-time log viewing and debugging.

### Installing Logdy

Install logdy using brew

```bash
brew install logdy
```

### Running Logdy

Start logdy with these settings to work with the example app:

```bash
logdy --no-analytics -p 8181 --api-key foobar
```

### Viewing Logs

Once logdy is running, simply run the example app and Janus SDK logs will appear in the logdy web interface at http://localhost:8181.

**Note:** The example app automatically uses the correct endpoint for Android (`10.0.2.2` for emulators, which differs from `localhost`).

### Downloading Test Privacy Experience JSON Files

The SDK shares test JSON files with the iOS version, located in a common Shared directory at the project root. These files are used to ensure the models can properly decode actual API responses from different regions and properties.

To download test JSON files:

```bash
cd ../Shared/PrivacyExperienceMockJSON
./download.sh <host> <region> [property_id]
```

Parameters:
- `host` - The API host without https:// (e.g., privacy.ethyca.com)
- `region` - The region code (e.g., us_ca, de, gb)
- `property_id` - (Optional) A specific property ID

For example:
```bash
./download.sh privacy.ethyca.com de
./download.sh privacy.ethyca.com us_ca abc123
```

The script will:
1. Download the JSON response for the specified region/property
2. Format it using `jq` for readability
3. Save it with a timestamp in the filename
4. Validate the downloaded file is valid JSON

The Android test suite includes `PrivacyExperienceJSONTests` that verify these JSON files can be properly accessed from the shared location.

### Publishing the SDK - Creating a Release

Use the publish script in the root of the project, with a dry run, then drop the dry-run parameter.

**Important** - Without the --dry-run parameter, this script WILL make commits to multiple repos and push to origin on your behalf.

```bash
./publish.sh --android --dry-run
```

The publish script uses the following sub tasks to complete it's work, which can be run manually if you wish:

1. Update the version using one of these commands:

```bash
# Increment major version (e.g., 1.0.0 -> 2.0.0)
./gradlew incrementMajorVersion

# Increment minor version (e.g., 1.0.0 -> 1.1.0)
./gradlew incrementMinorVersion

# Increment patch version (e.g., 1.0.0 -> 1.0.1)
./gradlew incrementPatchVersion

# Set a specific version
./gradlew setVersion -Pversion=1.2.3
```

2. Build and publish the SDK:

```bash
# Build and publish to specified directory
./gradlew publishSdk -PpublishDir=/path/to/janus-sdk-android
```

This will:
- Build a fully obfuscated release AAR
- Copy it to the target repository
- Copy documentation and README files
- Display instructions for final steps (git commit/tag/push)

3. Follow the displayed instructions to complete the release. Both repositories will need code pushed (fidesplus for the version number bump, and janus-sdk-android with the tagged release)

### Publishing to Maven Repository (NOT IMPLEMENTED YET)

To publish the SDK to Maven Central:

1. **Access Credentials from 1Password**:

   The required signing keys and Maven Central credentials are stored in 1Password. Locate the "JanusSDK Android Publishing Credentials" entry to obtain the pre-configured `gradle.properties` file.

   Copy this file to your `~/.gradle/` directory:

2. **Alternative: Setting Up Your Own Signing Keys**:

   If you need to create new signing credentials, follow these steps:

   a. Install GPG if not already installed:
   ```bash
   # macOS
   brew install gnupg

   # Ubuntu/Debian
   sudo apt-get install gnupg

   # Windows
   # Download and install GPG4Win from https://gpg4win.org/
   ```

   b. Generate a new GPG key pair:
   ```bash
   gpg --full-generate-key
   ```
   Choose RSA and RSA, 4096 bits, and provide your information when prompted.

   c. List your keys to get the key ID:
   ```bash
   gpg --list-secret-keys --keyid-format=long
   ```
   Your key ID is the 16-character string after "rsa4096/" in the output.

   d. Export your secret key to a file:
   ```bash
   gpg --export-secret-keys YOUR_KEY_ID > ~/.gnupg/secring.gpg
   ```

   e. Create or update your `~/.gradle/gradle.properties` file:
   ```properties
   # GPG Signing
   signing.keyId=YOUR_KEY_ID
   signing.password=YOUR_GPG_PASSPHRASE
   # must be an absolute path
   signing.secretKeyRingFile=/Users/YOU/.gnupg/secring.gpg

   # Maven Central credentials
   mavenCentralUsername=your_sonatype_username
   mavenCentralPassword=your_sonatype_password
   ```

3. **Run the Publishing Tasks**:

   ```bash
   # Publish to Maven Central
   ./gradlew publishToSonatype closeAndReleaseSonatypeStagingRepository
   ```

4. **Verify Publication**:

   After successful publication, verify your artifacts on [Maven Central](https://search.maven.org/search?q=g:com.ethyca.janussdk). Note that it may take several hours for artifacts to propagate to the public repository.

**Important Notes**:
- Maven Central publishing requires GPG signing to verify authenticity
- Keep your signing key and passphrase secure
- The SDK will be available at `com.ethyca.janussdk:android:VERSION`
- All published artifacts are signed with the Ethyca organization's key

### Security Features

The published SDK includes several security features:

1. **Code Obfuscation**: All internal implementation details are obfuscated using R8/ProGuard
2. **Minification**: Unused code is removed to reduce size
3. **Name Mangling**: Class, method, and field names are replaced with meaningless identifiers
4. **Package Restructuring**: Classes are repackaged to hide the original structure

Only the public API required for integration is preserved in a readable form.

### Running the Example App

Once developed, the example app will demonstrate the integration and usage of the JanusSDK.

1. Open `janus-sdk-android/Example` in Android Studio
2. Select a device or emulator
3. Run the app

## Code Style and Guidelines

- Follow Kotlin style conventions
- Use dependency injection to improve testability
- Write unit tests for all public methods
- Document all public APIs with KDoc comments
- Follow SOLID principles
- Target Android API 21 (Android 5.0) and above

## Dependency Management

The project uses Gradle for dependency management. Key dependencies include:

- Kotlin coroutines for asynchronous operations
- Retrofit for networking
- Room for data persistence
- Gson for JSON parsing
- JUnit and Mockito for testing

## Testing Strategy

- **Unit Tests**: For individual components and utility functions
- **Integration Tests**: For components that work together
- **UI Tests**: For UI components
- **End-to-End Tests**: For complete flows through the SDK

## Continuous Integration

CI/CD will be set up to:
- Run tests on each PR
- Generate documentation
- Publish AAR artifacts when version is bumped

## Documentation

The SDK uses KDoc comments for API documentation. To generate documentation:

```bash
./gradlew dokkaHtml
```

This will create documentation in `app/build/dokka/html/`.