Skip to content

qrdrop app 1.1.0

Choose a tag to compare

@github-actions github-actions released this 17 Sep 10:58
· 93 commits to main since this release
app-v1.1.0
8f3c5a1

A smaller Android download. Each release now has an APK per processor type beside the
universal one, and the F-Droid repository offers a phone only its own: about 14 MB for a
typical phone instead of 45. The universal APK is still on the Release page for anyone not
sure which they need. 32-bit x86, which only emulators use, is no longer built.

Android receives files. 1.0.0 could send from Android and could not receive at
all — and it said the wrong thing about why: pressing Save created an empty file and
then reported that the save dialog had been closed. Two things were wrong, and a phone
found them one after the other. The save dialog hands back a content:// address
rather than a path, which the app could not open; it now opens it through Android's
own content resolver. And Android's bridge between the app's page and its native half
cannot carry raw bytes, so the file's blocks now cross it as base64 there, while
Windows, macOS and Linux keep the faster raw path. Measured on a Realme phone running
Android 16: a 64 MiB file received at about 3.4 MB/s, byte-identical to the original,
with the sender and the phone computing the same verification digest.

On some Android phones, take less than about 20 seconds to choose where to save.
ColorOS (Oppo, Realme, OnePlus) freezes an app about 11 seconds after it leaves the
screen, and the save dialog counts as leaving it. A frozen phone cannot answer the
sender, and a sender that hears nothing for 30 seconds gives up. Measured on that
phone: saving after 2 or 20 seconds received the file whole, and saving after 45
seconds lost the sender. Taking 45 seconds with qrdrop allowed to run in the background
also received the file whole, because Android then wakes qrdrop briefly each time data
arrives.

A receive whose sender has gone now says so. If the sender left while the save
dialog was open, the app went on to show "Receiving, 0%" once a location was chosen,
and stayed there with nothing but Cancel. It now lands on "Transfer failed", says the
other device disconnected, and empties the file it had just created. On phones that
freeze apps in the background this was the usual way a slow choice showed up; the fix
is in the code the app shares with the website, so both get it.

A file received on Android shows its real size in the Files app. Every received
file was listed as 0 B there, and by anything else that asks Android's media index,
while the file itself was complete. Android indexed it at the moment the app opened it
for writing, before a byte had arrived, and was never asked to look again. The app now
asks, once the file is closed. This applies to files received over the network and by
Beam alike.

A transfer could fail before it started, with "Out-of-order frame: expected 0, got
1".
Seen once on that phone receiving from the command line, and gone on the retry.
Two short messages that set a transfer up could leave in the wrong order when they
were sent at the same moment, and the receiving side rightly refuses that. They now
always leave in order. The fault was in the transfer code the app shares with the
website and the command line, so all three get the fix.

A receive that fails says why. If the app could not write to the place you chose,
it said the save dialog had been closed without choosing a location — which is how
Android's receive bug above stayed hidden. It now shows the real error, and the
sending device is told the transfer failed and why, rather than that it was declined.
And when something went wrong partway through, every piece of the file still on its
way failed again and replaced the message, so the reason on screen was almost never
the reason. The first failure now ends the receive, and it is the one you see.

Cancel abandons the partial file. Cancelling a receive used to close the
connection and keep what had arrived under the name you saved it as: 15.9 MB of a
64 MiB file, on the phone above. On Windows, macOS and Linux it is now deleted. On
Android it is emptied rather than deleted — the save dialog creates that document and
the app is not allowed to remove it — so a cancelled receive leaves an empty file
behind.

A send whose receiver leaves partway through says so, and stops. When the other
device cancelled or went away mid-file, the send kept going to nobody and then waited
forever for a reply: a command-line sender printed "Sent 64 MB of 64 MB" after that
phone cancelled and was still running two minutes later, and the app showed the
disconnect while the send carried on underneath it. It now ends at the next piece of
the file with "The other device disconnected", in the app, the website and the
command line alike.

A finished send is no longer reported as a disconnect. The receiving device sends
"done" and closes the connection, and both arrive in that order — but the "done"
still had to be decrypted when the close was handled, so a file that had arrived
whole could end on the sender with "The other device disconnected". Between two
command lines on one machine it happened on the first try. The sender now finishes
reading what has already arrived first, which also means a decline, or an error the
receiver reported just before closing, is shown as what it was.


Installing

brew install --cask stan-ely/tap/qrdrop-app          # macOS, Apple silicon
scoop bucket add stan-ely https://github.com/stan-ely/scoop-bucket
scoop install stan-ely/qrdrop-app                     # Windows

Both resolve to the files below, and both are updated by this workflow.
Everything else on this page is a direct download.

On Android, add this project's own F-Droid repository once and the
client offers every future release as an ordinary update:

https://share.stan-ely.com/fdroid/repo?fingerprint=889603b768cd2ca50f6c553086827880aa1aad5bbf0098a3028a7f1b7fd47582

It serves the same APK this page does, signed with the same key --
not rebuilt and re-signed by F-Droid. That is what keeps a scanned
pairing code opening the app instead of a browser tab; see below.

About these files

qrdrop-<version>-x86_64-windows.zip is the portable Windows build --
the same binary the installer carries, with no installer around it.
It is what Scoop installs. Unlike the .exe, it cannot fetch the
Evergreen WebView2 runtime if your machine has none; that ships
with Windows 11 and Windows 10 21H2 or later, so this only matters on
something older.

Android has one APK per processor type, and a universal one. Pick
arm64-v8a for practically any phone from the last decade,
armeabi-v7a for an older 32-bit phone, x86_64 for a Chromebook or an
emulator, or universal (about three times the size) if you are not
sure. Every one of them is signed with the project's release key, whose
certificate fingerprint is the one published at
https://share.stan-ely.com/.well-known/assetlinks.json -- which is
what lets a scanned pairing code open the app instead of a browser tab.

The desktop installers are not signed. There is no Windows
code-signing certificate and no Apple Developer account behind this
project, so:

  • macOS will refuse the .dmg as being from an unidentified
    developer. xattr -d com.apple.quarantine /Applications/qrdrop.app
    after installing, if you decide to trust it.
  • Windows SmartScreen will warn about the installer. "More info",
    then "Run anyway", if you decide to trust it.

Those warnings are accurate: nobody has vouched for these binaries.
Verify what you downloaded against SHA256SUMS first, and note that
every file here carries a build provenance attestation you can check
with gh attestation verify <file> --repo stan-ely/qrdrop.

iOS is not here. It is compiled on every change and is proven to
link, but shipping it needs an Apple Developer account.