Skip to content

Repository files navigation

Hanami for Android

Android client for hanami — a thin shell, not a port: a native WebView locked to your hanami server's origin, plus a NIP-55 signing bridge. hanami is server-rendered hypermedia, so the web UI is the app; every feature ships from the server and this client never diverges from it. No server code lives here.

How it works

  1. Server screen (native): enter your instance's address — a public URL, a LAN IP, or a Tailscale IP. The WebView and the signing bridge are both bound to that origin.
  2. WebView: loads hanami's own UI. Off-origin navigation opens in the system browser and never sees the signing bridge (the origin lock is a security invariant).
  3. NIP-55 bridge: a window.nostr shim injected at document-start routes signEvent / nip44.encrypt / nip44.decrypt to your NIP-55 signer app (Signet, Amber, any compliant signer). To the server it's indistinguishable from a desktop NIP-07 extension, so hanami's existing browser-signing flow works unchanged.

Features

  • Sign in with any NIP-55 signer — one upfront approval, then silent signing via the signer's ContentResolver (per-request intent fallback if the signer declines silent mode)
  • Native NIP-98 session handshake: the server's sign-in page never renders
  • File uploads (system chooser) and downloads (DownloadManager, session-authenticated)
  • Sign-out / change-server flow with a native sign-in-error surface
  • Edge-to-edge UI, light/dark themes
  • Release builds are R8-minified and v2-signed; the APK is ~2 MB

Requirements

  • Android 8.0+ (minSdk 26)
  • A hanami server you can reach
  • A NIP-55 signer app installed (e.g. Signet or Amber)

Install

Grab the APK from Releases. Zapstore publishing is coming next.

Server-side notes

  • Works over plain http:// on LAN/Tailscale IPs (cleartext is permitted via the network security config; hanami's session cookie is only Secure on https, so sessions work).
  • A Tailscale MagicDNS hostname needs an allowed_hosts entry in the server's config.toml (IP literals always pass hanami's host guard).
  • No hanami changes required; the shell appends hanami-android/<ver> to the UA if the server ever wants to tailor copy.

NIP-55 design

  • Login: nostrsigner: intent with type=get_public_key and no package — Android's chooser picks the signer; the result carries the npub and the signer's package name.
  • Background permissions requested upfront (one approval, then silent signing): sign_event for kinds 27235 (sign-in), 24242 (Blossom auth), 30630 (drive nodes), 30078 (app-data), 5 (deletes), 10063/10002 (server/relay lists), plus nip44_encrypt and nip44_decrypt.
  • After login: silent signing via the signer's ContentResolver (content://<package>.SIGN_EVENT, args [payload, pubkey, current_user]). A null cursor falls back to the intent; a rejected column does NOT (the user said no).

Building

Open in Android Studio (SDK 35). Kotlin, classic Views; dependencies are just appcompat/material/androidx.webkit — deliberately thin, like the server it fronts.

./gradlew assembleRelease produces a signed, minified APK when keystore.properties (gitignored) and the keystore are present. A fresh clone without them still builds — the release just falls back to unsigned; only the maintainer's checkout produces the installable, stably-signed artifact.

Roadmap

  • Share-target upload and camera-roll backup
  • Bunker (NIP-46) sign-in — needs zero native work, the server holds that signer
  • Multi-server switching
  • FIPS URLs (needs an on-device transport)

License

MIT

About

Android companion app for Hanami, a Blossom server with built in file manager and other features.

Resources

Stars

Watchers

Forks

Releases

Packages

Contributors

Languages