Open-source project
Anthonyy232/Paperize avatar
Anthonyy232/Paperize

Paperize builds only on Java 17 with compile SDK 37, and ships on F-Droid

Paperize is a modern fully offline dynamic wallpaper changer application built for Android using Kotlin, Jetpack Compose, and Material 3

1,252 stars69 forksKotlinGPL-3.0

At a glance

What is it?
Paperize is an Android wallpaper changer in Kotlin and Jetpack Compose with a documented repository and use-case architecture, a version-locked build toolchain, and three distribution channels including F-Droid. The architecture section is the most useful part of the README, and it constrains contributors as much as it describes the code.
Who is it for?
Paperize fits someone who wants their wallpaper to change on a schedule from local images without an account, an upload or a network dependency, and its F-Droid presence provides a listed download route. Do not adopt it if your device runs below Android 12, since the minimum SDK is 31, and do not fork it expecting a forgiving build, because the toolchain is pinned to Java 17, Android Gradle Plugin 9.3.2 and Gradle 9.7.1.
Can I use it commercially?
Yes, with conditions. GPL-3.0 is a copyleft licence: if you distribute software that includes it, you must release that software's source code under the same licence. Running it internally without distributing it does not trigger that obligation.
Is it still maintained?
Yes. The repository last received commits 1 day ago.
What is it written in?
Mainly Kotlin, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on October 23, 2026, and from our analysis. They are not legal advice.

Editorial analysis

Three ways to install, and one of them is F-Droid

The download section lists three channels, and the choice between them is a real decision rather than a formality.

GitHub releases are the primary channel, with a downloads badge counting assets across releases. F-Droid hosts the package as `com.anthonyla.paperize`, and IzzyOnDroid carries an APK of the same package identifier.

The F-Droid and IzzyOnDroid routes matter for more than convenience. F-Droid hosts the package as `com.anthonyla.paperize`, and IzzyOnDroid carries an APK with the same package identifier. Both are consistent with the project's stated feature of on-device storage, where all wallpapers and settings are kept locally, and with the offline framing in the project description.

An offline wallpaper app that indexes your photo library and has no network permission surface is the sort of thing people are willing to install from a repository rather than a store, and the distribution choices reflect that.

The support note asks for sponsorship through GitHub Sponsors, one-time or monthly, rather than presenting an in-app purchase or an advertisement. That is consistent with an app with no accounts and no analytics.

Licensing is GNU General Public License v3.0 with the LICENSE file at the repository root. For an end user that means nothing changes; for anyone who wants to fork it into a product, GPL-3.0 obligates you to publish the source of your derivative, which is worth knowing before you plan around the code.

The feature list is narrow on purpose

The features section is seven bullets, and the specificity of the image format list tells you how the implementation actually behaves.

Dynamic wallpaper changer is the core: set the wallpaper to change at specific time intervals. Folder support exists for organising wallpapers into folders for auto-updating, which means a queue can draw from a directory rather than a fixed list. Dual screen support lets you choose the same album or separate albums for the home screen and the lock screen. Static and live wallpapers are both supported, with smooth live transitions as the alternative to a hard cut.

Wallpaper effects are applied at change time, and the list given is brightness, blur, scaling and vignette, with the README noting more exist. That phrasing, effects including a short list, tells you the effect set is extensible rather than fixed.

The format support is the detail worth checking against your library: JPG, PNG, WEBP, AVIF, HEIC/HEIF, BMP, GIF, TIFF and SVG. Nine formats, several of which are still awkward on Android, which is where most of the engineering in an app like this goes. GIF in particular is animated, so whether it appears as a still or as motion depends on how the live wallpaper path handles it.

On-device storage is stated as a feature rather than a side effect. Nothing is uploaded, and there is no account to create, which makes the app usable on a device with no cloud connectivity.

The architecture section reads as a contributor's contract

Most README architecture sections describe structure. This one states rules, and it is the most informative thing in the file.

