An Android app for creating Samsung Frame-ready images and sending them to a Frame device on the same local network.
  • Kotlin 98.4%
  • JavaScript 1.6%
Find a file
Repository files (latest commit first)
Filename Latest commit message Latest commit date
Ben Marquez Keenan 034c6b7493
All checks were successful
release / release (push) Successful in 1m8s
docs: add project README
Covers what the app does, tech stack, build instructions, and the
semantic-release/Forgejo Actions release pipeline.
2026-07-22 15:55:12 +01:00
.forgejo/workflows feat(ci): sign release APKs using a keystore stored in secrets 2026-07-22 15:16:44 +01:00
app Add semantic-release pipeline for versioning, changelog, and Android builds 2026-07-22 09:41:43 +01:00
gradle/wrapper Initial Frameify app: share/pick, resolution check, fixed-ratio crop, save 2026-07-15 08:17:06 +01:00
scripts Add semantic-release pipeline for versioning, changelog, and Android builds 2026-07-22 09:41:43 +01:00
.gitignore Fix semantic-release Gitea plugin package name; add lockfile 2026-07-22 10:54:54 +01:00
.releaserc.json fix(ci): replace tag-push trigger with explicit workflow dispatch 2026-07-22 14:44:22 +01:00
build.gradle.kts Initial Frameify app: share/pick, resolution check, fixed-ratio crop, save 2026-07-15 08:17:06 +01:00
CHANGELOG.md chore(release): 1.1.0 [skip ci] 2026-07-22 14:21:16 +00:00
gradle.properties Initial Frameify app: share/pick, resolution check, fixed-ratio crop, save 2026-07-15 08:17:06 +01:00
gradlew Initial Frameify app: share/pick, resolution check, fixed-ratio crop, save 2026-07-15 08:17:06 +01:00
gradlew.bat Initial Frameify app: share/pick, resolution check, fixed-ratio crop, save 2026-07-15 08:17:06 +01:00
package-lock.json Fix semantic-release Gitea plugin package name; add lockfile 2026-07-22 10:54:54 +01:00
package.json Fix semantic-release Gitea plugin package name; add lockfile 2026-07-22 10:54:54 +01:00
README.md docs: add project README 2026-07-22 15:55:12 +01:00
settings.gradle.kts Initial Frameify app: share/pick, resolution check, fixed-ratio crop, save 2026-07-15 08:17:06 +01:00
version.properties chore(release): 1.1.0 [skip ci] 2026-07-22 14:21:16 +00:00

Frameify

Release Build Status

Frameify is a native Android app for preparing photos for a Samsung Frame TV. It crops images to the Frame's 4K (3840×2160) 16:9 art-mode aspect ratio and can push them straight to a Frame TV over the local network — no cloud upload, no SmartThings account.

Features

  • Share-to-crop — send an image to Frameify from your gallery or any app (ACTION_SEND / ACTION_VIEW for image/*), or open one directly from the launcher.
  • Fixed aspect-ratio cropping — crop UI is locked to the Frame's 16:9 art-mode canvas (FrameSpec), built on CanHub/Android-Image-Cropper.
  • Direct-to-TV upload — discovers Frame TVs on the local Wi-Fi network and uploads art over the Frame's WebSocket control API (FrameTvClient, FrameTvDiscovery).
  • Local save — cropped images are also written to a Frameify folder for manual transfer.

Tech stack

  • Kotlin + Jetpack Compose (Material 3)
  • Coil for image loading, OkHttp for the Frame TV WebSocket client
  • Gradle (Android Gradle Plugin 8.4.2, Kotlin 1.9.24), min SDK 29 / target SDK 34

Project layout

app/src/main/java/com/frameify/app/
├── MainActivity.kt          # entry point, share/view intent handling
├── data/
│   ├── FrameSpec.kt          # Frame TV art-mode dimensions/aspect ratio
│   ├── ImageUtils.kt         # crop + resize helpers
│   └── tv/                   # Frame TV discovery, WebSocket client, saved-TV prefs
└── ui/
    ├── Screens.kt             # crop/preview/save flow
    ├── FrameTvScreens.kt      # TV discovery + upload flow
    └── Theme.kt

Building

Requires JDK 17.

./gradlew assembleDebug     # debug APK
./gradlew assembleRelease   # release APK (unsigned unless keystore.properties is present)

Release builds are signed using credentials in keystore.properties (gitignored; see build.gradle.kts for the expected keys: storeFile, storePassword, keyAlias, keyPassword). Without that file, assembleRelease produces an unsigned APK.

There are currently no automated tests in this project.

Releases

Versioning and the changelog are automated with semantic-release, driven by Conventional Commits on main (see CHANGELOG.md). version.properties at the repo root is the single source of truth for versionCode/versionName and is bumped by the release pipeline rather than edited by hand.

The latest release has its APK attached as a downloadable asset.

CI runs on Forgejo Actions:

  • .forgejo/workflows/release.yml — runs semantic-release on every push to main, tagging releases and updating the changelog.
  • .forgejo/workflows/android-build.yml — manually dispatched; builds a signed release APK and attaches it to the corresponding Forgejo release.