mokshablr/gander

Take a gander at any file. Offline, zero-permission Android viewer for PDF, Word, Excel, PowerPoint, photos, video, audio, Markdown and code.

JavaScript

1,107

371 commits

updated Sep 30, 2026

See the code

README

Gander: take a gander at any file. Open source Android file viewer for PDF, DOCX, XLSX, PPTX, JPG, MP4, MP3 and Markdown. 100% offline, 5 MB APK, zero permissions, no ads or trackers.

Get it on Google Play

Gander 🪿

Take a gander at any file. A tiny, open source, fully offline file viewer for Android that opens PDF, Word (.docx), Excel, PowerPoint (.pptx), photos, videos, audio, Markdown, text, code and .zip archives in one app, with zero permissions, no ads, no tracking and no internet access at all.

Join the mailing list for announcements, or grab the APK from Releases.

License: MIT Release Build Min API Kotlin

Every phone ships with a dozen half-viewers that bounce your documents to cloud services. Gander is the opposite: one small APK (about 5 MB) that renders everything on the device. It cannot phone home because it does not even hold the INTERNET permission.

arjun.maniyani.com/gander · Privacy policy

Gander demo: thumbnail recents, folder browsing, PDF, Word, Excel and Markdown viewing

Screenshots

Home: recents and foldersPDFThe same PDF, night mode
Recent files with thumbnail previews and granted foldersPDF viewer rendering a site survey report with a photographic plateThe same page with night mode on: the paper is black and the text white, the blue headings are still blue, and the photograph is left exactly as it was printed
PhotosWord (.docx)PowerPoint (.pptx)Excel (.xlsx)
Full-size photo in the zoomable image viewerWord document viewerPowerPoint slides viewerExcel spreadsheet viewer with sheet tabs

Features

  • One viewer for everything: documents, spreadsheets, slides, images, video, audio, Markdown, code, 3D models
  • Opens .zip files: a zip lists like a folder, and each file in it opens in its usual viewer, read straight out of the archive with nothing unzipped to the phone
  • Pinch zoom and smooth scrolling everywhere, with deep zoom into huge photos (tiled decoding)
  • Recent files with thumbnail previews (image, video frame, PDF first page)
  • Folder browsing through one-time system grants, still without any storage permission
  • Share sheet and "Open with" integration: share a file from any app (chat, mail, browser) into Gander, or tap it in a file manager
  • Find in document: search inside PDF, Word, OpenDocument, Rich Text, every sheet of a workbook, slides, Markdown, text and code with match navigation
  • Select and copy text in a PDF, and read one with a screen reader
  • Picks up where you left off: a PDF reopens at the page you were reading, however you open it
  • Night mode for PDFs: turns the page over for reading in the dark, keeping each colour's hue, turning scans and figures over with the text, and leaving photographs exactly as they were printed
  • Share and locate: send the open file to any app, or jump to its folder in the file manager
  • Private by construction: no permissions, no INTERNET, no analytics, no accounts, nothing leaves the phone
  • Checks its own promise: the About screen asks Android what the app requests and shows you the answer, next to the full licence text for every bundled library
  • Modern Android: Material 3, dark mode, edge to edge, works on Android 8.0+

Supported formats

CategoryFormatsRenderer
DocumentsPDFpdf.js, offline in a sandboxed WebView
Word .docx .docm .dotxdocx-preview, offline in a sandboxed WebView
Word 97-2003 .doc, OpenDocument .odt, Rich Text .rtfGander's own readers, offline in a sandboxed WebView
Spreadsheets.xlsx .xls .xlsm .xlsb .xltx .csv .odsSheetJS, offline
SlidesPowerPoint .pptx .ppsx .pptm .potxPPTXjs, offline
PhotosJPG, PNG, WebP, BMP, HEIC/HEIFTiled deep-zoom image view, EXIF aware
GIF (animated), SVG, AVIF, ICOWebView
VideoMP4, M4V, MOV, MKV, WebM, 3GP, AVI, FLV, MPEG-TSMedia3 ExoPlayer
AudioMP3, M4A, AAC, FLAC, WAV, OGG, Opus, AMRMedia3 ExoPlayer
Markdown.md rendered as formatted HTMLmarked + DOMPurify, offline
Text and code.txt .json .xml logs, subtitles (.srt .vtt), .m3u playlists, .nfo, most source filesText viewer
Archives.zipListed like a folder, entries opened in place
3D modelsSTL .stl, binary and textGander's own WebGL viewer, offline

An .stl, the file 3D printers take, opens as a solid you can turn with one finger and zoom or move with two; a double tap puts it back. Its size in millimetres is shown underneath. A phone can open models of up to about half a million triangles for each gigabyte of memory it has.

A .zip opens as a list laid out like a folder, and each file in it opens in the viewer it would get on its own, read straight out of the archive: nothing is unzipped or written to the phone. Password-protected entries open with their password, and names written by Windows zip tools in other languages are read as names rather than question marks, with File name encoding in the menu to correct a wrong guess.

Anything else, including files with no extension at all, offers View as text, which shows the raw contents without renaming the file. Large files load 5 MB at a time with a Show more button, so they open instantly and can still be read end to end.

Word 97-2003 .doc, OpenDocument .odt and Rich Text .rtf are read by code written for Gander rather than by a bundled library: text and formatting, headings, lists, tables, pictures, footnotes, headers and footers, in any script. The file's first bytes choose the reader, so a .doc that is Rich Text inside, as many are, opens all the same. Word 6 and Word 95 files show their text without formatting, and a Windows metafile picture shows a box saying it cannot be drawn.

Legacy binary .ppt is not supported (no open-source renderer is both faithful and small enough to bundle); the app explains this and suggests re-saving as .pptx. Binary .xls works.

Install

Runs on Android 8.0 (API 26) and up.

Viewing PDFs also needs Android System WebView 125 or newer (May 2024), Markdown files 92 and Word documents 80. Any phone still receiving WebView updates is well past all three; if yours is not, Gander says so when you open the file rather than failing quietly.

From Google Play, which keeps it updated: Gander on Google Play. Already installed it from here? Open the listing and tap Update. Play moves your install over, recents and folder grants included, since both copies are signed with the same key.

From GitHub, for phones without Google Play, or if you'd rather not use it:

  1. Download the latest APK from Releases: Gander-x.y.apk runs on every architecture, since the app ships no native libraries.
  2. Copy it to your phone, tap it, and allow "install unknown apps" when asked.
  3. Optional: Play Protect may warn about an unknown developer; that is what sideloaded open source looks like. Tap "Install anyway".

Updating: install the new APK over the old one; recents and folder grants survive.

Automatic updates without a store: install Obtainium and add https://github.com/mokshablr/gander as an app source. It follows the tagged GitHub releases here and updates Gander like a store would.

Verify before installing: every release is signed with the same key, so you can confirm an APK really came from this repo. Obtainium can pin the fingerprint below, and for a file you have already downloaded:

apksigner verify --print-certs Gander-x.y.apk

Signing certificate SHA-256:

5B:5C:F6:4A:94:23:7C:D5:F0:E0:85:76:00:38:BC:1C:EB:DF:18:DA:BA:5C:B3:EA:CA:7C:15:9F:22:A7:E2:4B

How the zero-permission trick works

Gander receives files through the Storage Access Framework and "Open with" intents, so the OS hands it exactly the documents you chose and nothing else. Office formats render inside a locked-down WebView whose every request is intercepted by WebViewAssetLoader: bundled JS libraries load from app assets and the document streams from the content URI. No network stack is ever touched, and the app does not declare the INTERNET permission, so there is nothing to audit or trust.

Folder browsing uses ACTION_OPEN_DOCUMENT_TREE grants. Note that Android itself refuses to grant the Downloads root to any app; grant Documents, DCIM or a subfolder of Downloads instead.

Build from source

To build it yourself you need JDK 21+ and the Android SDK (platform 36). These are build requirements only. The installed app runs on Android 8.0 (API 26) and up.

./gradlew assembleDebug        # installable debug build
./gradlew assembleRelease      # unsigned without a keystore

Release signing expects a local, untracked keystore at keystore/gander.jks, alias gander. Generate your own with:

keytool -genkeypair -keystore keystore/gander.jks -alias gander \
  -keyalg RSA -keysize 2048 -validity 10000 \
  -storepass gander-local -keypass gander-local -dname "CN=Gander"

That builds and signs with no further setup, because gander-local is the fallback password in app/build.gradle.kts. To use a different one, set it in ~/.gradle/gradle.properties rather than in the build file:

GANDER_STORE_PASSWORD=…
GANDER_KEY_PASSWORD=…

The keystore is gitignored on purpose: it is a personal signing key and must never land in a public repo. Neither should its password, which is why the real one lives outside the tree. Builds signed with your own key will not update an install of a release from here; the official signing certificate is above.

Architecture in one paragraph

ViewerActivity routes by file extension first, MIME type second (FileKind.kt), into one of four surfaces: a tiled SubsamplingScaleImageView for photos, Media3 ExoPlayer for video and audio, a sandboxed WebView for everything rendered by vendored JS libraries (app/src/main/assets/viewer/), PDF included, or a list (ArchiveBrowser.kt) for a .zip, whose entries ArchiveProvider serves back to those same surfaces without ever touching the disk. Documents under 16 MB are handed to the WebView whole; larger ones are served in ranges so only the pages being read are held in memory. The home screen (MainActivity) lists recents (persisted SAF grants) and granted folders (DocumentsContract child queries), with thumbnails generated off-thread and cached (Thumbs.kt).

Vendored viewer libraries and their licenses: pdf.js (Apache-2.0), JSZip (MIT), docx-preview (Apache-2.0), SheetJS CE (Apache-2.0), PPTXjs + divs2slides (MIT), jQuery 1.11 (MIT), D3 3.x + NVD3 (BSD/Apache), marked (MIT), DOMPurify (Apache-2.0/MPL). The app ships no native libraries.

Roadmap

  • F-Droid listing
  • Legacy .ppt support if a usable offline renderer appears
  • iOS companion (thin QuickLook wrapper)

Contributing

Issues and small PRs are welcome, see CONTRIBUTING.md. If Gander is useful to you, a star helps other people find it. There is a sponsor page as well, though a good bug report is worth more.

License

MIT, Copyright (c) 2026 Arjun Maniyani. Vendored viewer libraries keep their own licenses, listed above; all are MIT/Apache/BSD and compatible. The full text of every one of them ships inside the app, in app/src/main/assets/licences.md, reachable from About.

android
android-app
apk
document-viewer
docx
exoplayer
file-viewer
foss
kotlin
markdown
material-design
no-permissions
offline-first
pdf-viewer
pptx
privacy
video-player
xlsx

Significant stargazers

Yorick

109 followers · starred Jul 2026

Nico Domino

469 followers · starred Jul 2026

Pierce Lopez

143 followers · starred Aug 2026

Tushar Sadhwani

364 followers · starred Jul 2026

mokshablr/gander

Take a gander at any file. Offline, zero-permission Android viewer for PDF, Word, Excel, PowerPoint, photos, video, audio, Markdown and code.

JavaScript

1,107

371 commits

updated Sep 30, 2026

See the code

README

Gander: take a gander at any file. Open source Android file viewer for PDF, DOCX, XLSX, PPTX, JPG, MP4, MP3 and Markdown. 100% offline, 5 MB APK, zero permissions, no ads or trackers.

Get it on Google Play

Gander 🪿

Take a gander at any file. A tiny, open source, fully offline file viewer for Android that opens PDF, Word (.docx), Excel, PowerPoint (.pptx), photos, videos, audio, Markdown, text, code and .zip archives in one app, with zero permissions, no ads, no tracking and no internet access at all.

Join the mailing list for announcements, or grab the APK from Releases.

License: MIT Release Build Min API Kotlin

Every phone ships with a dozen half-viewers that bounce your documents to cloud services. Gander is the opposite: one small APK (about 5 MB) that renders everything on the device. It cannot phone home because it does not even hold the INTERNET permission.

arjun.maniyani.com/gander · Privacy policy

Gander demo: thumbnail recents, folder browsing, PDF, Word, Excel and Markdown viewing

Screenshots

Home: recents and foldersPDFThe same PDF, night mode
Recent files with thumbnail previews and granted foldersPDF viewer rendering a site survey report with a photographic plateThe same page with night mode on: the paper is black and the text white, the blue headings are still blue, and the photograph is left exactly as it was printed
PhotosWord (.docx)PowerPoint (.pptx)Excel (.xlsx)
Full-size photo in the zoomable image viewerWord document viewerPowerPoint slides viewerExcel spreadsheet viewer with sheet tabs