`AlbumRepository` owns library mutations, and imports, reordering, removal, covers and queue invalidation all use Room transactions, while provider scans run outside them. That separation is deliberate: a scan of a large document provider should not hold a database transaction open.

`DocumentSource` and `WallpaperRenderer` are domain interfaces with Android implementations under `data/source`, and the stated purpose is to keep use cases free of document-provider and bitmap-decoding details. This is the rule that keeps the code testable.

`WallpaperRepository` owns rotation queues and current-wallpaper records, with queue creation doing its check and write in one transaction, including synchronised screens. Both static changes and the live wallpaper engine dequeue through the same entry point, `ChangeWallpaperUseCase.dequeueNext`, which is how you avoid two code paths drifting apart.

`WallpaperController` shares static wallpaper application between the service and the worker, and callers hold a `WallpaperChangeLock` through application and scheduling, so no two callers apply a wallpaper concurrently. The controller recycles applied bitmaps.

`SettingsCoordinator` persists settings edits and applies their side effects one at a time, while ViewModels only hold UI state. The error policy is stated explicitly: repositories and use cases throw on failure, ViewModels, services and workers catch at the edge using `runCatchingCancellable` where they need a `Result`, so coroutine cancellation always propagates. That last clause is the one that matters, because swallowing cancellation is the classic Kotlin concurrency bug and the project has a named helper for it.

Room migrations are mandatory, and version 4 already exists

One line in the architecture section has real consequences for anyone modifying the app: Room migrations preserve versions 1 to 3 when upgrading to version 4, new schema changes must include a migration, and destructive fallback is disabled.

Those three statements together define the upgrade contract. A destructive fallback, which is Room's behaviour when a migration is missing and you allow the database to be recreated, is switched off. So if you change the schema without writing a migration, the app does not silently reset your library. It fails, loudly, which is the correct choice for an app where the library is the user's photos organised into albums.

The version range in the README tells you the shape of the history. Versions 1 through 3 had migrations written for them, and reaching version 4 required one.

The rest of the storage model follows from the repository rules above. Because `AlbumRepository` owns mutations and uses transactions for covers and queue invalidation, a schema change touches that class's tests, and because `WallpaperRepository` owns queues in a single transaction, the queue tables are the other place a migration will show up.

For a user upgrading from an older install, the practical promise is that their albums and settings survive. For a contributor, the practical demand is that you cannot shortcut a schema change by letting Room recreate the database.

The build toolchain is pinned tighter than most Android projects

The prerequisites table is where an unexpected build failure usually comes from, and the numbers are specific.

Java 17, Android Gradle Plugin 9.3.2, Gradle 9.7.1, compile SDK 37 which is Android 17, minimum SDK 31 which is Android 12, and target SDK 36.

Two things follow. The minimum SDK of 31 excludes every device below Android 12, which for a wallpaper app means an install on an older phone is refused rather than degraded. And the compile SDK of 37 with a target SDK of 36 means the project compiles against a newer platform than it targets, which is the normal arrangement but also means your Android Studio installation has to know about SDK 37.

For verification, the README documents two commands:

bash
./gradlew testDebugUnitTest lintDebug assembleDebug
./gradlew connectedDebugAndroidTest

The first runs unit tests, lint and a debug assembly in one invocation. The second runs device tests, which need a running emulator or a connected device on API 31 or newer, and on Windows the wrapper is `gradlew.bat`.

That the wrapper is checked in is stated alongside the requirement to set `ANDROID_HOME` or configure `sdk.dir` in `local.properties`. Using the checked-in wrapper rather than a system Gradle is what keeps the 9.7.1 requirement honest.

The device tests are described by coverage area rather than by count: rendering, scheduling, document provider failures, import rollback, album cleanup and library controls. Those six areas map directly onto the architecture rules above, since import rollback is what the transactional import in `AlbumRepository` buys and document provider failure handling is what `DocumentSource` exists to isolate.

