Skip to content

Repository files navigation

ScoreScan SDK

Kotlin KMP Android iOS License

A Kotlin Multiplatform SDK for capturing and uploading scorecard images to Firebase Storage. Share business logic across Android and iOS while using native UI frameworks.

Features

  • Camera Capture - Native camera integration with landscape orientation
  • Document Detection - Real-time paper/document edge detection using Vision framework (iOS)
  • Auto-Crop - Automatically crops captured images to detected document boundaries
  • Gallery Picker - Select images from device photo library
  • Image Processing - Automatic resizing and JPEG compression
  • Firebase Upload - Direct upload to Firebase Storage with progress tracking
  • Compose UI Components - Ready-to-use camera UI components for Android
  • SwiftUI Support - Native iOS implementation with SwiftUI
  • Permission Handling - Cross-platform permission management

Architecture

┌─────────────────────────────────────────────────────────────┐
│                        Shared Module                         │
│  ┌─────────────┐  ┌─────────────┐  ┌─────────────────────┐  │
│  │   Storage   │  │ Permissions │  │    UI Components    │  │
│  │  Repository │  │   Handler   │  │  (Compose Common)   │  │
│  └─────────────┘  └─────────────┘  └─────────────────────┘  │
│  ┌─────────────────────────────────────────────────────────┐│
│  │              Koin Dependency Injection                  ││
│  └─────────────────────────────────────────────────────────┘│
└─────────────────────────────────────────────────────────────┘
         │                                    │
         ▼                                    ▼
┌─────────────────┐                ┌─────────────────┐
│     Android     │                │       iOS       │
│  ┌───────────┐  │                │  ┌───────────┐  │
│  │  CameraX  │  │                │  │AVFoundation│  │
│  │  Compose  │  │                │  │  SwiftUI  │  │
│  └───────────┘  │                │  │  Vision   │  │
└─────────────────┘                └─────────────────┘

Installation

Android

GitHub Packages

// settings.gradle.kts
dependencyResolutionManagement {
    repositories {
        maven {
            url = uri("https://maven.pkg.github.com/golfgenius/ScoreScanSDK")
            credentials {
                username = project.findProperty("gpr.user") as String? ?: System.getenv("GITHUB_ACTOR")
                password = project.findProperty("gpr.key") as String? ?: System.getenv("GITHUB_TOKEN")
            }
        }
    }
}

// build.gradle.kts
dependencies {
    implementation("com.swingu.scorecardcam:scorescan-sdk-android:1.0.0")
}

Requires a GitHub Personal Access Token (PAT) with read:packages scope. Add gpr.user and gpr.key to your gradle.properties or set the environment variables.

Local Build

./gradlew :shared:publishAndroidSDK

iOS

Swift Package Manager

In Xcode: File > Add Package Dependencies > Enter:

https://github.com/golfgenius/ScoreScanSDK

Requires access to the private repository. Add your GitHub account in Xcode > Settings > Accounts, or configure SSH keys.

XCFramework (Manual)

./gradlew :shared:buildXCFramework

The built framework will be at shared/build/XCFrameworks/release/ScoreScanSDK.xcframework.

Quick Start

Android

// Application.kt
class MyApp : Application() {
    override fun onCreate() {
        super.onCreate()
        setAndroidContext(this)
        initKoin { androidContext(this@MyApp) }
    }
}

// Upload an image
val uploadService = getKoinHelper().getImageUploadService()

lifecycleScope.launch {
    when (val result = uploadService.uploadImageWithAutoName(
        source = imagePath,
        folder = "scorecards"
    )) {
        is UploadResult.Success -> Log.d("Upload", "URL: ${result.downloadUrl}")
        is UploadResult.Error -> Log.e("Upload", result.message)
    }
}

iOS

// App.swift
@main
struct MyApp: App {
    init() {
        FirebaseApp.configure()
        ModulesKt.doInitKoin()
    }
}

// Use the camera view
ScorecardCameraView(
    config: ScorecardConfig(
        folder: "scorecards",
        maxWidth: 4032,
        maxHeight: 3024,
        quality: 95
    ),
    onResult: { result in
        switch result {
        case .success(let url):
            print("Uploaded: \(url)")
        case .cancelled:
            break
        case .error(let message):
            print("Error: \(message)")
        }
    }
)

Requirements

Platform Minimum Version
Android API 24 (Android 7.0)
iOS 16.0
Kotlin 2.3.0

Dependencies

  • Firebase Storage (via GitLive firebase-kotlin-sdk)
  • Koin 4.0 for dependency injection
  • Compose Multiplatform for UI components
  • CameraX (Android) / AVFoundation + Vision (iOS)

Project Structure

ScoreScan/
├── shared/                    # Kotlin Multiplatform shared module
│   ├── commonMain/           # Shared code
│   │   ├── di/               # Koin modules
│   │   ├── permissions/      # Permission abstractions
│   │   ├── storage/          # Firebase Storage logic
│   │   └── ui/camera/        # Compose UI components
│   ├── androidMain/          # Android-specific implementations
│   └── iosMain/              # iOS-specific implementations
├── Sources/
│   └── ScorecardCamUI/       # Swift UI layer (SPM target)
│       ├── ScorecardCameraView.swift   # Main camera + review UI
│       ├── DocumentDetector.swift      # Vision rectangle detection & cropping
│       ├── DocumentOverlayView.swift   # Live detection overlay
│       └── CameraPreviewView.swift     # AVCaptureSession preview
├── composeApp/               # Android demo app
├── iosApp/                   # iOS demo app (SwiftUI)
├── Package.swift             # Swift Package Manager manifest
└── .github/workflows/        # CI/CD release automation

Building

# Build Android AAR
./gradlew :shared:assembleRelease

# Build iOS XCFramework
./gradlew :shared:buildXCFramework

# Publish to local Maven
./gradlew :shared:publishAndroidSDK

# Run Android app
./gradlew :composeApp:installDebug

# Run iOS app
open iosApp/iosApp.xcworkspace

Firebase Setup

  1. Create a project at Firebase Console
  2. Enable Firebase Storage
  3. Add platform config files:
    • Android: google-services.json in composeApp/
    • iOS: GoogleService-Info.plist in iosApp/iosApp/

SDK Distribution

SDK releases are automated via GitHub Actions. When a GitHub Release is published:

  1. Android - The AAR is published to GitHub Packages (Maven)
  2. iOS - The XCFramework is built, zipped, and committed to the repo for SPM resolution

Both distribution channels require repository access, keeping the SDK private.

Manual Build

# Android AAR + Maven
./gradlew :shared:publishAndroidSDK

# iOS XCFramework
./gradlew :shared:buildXCFramework

License

Copyright 2024 Swingu

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.

Contributing

Contributions are welcome! Please open an issue or submit a pull request.

About

Kotlin Multiplatform SDK for capturing and uploading scorecard images to Firebase Storage. Supports Android & iOS with shared business logic.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Used by

Contributors

Languages