Privacy and data boundary

Verify User-Approved Android MediaStore Trash and Delete

Distinguish app-owned media from shared MediaStore rows and verify the completed system trash or delete action separately from application derivatives.

Review status: Fact and editorial QA complete; owner review pending · 2026-10-08 · Fact IDs: ANDROID-MEDIASTORE-DELETE-CONSENT-2026-10, ANDROID-PRIVACY-01, PRIVACY-01

Direct answer

Start by identifying who owns the media row and which storage boundary it belongs to. Android 10+ lets an app access and modify its own media without storage permissions; another app's MediaStore row follows a different scoped-storage path. App-specific files, MediaStore item Uris, Photo Picker grants, and SAF document Uris are not interchangeable. createDeleteRequest and createTrashRequest require specific item Uris hosted by MediaStore.AUTHORITY. Picker read access does not itself grant write or delete authority. For an app-owned media row that the product no longer needs, delete it through the owner path and separately clean app-owned thumbnails, transcripts, embeddings, or history references. Android says the app can access and modify its own media on Android 10+ without storage permissions, but re-check current ownership/access after reinstall instead of relying on an old attribution. A readable descriptor for another app's item does not establish ownership. Apps targeting Android 11/API 30+ that are not the default gallery need user confirmation to modify or delete another app's media. MediaStore trash/delete requests provide that system UI for specific item Uris; they do not handle cloud, SAF, private, or arbitrary provider data. Trash and permanent deletion are distinct. createTrashRequest(resolver, uris, true) asks to move selected rows to system trash; on approval Android sets IS_TRASHED. Passing false requests the opposite state for eligible rows. Trash remains reversible until the system-defined retention expires; it is not immediate row deletion. createDeleteRequest(resolver, uris) instead requests immediate permanent deletion. Name the chosen action and exact item set in the UI and audit record. Creating the PendingIntent does not complete the operation. Launch its IntentSender using current activity-result handling, keep an identity for the exact URI set, and process the returned result. Android says the requested operation finishes before that result is delivered: approved delete calls ContentResolver.delete; approved trash updates IS_TRASHED. Before interpreting a missing row, verify query access and use the appropriate trashed visibility, including QUERY_ARG_MATCH_TRASHED when needed. A query error, inaccessible row, or unexpected absence is unknown or may reflect an external change, not proof of this app's delete. RESULT_OK means the system operation completed; do not issue the same delete again. Re-query before updating local history or counts, and represent unavailable verification separately. Keep createWriteRequest separate: it requests general write access to specific items, not trash or delete, and is unnecessary just to request row removal. Read permission is not write permission. Apps targeting Android 11/API 30+ that are not the default gallery must show confirmation when modifying or deleting another app's media unless the user granted separate media-management special access. MANAGE_MEDIA is broader, available to eligible apps targeting API 31+, and needs its own disclosure and settings flow. It is not the default for occasional cleanup; use the narrow item request when applicable. IS_PENDING is not a trash flag. Android uses it to keep a media item that the app is still writing private from other apps until the owner clears the pending state. It is a publication/creation lifecycle for an app-owned row, not a user request to move existing shared content to trash. Similarly, deleting a MediaStore row does not prove that the source pixels were removed from an app-private cache, model input, backup, export, or another provider. Use separate cleanup steps for derivatives owned by the AI app and make their success states explicit. Do not claim that a system delete erases every copy or that an app-private cleanup removed a user's shared original. Test with disposable media from different owners: an app-owned row, another test app's row, a Photo Picker URI, and a SAF URI. Confirm the owner path differs from shared-row consent and reject non-MediaStore Uris for these APIs. Exercise trash approve/decline, restore, permanent delete, non-success result, pre-launch disappearance, and post-operation query. Verify system state and local cleanup separately. Results apply only to the tested OS/API and URI flow; they do not show that Cove exports to or manages a gallery.

A user removes a shared image after reviewing its local analysis

An Android application has analyzed a photo selected from shared media. The user wants either to place the original in the device trash or permanently delete it, while keeping a separately saved text note. The URI is readable, but the app did not create the media row.

Decision

Classify the URI and ownership, present the matching system-mediated trash or delete request for an eligible MediaStore item, then re-query the result and clean only app-owned derivatives under their own policy.

Expected outcome

The user can distinguish reversible trash from permanent deletion and see whether the external row changed, without assuming that an analysis-history deletion controls the original or every backup.

Evidence to collect