Features

  • One viewer for everything: documents, spreadsheets, slides, images, video, audio, Markdown, code, 3D models
  • Opens .zip files: a zip lists like a folder, and each file in it opens in its usual viewer, read straight out of the archive with nothing unzipped to the phone
  • Pinch zoom and smooth scrolling everywhere, with deep zoom into huge photos (tiled decoding)
  • Recent files with thumbnail previews (image, video frame, PDF first page)
  • Folder browsing through one-time system grants, still without any storage permission
  • Share sheet and "Open with" integration: share a file from any app (chat, mail, browser) into Gander, or tap it in a file manager
  • Find in document: search inside PDF, Word, OpenDocument, Rich Text, every sheet of a workbook, slides, Markdown, text and code with match navigation
  • Select and copy text in a PDF, and read one with a screen reader
  • Picks up where you left off: a PDF reopens at the page you were reading, however you open it
  • Night mode for PDFs: turns the page over for reading in the dark, keeping each colour's hue, turning scans and figures over with the text, and leaving photographs exactly as they were printed
  • Share and locate: send the open file to any app, or jump to its folder in the file manager
  • Private by construction: no permissions, no INTERNET, no analytics, no accounts, nothing leaves the phone
  • Checks its own promise: the About screen asks Android what the app requests and shows you the answer, next to the full licence text for every bundled library
  • Modern Android: Material 3, dark mode, edge to edge, works on Android 8.0+

Supported formats

CategoryFormatsRenderer
DocumentsPDFpdf.js, offline in a sandboxed WebView
Word .docx .docm .dotxdocx-preview, offline in a sandboxed WebView
Word 97-2003 .doc, OpenDocument .odt, Rich Text .rtfGander's own readers, offline in a sandboxed WebView
Spreadsheets.xlsx .xls .xlsm .xlsb .xltx .csv .odsSheetJS, offline
SlidesPowerPoint .pptx .ppsx .pptm .potxPPTXjs, offline
PhotosJPG, PNG, WebP, BMP, HEIC/HEIFTiled deep-zoom image view, EXIF aware
GIF (animated), SVG, AVIF, ICOWebView
VideoMP4, M4V, MOV, MKV, WebM, 3GP, AVI, FLV, MPEG-TSMedia3 ExoPlayer
AudioMP3, M4A, AAC, FLAC, WAV, OGG, Opus, AMRMedia3 ExoPlayer
Markdown.md rendered as formatted HTMLmarked + DOMPurify, offline
Text and code.txt .json .xml logs, subtitles (.srt .vtt), .m3u playlists, .nfo, most source filesText viewer
Archives.zipListed like a folder, entries opened in place
3D modelsSTL .stl, binary and textGander's own WebGL viewer, offline

An .stl, the file 3D printers take, opens as a solid you can turn with one finger and zoom or move with two; a double tap puts it back. Its size in millimetres is shown underneath. A phone can open models of up to about half a million triangles for each gigabyte of memory it has.

A .zip opens as a list laid out like a folder, and each file in it opens in the viewer it would get on its own, read straight out of the archive: nothing is unzipped or written to the phone. Password-protected entries open with their password, and names written by Windows zip tools in other languages are read as names rather than question marks, with File name encoding in the menu to correct a wrong guess.

Anything else, including files with no extension at all, offers View as text, which shows the raw contents without renaming the file. Large files load 5 MB at a time with a Show more button, so they open instantly and can still be read end to end.

Word 97-2003 .doc, OpenDocument .odt and Rich Text .rtf are read by code written for Gander rather than by a bundled library: text and formatting, headings, lists, tables, pictures, footnotes, headers and footers, in any script. The file's first bytes choose the reader, so a .doc that is Rich Text inside, as many are, opens all the same. Word 6 and Word 95 files show their text without formatting, and a Windows metafile picture shows a box saying it cannot be drawn.

Legacy binary .ppt is not supported (no open-source renderer is both faithful and small enough to bundle); the app explains this and suggests re-saving as .pptx. Binary .xls works.

Install

Runs on Android 8.0 (API 26) and up.

Viewing PDFs also needs Android System WebView 125 or newer (May 2024), Markdown files 92 and Word documents 80. Any phone still receiving WebView updates is well past all three; if yours is not, Gander says so when you open the file rather than failing quietly.

From Google Play, which keeps it updated: Gander on Google Play. Already installed it from here? Open the listing and tap Update. Play moves your install over, recents and folder grants included, since both copies are signed with the same key.

From GitHub, for phones without Google Play, or if you'd rather not use it:

  1. Download the latest APK from Releases: Gander-x.y.apk runs on every architecture, since the app ships no native libraries.
  2. Copy it to your phone, tap it, and allow "install unknown apps" when asked.
  3. Optional: Play Protect may warn about an unknown developer; that is what sideloaded open source looks like. Tap "Install anyway".

Updating: install the new APK over the old one; recents and folder grants survive.

Automatic updates without a store: install Obtainium and add https://github.com/mokshablr/gander as an app source. It follows the tagged GitHub releases here and updates Gander like a store would.

