Show HN: Gander, an Android file viewer that asks for no permissions (github.com)
I built an Android file viewer that opens PDF, Word, Excel, PowerPoint, images, video, audio, Markdown and code, and asks for no permissions at all.
I have always been uneasy about opening files people send me. On Android you either install a 400 MB office suite and sign in or use a small free viewer that wants storage access and ends up uploading your file to a server to render it. Also the hassle of having to download different apps for different file formats was really annoying.
Gander holds no permissions, not even INTERNET so the OS itself guarantees the file cannot leave the phone.
PDFs use Pdfium, media uses Media3, and Office formats are rendered by bundled JS libraries in a WebView and so no request goes to any server.
It is a viewer only. Complex PowerPoint decks come out approximately right, spreadsheet charts are not drawn, and old binary .doc and .ppt are unsupported. I'll work on it as issues come up :P
It is 14 MB, MIT licensed and uploaded on Github releases.
Do try it! I would love some feedback especially on files that render badly or need new support.
46 comments
[ 0.23 ms ] story [ 31.9 ms ] threaddocx was annoying in a different way. Bullets came out as junk characters for a while and I couldnt work out why. I then found that Word writes them as private use area codepoints in the Symbol font so unless you have that exact font you get some junk. I just map them back to unicode after the render.
xlsx was the easy one, SheetJS does the hard part.
On faithful though none of this is faithful the way LibreOffice is. Its more that "you can read the document and it looks roughly right" which is what I wanted out of an app of 14MB.
I thought granting internet access to apps is not avoidable on Android.
When an app does not request internet, is it really guaranteed that it cannot talk to the outside world? Or is it having other avenues like opening a browser or some other component with a custom url or something?
Update: I just asked Gemini, and it does not look good:
An Android app without the INTERNET permission is not guaranteed to be isolated from the outside world. While it cannot make direct network connections itself, it can use several other mechanisms to transmit data externally:
Intent-Based Communication (The Browser) An app can launch an explicit or implicit Intent to hand data over to another app that does have internet access.
That means the app can open a system browser using a URL containing the data it wants to transmit.
It can also load a Chrome Custom Tab inside its own UI task, passing data through the URL string.
There is also Inter-Process Communication: If two apps from the same developer share a User ID (sharedUserId), they run in the same process and share all permissions, including internet access.
There is also the concept of Content Providers: Content Providers allow apps to share data. An offline app can write data into a shared database or a public Content Provider. A secondary, online-enabled app can then read that database and upload the contents.
But I think the OP is to be complimented for what they've built and their intention in making it local-only. I've long felt that apps that *genuinely" respect privacy are one of the few areas of opportunity still left in the mobile space. I wish there were more develpers building things like this.
Good grief. What a huge vulnerability. Is there some benefit that justifies this?
This can be mitigated by using an app like URLCheck [1], which you set as your default browser, and it shows and lets you edit the URL being opened before handing it off to your real browser. It also has neat features like choosing to open in incognito (if you use Firefox) and automatically removing tracking parameters.
[1] https://f-droid.org/packages/com.trianguloy.urlchecker
It's not a guarantee then, it's just a lot less to check. There's no silent route out so all that's left is what the app chooses to send via intents and Gander sends two, both when you tap something ("Share" and "Show in file manager")
Nothing anywhere builds a URL out of the file contents. No browser launch, no Custom Tabs and no shared user ID. The only content provider is closed to other apps. The one time a file goes anywhere is when you hit Share and pick the app, and what it gets is read access to that one file.
In case you grep it there's an https:// in ViewerActivity.kt. That's the local virtual host WebViewAssetLoader serves the bundled renderers from, it never leaves the process.
- An app without the INTERNET permission will crash the moment you try to access the internet. It's like a rite of passage of every android developer with every new project, you forgot the permission.
- Launching an Intent is EXTREMELY visible. It opens a full on browser. It's limited to a GET with a dedicated URL, so what are they going to do, stuff your data in query params ?
- Even in the case of another app being installed that would silently receive this intent and not pop an activity, you need a different app. It cannot be an activity added by the same package.
- Loading a Chrome Custom Tab opens a whole ass browser in front of you, think you're going to miss it ?
- Shared user IDs also require two different app installations and you cannot declare multiple. You also cannot have sharedUserId if you do not sign the apps with the same key. you cannot sharedUserId with Facebook, you need once again a dedicated app installation.
- A ContentProvider needs a dedicated permission on the writing app AND on the reading app, which is once again very visible.
I'll add more to your list: an app can request to write a file inside your downloads folder, and another one can show a popup asking you to open it! And if someone shows up with a hammer at your door, he can also hit your fingers really hard to make you tell him the data.
Android apps are, by default, very well isolated. INTERNET is a permission like any other, just not surfaced as a dangerous one (like permanent access to your background location would be), or a runtime one (like access to your current location while the app is in foreground)
Fixed in the manifest just now, it'll be in the next build.
odt and odp dont work at all. odt is a fair ask.. its the same shape of problem as docx so it's doable. Less sure about odp though.. the pptx renderer is already the weakest part of this.
And yeah, fewer apps on the phone was pretty much the whole reason I started building this.
> Requirements: JDK 17+ and the Android SDK (platform 35).
Bummer. I am stuck with Android 14 for the moment.
Android 14 is well past the floor, you're good to go!
> A tiny, open source, fully offline file viewer for Android that opens PDF, Word,
Perhaps correct Word to DOCX. Word is not just DOCX and DOCX is not just Word. This user needs DOC viewing and would be disappointed having installed this app.
I wish you every success with this.
How is accessibility? Do PDFs work with screenreaders for example?
1. Markdown loads as preview
2. Plain text files wrap instead of scrolling to the right
Good job and thank you for sharing
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
I know it's old, but I still receive them from time to time.