Direct answer
Password-protected PDF handling is an open-and-process workflow, not a reason to make an unprotected copy automatically. Pin each Android member separately: the PdfRenderer(ParcelFileDescriptor, LoadParams) constructor is documented as added in API 35; LoadParams and LoadParams.Builder.setPassword() are documented from API 35 and S Extensions 13; PdfRendererPreV and its password-taking constructor are also API 35 plus S Extensions 13, while that compatibility class can render documents from Android R through U. Do not transfer one member's version label to another or infer availability on every API 30–34 device. A null password means none was supplied; an unencrypted document or an empty user password may also open without proving that a required credential was accepted. Check the exact SDK extension or compatibility path before prompting. The constructor requires a seekable ParcelFileDescriptor. A protected PDF can use a user password to open with document-defined operation restrictions, or an owner password associated with broader permissions. The PDF specification distinguishes those roles, but PdfRenderer accepts a password string and does not document which role or permission bits were accepted. A successful open does not by itself prove a supplied credential was accepted, since the file may be unencrypted or accept an empty user password; only a required-password fixture with a known test credential can show that credential opens that fixture. Neither case establishes permission to export or share. Keep document restrictions and application-level user consent separate from rendering access. The failure signal is deliberately limited. Android says a required password or unsupported security scheme can raise SecurityException, and the renderer reference also documents that an incorrect supplied password raises SecurityException. Do not parse exception text or classify every SecurityException as a mistyped password. Present a neutral open failure unless another documented signal distinguishes it; let the user retry a bounded number of times or cancel, then report unsupported/unknown where appropriate. Do not brute-force credentials, silently fall back to a network viewer, or turn a failed open into an empty successful document. Treat the credential as sensitive input. Collect it only after the user selects the document and the supported renderer path is known. Keep it out of logs, analytics, crash context, saved state, WorkManager input, and persistent preferences. Clear the password field and references when the attempt ends, but do not claim that clearing a UI field zeroizes a Java/Kotlin String from memory. Avoid retaining LoadParams or renderer instances beyond their document task. If the user cancels or the process is recreated, do not restore the secret automatically; ask again when the user chooses to retry. Keep the plaintext scope narrow. A successful renderer open may allow page rendering and text/content APIs on the current document, but those operations should stay within the user-requested local task and app-owned temporary state. Android also documents PdfRenderer.write(destination, removePasswordProtection); that is a separate export capability. A read-only analysis flow should not call write with password removal, create a persistent unprotected derivative, or imply that opening the file authorized sharing. If the product later supports an unprotected export, make the destination, new file, and loss of protection explicit and verify the emitted bytes separately. Resource ownership matters on both success and failure. Pass a newly opened, app-owned descriptor for this attempt, never a borrowed descriptor shared with another task. The renderer takes ownership when construction succeeds and closes that descriptor when the renderer closes. If construction throws and no renderer is available, deterministically close this attempt-owned descriptor in the failure path rather than leaving ownership ambiguous. Keep an opened Page scoped inside the renderer: close the page first, then close the renderer; do not manually close the successful renderer's descriptor. Construction can be long-running, so perform it off the UI thread. Android recommends a separate isolated process with minimal permissions for untrusted PDFs. A coroutine timeout or cancellation signal does not prove native construction stopped: fence any late result with the current request owner, and wait for the constructor to actually exit before closing its input or deleting an app-owned temporary copy. The source remains immutable. Build fixtures that distinguish renderer behavior from credential assumptions. Include an unprotected file, a required-open-password file with a known test credential, an incorrect password, a permission-restricted file, and a file using a security scheme the chosen renderer does not support. Record API and extension level per exact class/member, renderer class, open result, page access, and whether the source bytes remained unchanged. Verify that a failure does not trigger write/removePasswordProtection, upload, or deletion. The evidence supports only the exact files, passwords, renderer, API/extension, and read-only task tested. It does not establish a general PDF security guarantee, legal rights, Cove PDF support, or that a user-supplied password should be retained.
A user supplies a password for a selected PDF
An Android app receives a password-protected PDF through a user-selected document URI. The intended task is local page review, but the current device may not expose the password-capable PdfRenderer surface, and a load failure could mean an incorrect password or an unsupported security scheme.
Decision
Check renderer/API availability first, request the password only for this attempt, keep it out of persistent state, and use a read-only renderer path. On ambiguous failure, report that the document could not be opened rather than guessing the cause or making an unprotected copy.
Expected outcome
The app can distinguish supported open, user cancellation, and unknown/unsupported failure while preserving the original PDF and not claiming broader authorization.
Evidence to collect
The claim becomes reviewable only when the following evidence is attached to the same artifact and test run:
- Renderer class, member API and S-extension identity
- Required-password and unsupported-security fixtures
- Descriptor/page lifecycle and no-unprotected-copy observation
A privacy claim needs a data inventory and traffic evidence. A local-model label by itself is not proof.
Implementation workflow
- Identify the input and renderer capability. Record source URI/provider, byte identity where available, Android API, S extension, and exact class/member path. PdfRenderer(ParcelFileDescriptor, LoadParams) is API 35; LoadParams.Builder.setPassword and PdfRendererPreV including its password constructor are API 35 plus S Extensions 13. Do not merge those labels. Require a seekable descriptor.
- Request the credential at the point of use. Ask only after the user selects a protected document and a supported path exists. Keep the value transient; do not place it in logs, analytics, saved state, persistent storage, or background-work arguments.
- Classify failures without guessing. Treat SecurityException conservatively because wrong passwords and unsupported security schemes can share that signal. Offer bounded retry or cancel; do not brute-force or silently send the document elsewhere.
- Keep processing read-only and local. Use an attempt-owned seekable descriptor, never a borrowed shared handle. On constructor failure, close that descriptor deterministically; after success, close any Page before the renderer and let the renderer close its descriptor. Load off the UI thread and consider Android-recommended isolated/minimal-permission handling for untrusted PDFs. Do not call write with password removal unless there is a distinct user-requested export.
- Verify the credential and data lifecycle. Test an unprotected document separately from a required-password fixture with a known test credential, plus incorrect, restricted, and unsupported-security fixtures. A timeout does not prove native construction stopped: fence stale results and wait for actual exit before closing input or deleting a temporary copy. Confirm the secret is not persisted and source bytes remain unchanged.
Keep each transition observable. A failure should identify the stage, artifact, runtime, and recovery action without logging private user content.
Acceptance criteria
- Version requirements are attributed per member: PdfRenderer(ParcelFileDescriptor, LoadParams) is API 35; LoadParams.Builder.setPassword and PdfRendererPreV/password constructor require API 35 plus S Extensions 13. No member inherits another member's label.
- A SecurityException is not automatically labeled an incorrect password because the renderer also reports unsupported security schemes through that exception path.
- The password is never intentionally persisted, logged, placed in saved/background state, or used for an automatic network fallback; no memory-zeroization claim is made.
- Successful open does not prove a supplied password was accepted for an unencrypted or empty-password document; only a required-password fixture can verify the known test credential. Open success still grants no owner-level right or export consent.
- Only an attempt-owned descriptor is passed to construction; constructor failure closes it, successful use closes Page then renderer, and renderer owns successful descriptor closure. For untrusted input, isolation/minimal permissions and off-UI construction are considered; stale/cancelled work cannot clean input until construction actually exits.
Decision table
| Dimension | Choice or evidence | How to interpret it |
|---|---|---|
| No-password PDF | Open through the version-supported renderer path with no credential. | A successful open does not prove every page feature or later export behavior. |
| User/open password | Prompt for a user-supplied credential and open only the selected document. | The PDF standard associates this role with document-defined restrictions; Android does not report which password role was accepted. |
| Owner/permission password | Do not infer owner rights from a string that happens to open the renderer. | Permission policy and the app’s decision to export/share remain separate; do not bypass document or user restrictions. |
| Unsupported security scheme | Report the open path as unsupported or unknown and preserve the original. | SecurityException is not a reliable password-typo classification; no password search or network fallback is appropriate. |
Failure patterns to prevent
- Applying API 35 or S Extension 13 labels to the wrong member
- Treating every SecurityException as a wrong password
- Treating successful open as export permission or password erasure
Also prevent silent fallback, unpinned artifacts, missing cancellation, and conclusions that combine unlike configurations. Store unsuccessful runs alongside successful ones.
Minimum reproducibility record
| Layer | Record |
|---|---|
| Device | Manufacturer, model, chipset, RAM class, operating-system build |
| Software | Application version and git commit |
| Model | Family, variant, revision, format, file length, hash, quantization |
| Runtime | Name, revision, requested backend, observed backend evidence |
| Workload | Fixture revision, input hash, prompt hash, output policy |
| Outcome | Completed, failed, cancelled, fallback, and privacy-safe diagnostics |
Release checklist
- ☐ The primary query is answered without an unsupported number.
- ☐ Every artifact and runtime is pinned.
- ☐ The representative task and failure policy are explicit.
- ☐ Lifecycle, cancellation, cleanup, and fallback are tested.
- ☐ User-content and network boundaries are documented.
- ☐ Result wording applies only to the recorded configuration.
- ☐ The page links to raw method or evidence when results are added.
Sources and related evidence
- Android privacy and security
- Android API — LoadParams.Builder.setPassword (API 35; S Extensions 13)
- Android API — PdfRenderer constructors (API 21/35), worker-thread and untrusted-file isolation guidance
- Android API — PdfRendererPreV and password constructor (API 35; S Extensions 13)
- Android PDF viewer — API 35 and compatibility surface
- Adobe — PDF Reference 1.7 security handler and password roles
Chinese deployment and troubleshooting content is organized in the .奇连 AI 端侧专题.
Frequently asked questions
Which Android API supports a password-protected PDF?
The PdfRenderer(ParcelFileDescriptor, LoadParams) constructor is API 35. LoadParams.Builder.setPassword and PdfRendererPreV, including its password constructor, are API 35 plus S Extensions 13. Check the exact member and device extension; do not apply one member's label to another.
Does SecurityException prove the user entered the wrong password?
No. Android documents both incorrect-password and unsupported-security-scheme failures through SecurityException. Unless another documented signal distinguishes them, report that the renderer could not open the file.
Does a successful open prove the supplied password was accepted?
Not for every file: an unencrypted PDF or one with an empty user password may open without establishing that. Use a required-password fixture and a known test credential to test that narrow claim; open success still does not report password role or authorize export.
Should the app save a decrypted copy to simplify later processing?
Not by default. Keep the standard workflow read-only and temporary. PdfRenderer.write can remove password protection, so any unprotected export requires a distinct user action, destination, and output verification.