Alongside the Gradle files the repository has a `metadata/` directory, `CHANGELOG.md` and a `renovate.json`.

Tech stack, translations and maintenance

The tech stack table names one choice per category, which is unusually disciplined for an Android app of this size.

Kotlin for the language, Jetpack Compose for the UI framework, Material 3 as the design system, Dagger Hilt for dependency injection, Room for the database, and Coil for image loading. A single further dependency is listed in a collapsed section: Zoomable, described as zoomable and pannable views.

That last one tells you something about the app's shape. A wallpaper preview that can be zoomed and panned means the editing flow treats the image as the subject, and the effects list including blur and vignette implies you adjust those on the full-resolution image rather than on a thumbnail.

Room rather than DataStore for the database is consistent with the architecture section, since the albums, covers and rotation queues are relational data rather than preferences. Hilt is consistent with the repositories-and-use-cases structure, since that pattern normally relies on constructor injection.

On translations, the README asks for help and states that most translations are currently provided using machine translation, with contributions from native speakers appreciated. Translation is handled through Crowdin, which means the translation source lives outside the repository and pull requests for translations are not the mechanism. That is worth knowing before you go to fix a translation in the source tree.

Maintenance is current. The repository is not archived, the last push was on 2026-10-13, four days before today, and the default branch is `master`. Releases are frequent and small: v4.2.1 on 2026-10-13, v4.2.0 on 2026-09-26 and v4.1.1 on 2026-09-12. Patch releases days apart and minor releases every few weeks indicate active maintenance rather than a finished project, which is the right expectation for an app that has to follow Android platform changes.

The topic list includes `mvvm`, which matches the architecture rule that ViewModels hold UI state only and that settings side effects run through `SettingsCoordinator`.

Editorial conclusion

Paperize fits someone who wants their wallpaper to change on a schedule from local images without an account, an upload or a network dependency, and its F-Droid presence provides a listed download route. Do not adopt it if your device runs below Android 12, since the minimum SDK is 31, and do not fork it expecting a forgiving build, because the toolchain is pinned to Java 17, Android Gradle Plugin 9.3.2 and Gradle 9.7.1. Verify first that Room migrations must exist for your schema change, since destructive fallback is disabled and version 4 already preserves versions 1 to 3.

Frequently asked questions

How do I install Paperize?

Three channels are listed: GitHub releases, F-Droid as `com.anthonyla.paperize`, and IzzyOnDroid. The F-Droid route provides a download option rather than a store-based installation.

What are the Android version requirements for Paperize?

Minimum SDK 31 which is Android 12, compile SDK 37 which is Android 17, and target SDK 36. Devices below Android 12 are excluded by the minimum SDK.

What do I need to build Paperize from source?

Java 17, Android Gradle Plugin 9.3.2, Gradle 9.7.1, compile SDK 37, minimum SDK 31 and target SDK 36. Set `ANDROID_HOME` or `sdk.dir` in `local.properties`, then use the checked-in Gradle wrapper rather than a system Gradle.

Which image formats does Paperize support?

JPG, PNG, WEBP, AVIF, HEIC/HEIF, BMP, GIF, TIFF and SVG. Both static and live wallpapers are supported, and wallpaper effects include brightness, blur, scaling and vignette among others.

Can I destroy the Paperize database instead of writing a migration?

No. The README states that new schema changes must include a Room migration and that destructive fallback is disabled, and that migrations preserve versions 1 to 3 when upgrading to version 4. A missing migration fails rather than recreating the database.

What license is Paperize released under?

GNU General Public License v3.0, with the LICENSE file at the repository root. If you fork it into a product, the copyleft obligation applies to your derivative.

Official sources

  1. Anthonyy232/Paperize on GitHub
  2. License: GPL-3.0
  3. Project website
  4. README
  5. Releases
Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/anthonyy232-paperize.svg)](https://hysenlabs.com/projects/anthonyy232-paperize)

Was this useful?