Skip to content

Latest commit

 

History

7 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

GitHubRepoFinder

iOS (SwiftUI) and Android (Jetpack Compose) app that fetches GitHub repositories by username. Both platforms share the same Swift networking code — no duplicate API logic.

┌────────────────────────────────────────┐
│         GitHubRepoKit (Swift)          │
│     URLSession → GitHub API → JSON     │
└─────────────┬──────────────┬───────────┘
              │              │
     ┌────────▼───┐   ┌─────▼──────────────┐
     │  iOS App   │   │   Android App       │
     │  (SwiftUI) │   │   (Jetpack Compose) │
     │            │   │                     │
     │  Direct    │   │  Swift .so (ARM64)  │
     │  import    │   │  via JNI + swift-java│
     └────────────┘   └─────────────────────┘

Prerequisites

  • macOS with Xcode 16+ (Swift 6.1+)
  • JDK 17 (brew install --cask corretto@17)
  • Android Studio with SDK 35, NDK
  • Swift SDK for Android (swift sdk install ...)
  • swift-java CLI (built from source)
  • XcodeGen (brew install xcodegen)

See SETUP.md for complete installation steps from a fresh MacBook.


Run iOS App

cd ios-app
open GitHubRepoFinder.xcodeproj
# Press Cmd+R to build and run on simulator

Run Android App

Prerequisites

  1. Publish swift-java runtime to local Maven (required for swiftkit-core:1.0-SNAPSHOT dependency):
cd ~/Developer/swift-java-source
JAVA_HOME=$(/usr/libexec/java_home -v 17) ./gradlew :SwiftKitCore:publishToMavenLocal
  1. Set JDK path in android-app/gradle.properties:
echo "org.gradle.java.home=$(/usr/libexec/java_home -v 17)" >> android-app/gradle.properties

Cross-compile Swift and deploy .so files

# 1. Cross-compile Swift for Android ARM64
swift build \
  --package-path GitHubRepoKit \
  --product GitHubRepoKitJNI \
  --swift-sdk $(swift sdk list | grep android | tail -1) \
  --triple aarch64-unknown-linux-android35

# 2. Deploy .so files
JNILIBS=android-app/app/src/main/jniLibs/arm64-v8a
mkdir -p $JNILIBS

BUILD_DIR=$(find GitHubRepoKit/.build -name "libGitHubRepoKitJNI.so" -path "*aarch64*android*" | head -1 | xargs dirname)
cp "$BUILD_DIR/libGitHubRepoKitJNI.so" "$JNILIBS/"
cp "$BUILD_DIR/libSwiftJava.so" "$JNILIBS/"

SDK_BUNDLE=$(find ~/Library/org.swift.swiftpm/swift-sdks -name "*.artifactbundle" -path "*android*" | head -1)
SWIFT_LIBS="$SDK_BUNDLE/swift-android/swift-resources/usr/lib/swift-aarch64/android"
NDK_SYSROOT=$(find "$SDK_BUNDLE" -path "*/sysroot/usr/lib/aarch64-linux-android" -type d | head -1 | sed 's|/usr/lib/aarch64-linux-android||')

for lib in libswiftCore.so libdispatch.so libswiftDispatch.so libBlocksRuntime.so \
           libswift_Concurrency.so libswiftAndroid.so libFoundation.so \
           libFoundationEssentials.so libFoundationInternationalization.so \
           libFoundationNetworking.so lib_FoundationICU.so \
           libswift_StringProcessing.so libswift_RegexParser.so \
           libswift_Builtin_float.so libswift_math.so \
           libswiftSynchronization.so libswiftSwiftOnoneSupport.so; do
    cp "$SWIFT_LIBS/$lib" "$JNILIBS/" 2>/dev/null || true
done

cp "$NDK_SYSROOT/usr/lib/aarch64-linux-android/libc++_shared.so" "$JNILIBS/"

Build and run

cd android-app

# Build
./gradlew :app:assembleDebug

# Start emulator (use -dns-server to fix network issues)
$ANDROID_HOME/emulator/emulator -avd <your-avd-name> -dns-server 8.8.8.8,8.8.4.4 &

# Install and run
adb wait-for-device
adb install -r app/build/outputs/apk/debug/app-debug.apk
adb shell am start -n com.example.githubrepo/.MainActivity

Project Structure

Folder What it does
GitHubRepoKit/ Shared Swift package — networking code used by both platforms
ios-app/ SwiftUI app, imports GitHubRepoKit directly
android-app/ Jetpack Compose app, calls Swift via JNI
android-app/github-repo-kit-bridge/ JNI bridge module (swift-java generated bindings + Kotlin wrapper)

See PROJECT_STRUCTURE.md for a detailed file-by-file breakdown.


How It Works

  1. GitHubService.swift makes HTTP calls using URLSession (works on both iOS and Android via FoundationNetworking)
  2. On iOS: the app imports GitHubRepoKit as a Swift package — native, direct
  3. On Android: Swift code is cross-compiled to .so using Swift SDK for Android, and called via JNI bindings generated by swift-java jextract
  4. Both platforms execute the exact same Swift networking code — zero Kotlin/Java HTTP logic

Regenerating JNI Bindings

Only needed if you change the public API in GitHubRepoKit/Sources/GitHubRepoKitJNI/JNIExports.swift:

swift-java jextract \
  --input-swift GitHubRepoKit/Sources/GitHubRepoKitJNI \
  --swift-module GitHubRepoKitJNI \
  --java-package com.example.githubrepo.bridge \
  --output-swift GitHubRepoKit/Sources/GitHubRepoKitJNI/Generated \
  --output-java android-app/github-repo-kit-bridge/src/main/java \
  --mode jni

Then fix initializeLibs() in the generated GitHubRepoFetcher.java to use System.loadLibrary() (see SETUP.md step 11).

About

Github repo finder Mobile app

Resources

Stars

1 star

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages