Hacktoberfest 2026: the issues maintainers tagged for October, open and beginner-friendly. Browse Hacktoberfest issues

Android: read the clipboard through a component that satisfies the Android 10 focus/IME gate

Open
#2,685 0 comments 0 reactions 0 assignees View on GitHub

Maintainers usually reply within 1 day

Nobody has claimed this yet.

Assessment

Difficulty
5/5
Estimated time
Over a week
Newbie friendliness
38/100
Issue type
Feature
Clarity
Mostly clear
Activity status
Active
Tech stack
android, typescript

Research direction

Start with #2676's AndroidToolHost.probeClipboardShellSupport fact and the existing helper-APK lifecycle, then evaluate the bundled test IME, foreground helper activity, and snapshot helper in that order. Use the Android leg tests, capability-probe tests, and cross-language golden table as the validation seams. Done means Android 16 reads a copied marker, distinguishes route failure from an empty clipboard, and updates help, website/docs/docs/commands.md, and website/docs/docs/known-limitations.md.

Written by the indexing model from the issue text.

Description

enhancement needs-triage

Purpose

Make an Android clipboard read able to return real clip contents on a modern Android build.

#2674 diagnosed the empty read as Android 10's (API 29) clipboard-access restriction. That restriction is real, but on every build the CLI can currently reach it is not the binding constraint: no Android build through 16 implements a shell command for the clipboard service, so adb shell cmd clipboard … never reaches ClipboardManager at all — it is answered by Binder.handleShellCommand's framework default (No shell command implementation. on stderr, exit status 0). #2676 makes that answer refuse with UNSUPPORTED_OPERATION instead of reporting an empty clipboard. It does not make a read work, and it cannot: adb has no process that satisfies the focus/IME gate.

This issue is that remaining half: read the clipboard from a component that satisfies the gate, so clipboard read can verify a copy flow on Android 10+ devices.

Required behavior

  • On a build with no clipboard shell command, clipboard read returns the device's actual primary-clip text when the read route is available on that device.
  • A read that the route could not perform fails with a typed reason. It never resolves an empty string as an answer: "denied", "no route installed", and "the clipboard is genuinely empty" must be distinguishable by details.reason, never by prose.
  • capabilities advertises clipboard only when the route that will answer the read is actually present on that device, not when some hypothetical route could exist.
  • Writes are unchanged. Android does not gate setPrimaryClip the way it gates reads, and #2676's refusal stays the answer on builds where the write cannot be issued at all.
  • The route is installed and driven through the existing helper-APK lifecycle, with the same first-install-confirmation behavior documented for the snapshot helper and test IME.

Candidate routes

Evaluate in this order; the issue is decided by whichever one proves out on a device.

  1. The bundled test IME. Under --test-ime it is the active input method service and is therefore permitted to call getPrimaryClip(). Needs a read command in its protocol plus lifecycle ownership.
  2. A helper activity brought to the foreground. Satisfies the focus half of the gate, but takes over the screen and changes what the next interaction sees, so it has to state that in its result.
  3. The snapshot helper. Lowest install cost — it is already installed for Android snapshots — but it has neither focus nor IME status today, so it only works if it can be made to hold focus without disturbing the screen.

Observable completion conditions

  • On an Android 16 (API 36) device, an in-app copy (long-press → Copy in any stock app) is then read back by clipboard read, with the marker text in the JSON result.
  • pnpm check:affected --run passes, with the new behavior covered at the same seams as the existing clipboard legs: the Android leg tests, the capability-probe tests, and the cross-language golden table if a new reason crosses the runner boundary.
  • Versioned help (help clipboard), website/docs/docs/commands.md, and website/docs/docs/known-limitations.md state which devices answer a read and what each refusal reason means.

Boundary

// clipboard read --json, route present, copy performed in an app
{ "success": true, "data": { "platform": "android", "action": "read", "text": "SECRET-MARKER-42" } }

// clipboard read --json, route not installed on this device
{
  "success": false,
  "error": {
    "code": "UNSUPPORTED_OPERATION",
    "details": { "reason": "android_clipboard_read_route_unavailable" },
    "hint": "…" // names the install or activation step, never another adb attempt
  }
}

An empty clipboard answers text: "" with a route-reported fact distinguishing it from a denial; the exact fact shape is this issue's first decision.

Dependencies

  • Depends on #2676 (fix/android-clipboard-shell-response) for the response classifier, the typed android_clipboard_shell_command_unavailable refusal, and the AndroidToolHost.probeClipboardShellSupport fact. That probe's verdict becomes a route identity (shell-command / ime / helper / none) rather than a single supported/unsupported bit; whoever takes this owns that widening.
  • Part of #2674, whose reported symptom #2676 already removes.
  • Out of scope here: classifying pre-shell_v2 merged-stream output, where the missing-shell sentence arrives on stdout and is indistinguishable from clipboard payload.
Dominant language
TypeScript
Stars
4.8k
Forks
315
Avg merge
11h 17m
Merged PRs (30d)
536

Getting set up

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

More from callstack/agent-device

All issues in callstack/agent-device

Similar issues

More TypeScript issues

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.