{"id":"f1f52329-b3be-4878-a639-3c59682bd36f","shortId":"vqBVBv","kind":"skill","title":"android-permissions-activity-results","tagline":"Use modern permission requests, Activity Result APIs, and capability-gated UX in Android flows.","description":"# Android Permissions Activity Results\n\n## When To Use\n- Use this skill when the request is about: android permission request flow, activity result api android, camera permission in android app.\n- Primary outcome: Use modern permission requests, Activity Result APIs, and capability-gated UX in Android flows.\n- Read `references/patterns.md` when you need the picker-vs-permission matrix or API-level behavior checklist.\n- Read `references/scenarios.md` for photo picker, notification permission, and limited media access examples.\n- Handoff skills when the scope expands:\n- `android-media-files-sharing`\n- `android-testing-ui`\n\n## Workflow\n1. Start with the capability the user needs, not the permission name: photo picker, document picker, camera capture, or notification opt-in often avoids broader runtime permissions.\n2. Choose the right Activity Result contract and keep the launcher in a stable lifecycle owner such as an activity, fragment, or remembered Compose launcher.\n3. Model the full permission state space explicitly: granted, denied, permanently denied, limited/selected access, one-time access, and settings-based recovery.\n4. Account for API-level differences such as `POST_NOTIFICATIONS` on Android 13+, approximate vs precise location, background location as a separate flow, and Android 14 selected-photos access.\n5. Re-check capability on return from settings or picker flows, then validate rotation, process death, and denial recovery instead of assuming the happy path.\n\n## Guardrails\n- Treat loading, empty, error, offline, and permission-denied states as first-class UI states.\n- Do not launch permission or picker contracts directly from composition without a user action or explicit side effect.\n- Prefer the narrowest capability surface available, such as Photo Picker or SAF, over broad storage permissions.\n- Keep permission recovery testable: rationale, settings redirect, denied state, and post-return revalidation.\n\n## Anti-Patterns\n- Assuming the happy path is enough for product flows.\n- Repeatedly re-prompting after denial instead of offering a clear settings or alternate-path recovery.\n- Requesting media or storage access when the Photo Picker or document contracts are enough.\n- Treating Android 14 selected-photos access as full media-library access.\n\n## Review Focus\n- Can the feature use a picker or contract instead of a runtime permission?\n- Does the flow handle denial, limited access, and return-from-settings correctly?\n- Are permission launches owned by the right lifecycle scope and initiated at the right time?\n- Are platform-specific behaviors called out for Android 13+ and Android 14+ where relevant?\n\n## Examples\n### Happy path\n- Scenario: Find the repo's Activity Result and permission surfaces before proposing a flow change.\n- Command: `rg -n \"rememberLauncherForActivityResult|RequestPermission|RequestMultiplePermissions|PickVisualMedia|OpenDocument|TakePicture\" examples`\n\n### Edge case\n- Scenario: Review notification and media access paths for API-level-specific behavior.\n- Command: `rg -n \"POST_NOTIFICATIONS|READ_MEDIA_|READ_EXTERNAL_STORAGE|PickVisualMedia\" examples`\n\n### Failure recovery\n- Scenario: Differentiate permission prompts from media-sharing and testing requests.\n- Command: `python3 scripts/eval_triggers.py --skill android-permissions-activity-results`\n\n## Done Checklist\n- The chosen contract or picker is narrower than a broad permission where possible.\n- Denied, permanently denied, limited, and settings-return states are all modeled.\n- API-level differences are called out for the affected Android versions.\n- Recovery UI and observability are explicit instead of implied.\n\n## Official References\n- [https://developer.android.com/training/permissions/requesting](https://developer.android.com/training/permissions/requesting)\n- [https://developer.android.com/training/basics/intents/result](https://developer.android.com/training/basics/intents/result)\n- [https://developer.android.com/training/data-storage/shared/photopicker](https://developer.android.com/training/data-storage/shared/photopicker)\n- [https://developer.android.com/about/versions/14/changes/partial-photo-video-access](https://developer.android.com/about/versions/14/changes/partial-photo-video-access)\n- [https://developer.android.com/develop/ui/views/notifications/notification-permission](https://developer.android.com/develop/ui/views/notifications/notification-permission)\n- [https://developer.android.com/privacy-and-security/minimize-permission-requests](https://developer.android.com/privacy-and-security/minimize-permission-requests)","tags":["android","permissions","activity","results","agent","skills","krutikjain","agent-skills","android-development","android-skills","androidx","claude-code"],"capabilities":["skill","source-krutikjain","skill-android-permissions-activity-results","topic-agent-skills","topic-android","topic-android-development","topic-android-skills","topic-androidx","topic-claude-code","topic-codex","topic-cursor","topic-jetpack-compose","topic-kotlin","topic-skills"],"categories":["android-agent-skills"],"synonyms":[],"warnings":[],"endpointUrl":"https://skills.sh/krutikJain/android-agent-skills/android-permissions-activity-results","protocol":"skill","transport":"skills-sh","auth":{"type":"none","details":{"cli":"npx skills add krutikJain/android-agent-skills","source_repo":"https://github.com/krutikJain/android-agent-skills","install_from":"skills.sh"}},"qualityScore":"0.454","qualityRationale":"deterministic score 0.45 from registry signals: · indexed on github topic:agent-skills · 8 github stars · SKILL.md body (4,599 chars)","verified":false,"liveness":"unknown","lastLivenessCheck":null,"agentReviews":{"count":0,"score_avg":null,"cost_usd_avg":null,"success_rate":null,"latency_p50_ms":null,"narrative_summary":null,"summary_updated_at":null},"enrichmentModel":"deterministic:skill-github:v1","enrichmentVersion":1,"enrichedAt":"2026-05-18T19:13:28.572Z","embedding":null,"createdAt":"2026-05-18T13:20:51.278Z","updatedAt":"2026-05-18T19:13:28.572Z","lastSeenAt":"2026-05-18T19:13:28.572Z","tsv":"'/about/versions/14/changes/partial-photo-video-access](https://developer.android.com/about/versions/14/changes/partial-photo-video-access)':561 '/develop/ui/views/notifications/notification-permission](https://developer.android.com/develop/ui/views/notifications/notification-permission)':564 '/privacy-and-security/minimize-permission-requests](https://developer.android.com/privacy-and-security/minimize-permission-requests)':567 '/training/basics/intents/result](https://developer.android.com/training/basics/intents/result)':555 '/training/data-storage/shared/photopicker](https://developer.android.com/training/data-storage/shared/photopicker)':558 '/training/permissions/requesting](https://developer.android.com/training/permissions/requesting)':552 '1':111 '13':200,417 '14':213,354,420 '2':139 '3':164 '4':187 '5':218 'access':93,177,181,217,342,358,364,386,458 'account':188 'action':274 'activ':4,10,23,40,55,143,158,431,498 'affect':536 'altern':335 'alternate-path':334 'android':2,19,21,36,43,47,64,102,107,199,212,353,416,419,496,537 'android-media-files-shar':101 'android-permissions-activity-result':1,495 'android-testing-ui':106 'anti':310 'anti-pattern':309 'api':12,42,57,79,191,462,528 'api-level':78,190,527 'api-level-specif':461 'app':48 'approxim':201 'assum':240,312 'avail':284 'avoid':135 'background':205 'base':185 'behavior':81,412,465 'broad':292,511 'broader':136 'call':413,532 'camera':44,127 'capability-g':14,59 'capabl':15,60,115,222,282 'captur':128 'case':452 'chang':440 'check':221 'checklist':82,501 'choos':140 'chosen':503 'class':258 'clear':331 'command':441,466,491 'compos':162 'composit':270 'contract':145,267,349,374,504 'correct':392 'death':234 'deni':173,175,253,302,515,517 'denial':236,326,384 'developer.android.com':551,554,557,560,563,566 'developer.android.com/about/versions/14/changes/partial-photo-video-access](https://developer.android.com/about/versions/14/changes/partial-photo-video-access)':559 'developer.android.com/develop/ui/views/notifications/notification-permission](https://developer.android.com/develop/ui/views/notifications/notification-permission)':562 'developer.android.com/privacy-and-security/minimize-permission-requests](https://developer.android.com/privacy-and-security/minimize-permission-requests)':565 'developer.android.com/training/basics/intents/result](https://developer.android.com/training/basics/intents/result)':553 'developer.android.com/training/data-storage/shared/photopicker](https://developer.android.com/training/data-storage/shared/photopicker)':556 'developer.android.com/training/permissions/requesting](https://developer.android.com/training/permissions/requesting)':550 'differ':193,530 'differenti':481 'direct':268 'document':125,348 'done':500 'edg':451 'effect':278 'empti':247 'enough':317,351 'error':248 'exampl':94,423,450,477 'expand':100 'explicit':171,276,544 'extern':474 'failur':478 'featur':369 'file':104 'find':427 'first':257 'first-class':256 'flow':20,39,65,210,229,320,382,439 'focus':366 'fragment':159 'full':167,360 'gate':16,61 'grant':172 'guardrail':244 'handl':383 'handoff':95 'happi':242,314,424 'impli':547 'initi':403 'instead':238,327,375,545 'keep':147,295 'launch':263,395 'launcher':149,163 'level':80,192,463,529 'librari':363 'lifecycl':153,400 'limit':91,385,518 'limited/selected':176 'load':246 'locat':204,206 'matrix':76 'media':92,103,339,362,457,472,486 'media-librari':361 'media-shar':485 'model':165,526 'modern':7,52 'n':443,468 'name':122 'narrow':508 'narrowest':281 'need':70,118 'notif':88,130,197,455,470 'observ':542 'offer':329 'offici':548 'offlin':249 'often':134 'one':179 'one-tim':178 'opendocu':448 'opt':132 'opt-in':131 'outcom':50 'own':396 'owner':154 'path':243,315,336,425,459 'pattern':311 'perman':174,516 'permiss':3,8,22,37,45,53,75,89,121,138,168,252,264,294,296,379,394,434,482,497,512 'permission-deni':251 'photo':86,123,216,287,345,357 'picker':73,87,124,126,228,266,288,346,372,506 'picker-vs-permiss':72 'pickvisualmedia':447,476 'platform':410 'platform-specif':409 'possibl':514 'post':196,306,469 'post-return':305 'precis':203 'prefer':279 'primari':49 'process':233 'product':319 'prompt':324,483 'propos':437 'python3':492 'rational':299 're':220,323 're-check':219 're-prompt':322 'read':66,83,471,473 'recoveri':186,237,297,337,479,539 'redirect':301 'refer':549 'references/patterns.md':67 'references/scenarios.md':84 'relev':422 'rememb':161 'rememberlauncherforactivityresult':444 'repeat':321 'repo':429 'request':9,33,38,54,338,490 'requestmultiplepermiss':446 'requestpermiss':445 'result':5,11,24,41,56,144,432,499 'return':224,307,389,522 'return-from-set':388 'revalid':308 'review':365,454 'rg':442,467 'right':142,399,406 'rotat':232 'runtim':137,378 'saf':290 'scenario':426,453,480 'scope':99,401 'scripts/eval_triggers.py':493 'select':215,356 'selected-photo':214,355 'separ':209 'set':184,226,300,332,391,521 'settings-bas':183 'settings-return':520 'share':105,487 'side':277 'skill':30,96,494 'skill-android-permissions-activity-results' 'source-krutikjain' 'space':170 'specif':411,464 'stabl':152 'start':112 'state':169,254,260,303,523 'storag':293,341,475 'surfac':283,435 'takepictur':449 'test':108,489 'testabl':298 'time':180,407 'topic-agent-skills' 'topic-android' 'topic-android-development' 'topic-android-skills' 'topic-androidx' 'topic-claude-code' 'topic-codex' 'topic-cursor' 'topic-jetpack-compose' 'topic-kotlin' 'topic-skills' 'treat':245,352 'ui':109,259,540 'use':6,27,28,51,370 'user':117,273 'ux':17,62 'valid':231 'version':538 'vs':74,202 'without':271 'workflow':110","prices":[{"id":"9eb8be8d-da2f-45d9-98d9-11a8195c0113","listingId":"f1f52329-b3be-4878-a639-3c59682bd36f","amountUsd":"0","unit":"free","nativeCurrency":null,"nativeAmount":null,"chain":null,"payTo":null,"paymentMethod":"skill-free","isPrimary":true,"details":{"org":"krutikJain","category":"android-agent-skills","install_from":"skills.sh"},"createdAt":"2026-05-18T13:20:51.278Z"}],"sources":[{"listingId":"f1f52329-b3be-4878-a639-3c59682bd36f","source":"github","sourceId":"krutikJain/android-agent-skills/android-permissions-activity-results","sourceUrl":"https://github.com/krutikJain/android-agent-skills/tree/main/skills/android-permissions-activity-results","isPrimary":false,"firstSeenAt":"2026-05-18T13:20:51.278Z","lastSeenAt":"2026-05-18T19:13:28.572Z"}],"details":{"listingId":"f1f52329-b3be-4878-a639-3c59682bd36f","quickStartSnippet":null,"exampleRequest":null,"exampleResponse":null,"schema":null,"openapiUrl":null,"agentsTxtUrl":null,"citations":[],"useCases":[],"bestFor":[],"notFor":[],"kindDetails":{"org":"krutikJain","slug":"android-permissions-activity-results","github":{"repo":"krutikJain/android-agent-skills","stars":8,"topics":["agent-skills","android","android-development","android-skills","androidx","claude-code","codex","cursor","jetpack-compose","kotlin","skills"],"license":"mit","html_url":"https://github.com/krutikJain/android-agent-skills","pushed_at":"2026-03-25T05:47:20Z","description":"Android skills repository for Kotlin, Compose, XML, testing, CI, release work, and legacy upgrades","skill_md_sha":"3cb298d1bea7a1b10348660a708f0a6fb9f369d3","skill_md_path":"skills/android-permissions-activity-results/SKILL.md","default_branch":"main","skill_tree_url":"https://github.com/krutikJain/android-agent-skills/tree/main/skills/android-permissions-activity-results"},"layout":"multi","source":"github","category":"android-agent-skills","frontmatter":{"name":"android-permissions-activity-results","description":"Use modern permission requests, Activity Result APIs, and capability-gated UX in Android flows."},"skills_sh_url":"https://skills.sh/krutikJain/android-agent-skills/android-permissions-activity-results"},"updatedAt":"2026-05-18T19:13:28.572Z"}}