- Kotlin 98.4%
- JavaScript 1.6%
| Filename | Latest commit message | Latest commit date |
|---|---|---|
|
All checks were successful
release / release (push) Successful in 1m8s
Covers what the app does, tech stack, build instructions, and the semantic-release/Forgejo Actions release pipeline. |
||
| .forgejo/workflows | ||
| app | ||
| gradle/wrapper | ||
| scripts | ||
| .gitignore | ||
| .releaserc.json | ||
| build.gradle.kts | ||
| CHANGELOG.md | ||
| gradle.properties | ||
| gradlew | ||
| gradlew.bat | ||
| package-lock.json | ||
| package.json | ||
| README.md | ||
| settings.gradle.kts | ||
| version.properties | ||
Frameify
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_VIEWforimage/*), 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
Frameifyfolder 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— runssemantic-releaseon every push tomain, 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.