Verify before installing: every release is signed with the same key, so you can confirm an APK really came from this repo. Obtainium can pin the fingerprint below, and for a file you have already downloaded:

apksigner verify --print-certs Gander-x.y.apk

Signing certificate SHA-256:

5B:5C:F6:4A:94:23:7C:D5:F0:E0:85:76:00:38:BC:1C:EB:DF:18:DA:BA:5C:B3:EA:CA:7C:15:9F:22:A7:E2:4B

How the zero-permission trick works

Gander receives files through the Storage Access Framework and "Open with" intents, so the OS hands it exactly the documents you chose and nothing else. Office formats render inside a locked-down WebView whose every request is intercepted by WebViewAssetLoader: bundled JS libraries load from app assets and the document streams from the content URI. No network stack is ever touched, and the app does not declare the INTERNET permission, so there is nothing to audit or trust.

Folder browsing uses ACTION_OPEN_DOCUMENT_TREE grants. Note that Android itself refuses to grant the Downloads root to any app; grant Documents, DCIM or a subfolder of Downloads instead.

Build from source

To build it yourself you need JDK 21+ and the Android SDK (platform 36). These are build requirements only. The installed app runs on Android 8.0 (API 26) and up.

./gradlew assembleDebug        # installable debug build
./gradlew assembleRelease      # unsigned without a keystore

Release signing expects a local, untracked keystore at keystore/gander.jks, alias gander. Generate your own with:

keytool -genkeypair -keystore keystore/gander.jks -alias gander \
  -keyalg RSA -keysize 2048 -validity 10000 \
  -storepass gander-local -keypass gander-local -dname "CN=Gander"

That builds and signs with no further setup, because gander-local is the fallback password in app/build.gradle.kts. To use a different one, set it in ~/.gradle/gradle.properties rather than in the build file:

GANDER_STORE_PASSWORD=…
GANDER_KEY_PASSWORD=…

The keystore is gitignored on purpose: it is a personal signing key and must never land in a public repo. Neither should its password, which is why the real one lives outside the tree. Builds signed with your own key will not update an install of a release from here; the official signing certificate is above.

Architecture in one paragraph

ViewerActivity routes by file extension first, MIME type second (FileKind.kt), into one of four surfaces: a tiled SubsamplingScaleImageView for photos, Media3 ExoPlayer for video and audio, a sandboxed WebView for everything rendered by vendored JS libraries (app/src/main/assets/viewer/), PDF included, or a list (ArchiveBrowser.kt) for a .zip, whose entries ArchiveProvider serves back to those same surfaces without ever touching the disk. Documents under 16 MB are handed to the WebView whole; larger ones are served in ranges so only the pages being read are held in memory. The home screen (MainActivity) lists recents (persisted SAF grants) and granted folders (DocumentsContract child queries), with thumbnails generated off-thread and cached (Thumbs.kt).

Vendored viewer libraries and their licenses: pdf.js (Apache-2.0), JSZip (MIT), docx-preview (Apache-2.0), SheetJS CE (Apache-2.0), PPTXjs + divs2slides (MIT), jQuery 1.11 (MIT), D3 3.x + NVD3 (BSD/Apache), marked (MIT), DOMPurify (Apache-2.0/MPL). The app ships no native libraries.

Roadmap

  • F-Droid listing
  • Legacy .ppt support if a usable offline renderer appears
  • iOS companion (thin QuickLook wrapper)

Contributing

Issues and small PRs are welcome, see CONTRIBUTING.md. If Gander is useful to you, a star helps other people find it. There is a sponsor page as well, though a good bug report is worth more.

License

MIT, Copyright (c) 2026 Arjun Maniyani. Vendored viewer libraries keep their own licenses, listed above; all are MIT/Apache/BSD and compatible. The full text of every one of them ships inside the app, in app/src/main/assets/licences.md, reachable from About.

android
android-app
apk
document-viewer
docx
exoplayer
file-viewer
foss
kotlin
markdown
material-design
no-permissions
offline-first
pdf-viewer
pptx
privacy
video-player
xlsx

Significant stargazers

Yorick

109 followers · starred Jul 2026

Nico Domino

469 followers · starred Jul 2026

Pierce Lopez

143 followers · starred Aug 2026

Tushar Sadhwani

364 followers · starred Jul 2026

Languages

JavaScript

66.8%

Python

16.1%

Kotlin

15.2%

HTML

1.2%