The reports said the image failed to send. Different messaging apps, different devices, no pattern we could see except that it happened more on slower phones and more when the network was poor.

It was not a network problem. We were deleting the file while the other app was still reading it.

What sharing an image actually involves

You do not hand another Android app a file. You hand it a content URI — an opaque reference that your app serves through a provider — along with a temporary permission grant that lets the receiving app read it.

ONEShot renders the edited image, writes it to a temporary file, produces a URI for it through a FileProvider, and starts a share intent with FLAG_GRANT_READ_URI_PERMISSION. The system shows the share sheet. The user picks an app. That app opens the URI and reads the bytes.

The problem is in that last sentence, and specifically in *when*.

We had been cleaning up the temporary file when our activity resumed — the user had gone away to the share sheet and come back, so surely the share was done. That reasoning is wrong in two ways. The receiving app may still be reading; a large image over a slow storage path takes time. And several messaging apps do not read the image at the moment they receive the intent at all. They keep the URI, show you a compose screen, and read the bytes when you press send — which might be a minute later, after you have typed a message.

So a fast phone with a small image usually worked. A slow phone, a large image, or a user who typed a paragraph before sending got a file that had been deleted underneath them. The receiving app reported a failure in whatever terms it had available, and none of those terms were "the sending app deleted the file."

What we changed

Cleanup is time-based and generous, not lifecycle-based. Temporary shared files are removed on a schedule that assumes the receiving app might take a long while. They are small, they live in cache, and the system can reclaim that directory under pressure anyway. Deleting them promptly bought nothing and cost sends.

Cleanup happens on the way in, not on the way out. When ONEShot next starts a share, it clears out anything older than the retention window. This is the pattern that avoids the whole class of "when is the other app finished" question, which has no answer available to us.

One file per share, uniquely named. Reusing a filename meant a second share could overwrite the file that a first, still-pending share was pointing at. That produced the genuinely alarming version of the bug: the recipient got the wrong image.

That last one is why this is worth writing up. A crash is bad. Sending someone a different screenshot from the one you thought you were sending is much worse, especially in an app whose main job is removing things from images before they go out.

The other file mix-up

A related problem, and this one is the user's rather than ours, but the app can help.

It is remarkably easy to edit a screenshot, then share the original from the gallery. The gallery is where your muscle memory goes, the edited version and the original look similar in a thumbnail grid, and the original is usually the more recent of the two if the edit was saved first.

For an app used to remove private details, this is the failure that matters most, because the shared file is precisely the unredacted one.

ONEShot's answer is to keep sharing in the app rather than sending you back to a gallery to find the file, and to make the edited version visually distinguishable when it is saved. Neither of these is a guarantee. If you edited a screenshot to hide something, share it from the editor.

Format, and why we do not helpfully convert to JPEG

Screenshots are PNG. That is what Android captures, and it is the right format: a screenshot is mostly flat colour and sharp text, which is exactly what lossless compression handles well and exactly what JPEG handles badly.

Converting to JPEG makes the file smaller, and it also puts ringing artefacts around every letter. Text on a coloured background gets a visible halo. On a screenshot of a settings screen or a chat, the result looks noticeably degraded even at high quality settings.

So ONEShot exports PNG for screenshot-shaped images. The file is bigger. It is the right trade for content that is largely text.

This does mean that many messaging apps will recompress it on the way through, and there is nothing we can do about that. What arrives at the other end is out of our hands the moment the URI is read. The thing that is in our hands is not degrading it before it leaves.

Preparing a screenshot that communicates

The technical part is the easy half. Most bad screenshots are bad because of what was included, not how they were encoded.

Know why the screenshot exists. Asking for help, showing where to tap, saving evidence, reporting a bug, sharing something funny — each one implies a different crop and a different amount of context. A support screenshot needs the error and enough surroundings to identify the screen. A "tap here" screenshot needs the button and almost nothing else.

Crop for the reader's eye, not for size. Extra content — status bars, unrelated messages, empty space — makes the important part harder to find. Too little context and the reader cannot tell what they are looking at. The right crop answers "what should they notice first."

Scan the whole frame for private detail before anything else. Not the part you care about; the whole thing. Notification previews at the top. A name in a header. An account label in a corner. An address in a search suggestion. Someone else's message partly visible at the edge. This is where screenshots leak, and it is always the periphery.

Use as little markup as possible. One highlight beats five arrows. If several things need explaining, send several images in sequence and put the numbering in your message rather than inside the picture. The screenshot is evidence; the message is the explanation. Keeping those separate makes the conversation easier to follow.

Keep the original when it might be evidence. For a payment problem, an app error, or an official form, the unedited image may matter later. Share the edited one, keep the original private.

Look at what you are about to send. Not the edit screen — the finished image. This is a two-second habit and it catches both the wrong-file mistake and the redaction that did not quite cover what it needed to.

What we still cannot control

Once a receiving app has the image, everything about it is theirs: recompression, backup, forwarding, retention. An image shared into a group chat is an image that exists on every device in that group, and any of those may be backing up to somewhere you did not choose.

That is not a reason not to share screenshots. It is a reason for the review to happen before the share sheet opens, because it is the last moment at which anything is reversible.