The claim becomes reviewable only when the following evidence is attached to the same artifact and test run:

  • MediaStore URI authority and owner evidence
  • Trash/delete approval and result fixtures
  • Trashed visibility and derivative-cleanup records

A privacy claim needs a data inventory and traffic evidence. A local-model label by itself is not proof.

Implementation workflow

  1. Classify URI type and current ownership. Record whether the item is app-specific, an app-owned MediaStore row, a shared row, Photo Picker, or another provider URI. Re-check ownership and access after reinstall; a readable URI or display name is not proof.
  2. Choose the narrow user action. Delete an app-owned row through its owner path. For an eligible shared MediaStore row, choose trash or permanent delete explicitly; use a write request only when the operation genuinely needs write access.
  3. Launch the item-specific system request. Use createTrashRequest or createDeleteRequest only with specific MediaStore item Uris. Show the system PendingIntent through the current activity-result flow and preserve the request identity.
  4. Handle the result and verify visibility. Record the activity result, confirm the query scope, and use appropriate trashed visibility such as QUERY_ARG_MATCH_TRASHED. After approved delete, an absent row under that verified query is consistent with the completed operation. Query failure or unexpected absence is unknown/external change, not independent delete proof; never repeat an operation already completed with RESULT_OK.
  5. Clean application-owned derivatives separately. Remove selected app-owned cache, thumbnail, transcript, or index entries under a distinct deletion contract. Preserve a user-requested note if its retention scope is separate from the original media.

Keep each transition observable. A failure should identify the stage, artifact, runtime, and recovery action without logging private user content.

Acceptance criteria

  • The implementation distinguishes app-owned rows, other apps shared MediaStore rows, Photo Picker grants, SAF Uris, and app-specific files before selecting a deletion API.
  • Trash, permanent delete, and general write access are separate actions; only specific MediaStore-authority item Uris are passed to trash/delete requests.
  • RESULT_OK is treated as completion of the requested system operation, not a permission-only grant; verification separately checks query access and appropriate trashed visibility, while inaccessible/missing rows remain unknown.
  • Read access is never described as delete permission; refusal, missing rows, and remaining backups or copies do not become false deletion-success claims.
  • The guide makes no claim that Cove currently creates, exports, trashes, or manages shared media.

Decision table

DimensionChoice or evidenceHow to interpret it
App-owned MediaStore itemRemove through the owner path, then clean linked app-owned derivatives.Android grants the creating app access to its own media on Android 10+; ownership is not inferred from URI readability.
Shared MediaStore item to trashRequest IS_TRASHED=true through createTrashRequest.System-mediated and reversible until the system-defined trash retention expires.
Shared MediaStore item to deleteRequest createDeleteRequest for the exact item Uris.Prompts for immediate permanent row deletion; not a trash state or general write grant.
SAF or Photo Picker UriUse the entry path's documented access and delete contract.Do not assume an arbitrary provider Uri is eligible for MediaStore requests.

Failure patterns to prevent

  • Equating read access with delete authority
  • Repeating deletion after RESULT_OK
  • Claiming shared-row deletion removes every copy

Also prevent silent fallback, unpinned artifacts, missing cancellation, and conclusions that combine unlike configurations. Store unsuccessful runs alongside successful ones.

Minimum reproducibility record

LayerRecord
DeviceManufacturer, model, chipset, RAM class, operating-system build
SoftwareApplication version and git commit
ModelFamily, variant, revision, format, file length, hash, quantization
RuntimeName, revision, requested backend, observed backend evidence
WorkloadFixture revision, input hash, prompt hash, output policy
OutcomeCompleted, 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

Chinese deployment and troubleshooting content is organized in the .奇连 AI 端侧专题.

Frequently asked questions

Does a Photo Picker or SAF read grant let the app delete the original?

No. A read grant and the authority that owns a MediaStore row are different facts. Use only the deletion mechanism supported by that provider and explicitly authorized by the user.

Does trash mean the item is already permanently gone?

No. createTrashRequest sets the MediaStore trash state after approval; Android says trashed items are permanently removed after a system-defined period. Permanent deletion is a different request.

Does RESULT_OK only mean permission was approved?

No. Android documents that the requested delete or trash operation is complete before the activity result arrives, so do not issue it again. Re-query with access and trash visibility in place; if that query is unavailable or the row is unexpectedly absent, report verification as unknown.

Should an app request MANAGE_MEDIA for occasional cleanup?

Not by default. It is broader special access available to eligible apps targeting API 31 or higher. A narrow item-specific system request better matches an occasional user-directed delete or trash action.